Mark, Cool beans and agreed about @Asynchronous! Since I read about @Asynchronous on Stackoverflow.com (a post by David Blevins), I decided to give it a try, but I think I did read that 'asynchronous' (runnable, etc...) tasks are not all that good in web application.
So, while you were writing your reply, I was already commenting out the call to the @Asynchronous method, and I reverted to the synchronous version of the method to update Google Calendar. After adding @Asynchronous, I added some logic that works better than @Asynchronous, it will not do a google calendar update on 'every' database update; I have some strategic processing in place that brought the # of google calendar requests down by hundreds and even thousands on a daily average. You know what? I attempted to add to META-INF as well as WEB-INF (some days ago), and I already reported (in an earlier post) that that didn't allow my web app to start in TomEE (or Glassfish, if I was still using Glassfish when I reported that earlier...smile). In response to Eclipse...hopefully, no offense will be taken, i'm not a user of eclipse, I've been a user of NetBeans ever since I started developing JSF web application (since last summer, 2011), and I can be the loyal type if something or someone treats me good. I was 'loyal' to Mojarra, but then I heard about the Mojarra issues updating components via AJAX, so I migrated to MyFaces Core (when I heard MyFaces Core 2.1.7+ performs better than Mojarra), and then reading one of your posts, Mark, about OpenWebBeans performing fast, and JIRA's and many people mentioning that CDI is better than JSF managed beans, I decided to migrate to CDI, and determined to use any/all features available that is offered by CDI, like events, SSE (server sent events), push (like Atmosphere), etc... Was having trouble using Atmosphere with Glassfish, so decided to give TomEE a whirl, since you, Andy Bailey (a friend in PrimeFaces forum), and others recommended TomEE. I like all that Glassfish 'markets' (or tries to sell) to JSF developers, but I'm liking what I see and hear about TomEE, OpenWebBeans, OpenEJB, etc... What is a good example or use case for using CDI events? Thanks, Howard On Tue, Nov 20, 2012 at 9:36 AM, Mark Struberg <strub...@yahoo.de> wrote: > Hi! > > One of my first advice is to make sure that beans.xml is really there for > the container. > I've seen this pretty often if someone starts the webapp directly from > Eclipse. In that case the CDI container sometimes cannot find > WEB-INF/beans.xml as eclipse doesn't set the classpath entries correctly. > > Sometimes it helps to add a META-INF/beans.xml to the webapp classpath. > This will end up in WEB-INF/classes/META-INF/beans.xml and is perfectly > fine from a spec perspective. > > There's a 30% chance that this is your problem ;) > > For the @Asynchronous: > > In general I do not really like @Asynchronous in webapps. It's really very > seldom useful as you need to wait for the result anyway. It also doesn't > get any Session, Request or Transaction information propagated over and > it's not guaranteed to succeed. Think about what happens if an Exception > gets hit in the asynchronous bean? > > This is really only useful in 2 cases: > * fire and forget. If you don't take care if the job succeeds or not, then > you might use it. > > * spawning off multiple jobs and waiting for all of them before returning. > > Still you need to take a lot of care about error handling and similar > stuff. > > > In our big application where we really need asynchronous tasks to be > guaranteed to get executed we went the classic route which works on the > Host since the 60s: we just write the job into an own 'Tasks' table and > process it via an own Quartz job. On success, it updates the status. On > error it sets the task to a failure status and adds information about the > cause. > That way we have a failure safe and restartable implementation. > > LieGrue, > strub > > > ----- Original Message ----- > > From: "Howard W. Smith, Jr." <smithh032...@gmail.com> > > To: us...@openejb.apache.org; MyFaces Discussion < > users@myfaces.apache.org> > > Cc: > > Sent: Tuesday, November 20, 2012 3:06 PM > > Subject: Re: Migrating to CDI: @Asynchronous > > > > MyFaces Users, > > > > Please read OP (or my original email below), and then read this email, > and > > advise. > > > > Romain, > > > > Yes, I have a code snippet; please continue reading beyond/below first > code > > snippet. > > > > > > Below is the code that is called by multiple beans as well as the bean > > where this method is defined. > > > > /* > > * Is it safe to start a new thread in a JSF managed bean? > > * Look at answers by BalusC and David Blevins > > * > > > http://stackoverflow.com/questions/6149919/is-it-safe-to-start-a-new-thread-in-a-jsf-managed-bean > > * > > * Java EE 6 Tutorial Chapter 27 Using Asynchronous Method Invocation > > in Session Beans > > * http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html > > */ > > @Asynchronous > > public Future<Date> updateGoogleCalendarPostEditAsync(Date > > tripDateToBePlacedInQueue) { > > > > String log; > > > > Date tripDate = > > > usersController.queueDateAndOrUpdateGoogleCalendar(tripDateToBePlacedInQueue); > > if (tripDate == null) { > > return new AsyncResult<>(tripDate); > > } > > > > performingGoogleCalendarMaintenace = true; > > > > try { > > > > if (usersController.googleCalendarHasEvents()) { > > usersController.deleteEvents(tripDate, tripDate); > > } > > > > String tripDateFrom = > displayUtil.getDateFromDateTime(tripDate, > > false); > > String tripDateTo = displayUtil.getDateFromDateTime(tripDate, > > false); > > > > List<Orders> list = > getFacade().findAllConfirmed(tripDateFrom, > > tripDateTo, true); > > > > if (list != null) { > > for (Orders o : list) { > > > > usersController.addEventToCalendar(newGoogleCalendarEvent(o)); > > } > > } > > > > log = > "pf_OrdersController.updateGoogleCalendarPostEditAsync(): > > " + > > new DateTime(tripDate).toString("MM/dd/yyyy") + > > " processed successfully"; > > } catch (Exception e) { > > e.printStackTrace(); > > messages.addFormErrorMsg("Error updating Google Calendar", > > (e.getMessage() != null) ? e.getMessage() : ""); > > log = > "pf_OrdersController.updateGoogleCalendarPostEditAsync(): > > " + > > new DateTime(tripDate).toString("MM/dd/yyyy") + > > " processing failed due to exception"; > > } finally { > > performingGoogleCalendarMaintenace = false; > > } > > System.out.println(log); > > > > // Return our result > > return new AsyncResult<>(tripDate); > > } > > > > Below, is code where the @Asynchronous method is *called within the same > > bean*, and is not the last piece of code in the calling method. > > > > /* > > * 1. if tripDate changed, then update Google Calendar for > > original trip date > > * 2. update Google Calendar for current trip date > > */ > > if (new > > DateTime(current.getReportDateTime()).toString("MM/dd/yyyy").equals( > > new > > DateTime(tripDateBeforeEdit).toString("MM/dd/yyyy")) > > == false) { > > updateGoogleCalendarPostEditAsync(tripDateBeforeEdit); > > } > > > updateGoogleCalendarPostEditAsync(current.getReportDateTime()); > > } > > if (invokePrepareEdit) > > return prepareEdit(); > > else > > return null; > > > > Below, is code that is at the very end of a calling method and *called > > within the same bean*, so there are no concerns here. > > > > /* > > * update Google Calendar for current trip date > > */ > > > updateGoogleCalendarPostEditAsync(current.getReportDateTime()); > > return returnToBrowseOrView(); > > > > > > Below, is code that was *added to another bean*, that will call the > > *@Asynchronous > > method defined on the other bean* (ordersController). > > > > public void updateGoogleCalendar() { > > if (relatedEntityName.equals("orders")) { > > Orders order = (Orders) relatedEntityObj; > > > > > ordersController.updateGoogleCalendarPostEditAsync(order.getTripDateTime()); > > } > > } > > > > The method above, updateGoogleCalendar(), is called by code similar to > > below, which is not the last code executed in calling method. > > > > if (relatedEntityName.equals("orders")) { > > auditTrailDesc = "Updated ORDER: updated ORIGIN" + > > (originTx != null && originTx.length() > >> 0 > > ? "(" + originTx + ")" : ""); > > > > auditTrailController.createFromRelatedEntity(relatedEntityName, > > relatedEntityObj, auditTrailDesc); > > *// update Google Calendar* > > *updateGoogleCalendar();* > > } > > else if (relatedEntityName.equals("orderDriver")) { > > OrderDriver od = (OrderDriver) relatedEntityObj; > > OrderCostDetails orderCostDetails = > > od.getOrderCostDetails(); > > Orders order = new > > ArrayList<>(orderCostDetails.getOrders()).get(0); > > auditTrailDesc = "updated ORIGIN" + > > > > > > > > Thanks, > > Howard > > > > > > On Tue, Nov 20, 2012 at 2:25 AM, Romain Manni-Bucau > > <rmannibu...@gmail.com>wrote: > > > >> Hi, > >> > >> can you share any snippet of code? > >> > >> *Romain Manni-Bucau* > >> *Twitter: @rmannibucau <https://twitter.com/rmannibucau>* > >> *Blog: **http://rmannibucau.wordpress.com/*< > >> http://rmannibucau.wordpress.com/> > >> *LinkedIn: **http://fr.linkedin.com/in/rmannibucau* > >> *Github: https://github.com/rmannibucau* > >> > >> > >> > >> > >> 2012/11/20 Howard W. Smith, Jr. <smithh032...@gmail.com> > >> > >> > Prior to migrating from JSF managed to CDI (and currently in > > production), > >> > my web app is using @Asynchronous on @SessionScoped bean to push data > > to > >> > and keep Google Calendar updated with specific data from the > database. > >> > > >> > Honestly, I don't think I coded it correctly. What I mean by that, > > I > >> don't > >> > think I'm handling or capturing the return value of @Asynchronous > >> methods, > >> > and honestly, I don't know where execution is ending after some or > > most > >> of > >> > the calls to @Asynchronous methods. > >> > > >> > Currently, in production, the @Asynchronous method calls seem to be > >> working > >> > fine (production = MyFaces Core 2.1.9, JSF managed beans, Glassfish > >> > 3.1.2.2). Now that I'm migrating to TomEE/CDI, it seems as though > >> > @Asynchronous is breaking my app; of course, I don't mind > > accepting > >> > responsibility and calling it a developer error. @Asynchronous seems > > to > >> > result with the following error: > >> > > >> > Target Unreachable, identifier resolved to null > >> > > >> > I've read the following: > >> > > >> > > >> > > >> > > > http://www.andrejkoelewijn.com/wp/2010/03/05/jee-cdi-tip-target-unreachable-identifier-resolved-to-null/ > >> > > >> > > >> > > >> > > > http://stackoverflow.com/questions/4845041/target-unreachable-identifier-resolved-to-null > >> > > >> > but I have an empty beans.xml in WEB-INF and I have no JARs of my own > > (so > >> > no need to add beans.xml to META-INF, and please note, a lot of the > > xhtml > >> > pages in the app are working as designed. Also, I read something > about > >> > cyclic references (below) > >> > > >> > "injection points in one bean deployment archive cannot be > > satisfied by a > >> > bean in a separate bean archive, even when they are from libraries in > > the > >> > same module (web > >> > archive)"< > >> > > >> > > > http://java.net/jira/browse/GLASSFISH-15721?focusedCommentId=301147&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_301147 > >> > > > >> > > >> > but I'm sure that is not the cause of the error that I'm > > experiencing. > >> > > >> > So, would you all recommend me to consider CDI Events instead of > >> > @Asynchronous, both, or should I just fix @Asynchronous to work in > the > >> CDI > >> > app? > >> > > >> > Thanks, > >> > Howard > >> > > >> > > >