myfaces-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Howard W. Smith, Jr." <smithh032...@gmail.com>
Subject Re: Migrating to CDI: @Asynchronous
Date Tue, 20 Nov 2012 19:52:05 GMT
Doh, NetBeans is probably not following the specification, because NetBeans
has squiggly line under the bean class name, and has the following as a tip:

CDI artifact is found but there is no beans.xml file.

So, to avoid this, I need to have beans.xml in WEB-INF instead of META-INF.

Per what I read in Java EE 6 tutorial (CDI) and other articles online, it
seems as though beans.xml is supposed to be placed in META-INF, if you have
JARs that you've developed that is referenced by the app. I could be saying
this incorrectly. :)


On Tue, Nov 20, 2012 at 1:57 PM, Howard W. Smith, Jr. <
smithh032772@gmail.com> wrote:

> Mark,
>
> I confirmed and 'opted' to do the same as what you mentioned below, and
> web app is working fine. I 'moved' beans.xml from WEB-INF to META-INF, and
> app is running well, and running same as when beans.xml was in WEB-INF.
> I'll keep beans.xml in META-INF as per your recommendation.
>
> *2.) I'm not using NetBeans, but it's basically the same scenario. In my
> project I opted for only using META-INF/beans.xml and completely dropping
> WEB-INF/beans.xml. This is perfectly fine as per the CDI spec [1].*
>
> Please note, (temporarily) commenting out @Asynchronous method calls in my
> app most likely resolved the issue in OP.
>
> Thanks,
> Howard
>
>
> On Tue, Nov 20, 2012 at 10:18 AM, Mark Struberg <struberg@yahoo.de> wrote:
>
>> Dropping OpenEJB as we are now back to core JSF and related. I don't want
>> to spam them ;)
>>
>> 1.): each container has pros and cons. And each of them needs different
>> workarounds in edge cases :)
>>
>>
>> 2.) I'm not using NetBeans, but it's basically the same scenario. In my
>> project I opted for only using META-INF/beans.xml and completely dropping
>> WEB-INF/beans.xml. This is perfectly fine as per the CDI spec [1].
>>
>>
>> >What is a good example or use case for using CDI events?
>>
>> Oh there are plenty! You just need to understand that CDI events !=
>> messages. CDI events are _always_ synchronous and only get delivered to
>> beans in currently active contexts.
>>
>>
>> E.g. if you fire a CDI event and have a public @SessionScoped class User
>> then only the contextual instance 'User' from the current session will
>> receive the event.
>>
>> You can think about CDI events as a method invocation where you do not
>> know on which (and how many) instances you invoke it.
>>
>>
>> A practical use case. In our application we have a big fat menu. The menu
>> content is depending on the language of the user and his privileges. Since
>> this can change on a language change or if the user logs in/out, etc most
>> apps always re-calculate the whole MenuItem tree from the database.
>>
>>
>> What we did in our application is the following: Menu is a @SessionScoped
>> cdi bean and we do NOT re-calculate the items for every request. Instead we
>> fire a UserSettingsChangedEvent on each language change and login/logout.
>> In the Menu bean (and a lot other places) we @Observes
>> UserSettingsChangedEvent and reload the menu in that case.
>>
>>
>> This performs vastly better and allows us to radically cache lots of
>> things.
>>
>>
>>
>> LieGrue,
>> strub
>>
>> [1] https://issues.jboss.org/browse/CDI-218
>>
>> >________________________________
>> > From: "Howard W. Smith, Jr." <smithh032772@gmail.com>
>> >To: MyFaces Discussion <users@myfaces.apache.org>; Mark Struberg <
>> struberg@yahoo.de>
>> >Cc: "users@openejb.apache.org" <users@openejb.apache.org>
>> >Sent: Tuesday, November 20, 2012 3:56 PM
>> >Subject: Re: Migrating to CDI: @Asynchronous
>> >
>> >
>> >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 <struberg@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." <smithh032772@gmail.com>
>> >>> To: users@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
>> >>> <rmannibucau@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. <smithh032772@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
>> >>>>  >
>> >>>>
>> >>>
>> >>
>> >
>> >
>> >
>>
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message