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
>>  >
>> 
>

Reply via email to