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. < smithh032...@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 <strub...@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." <smithh032...@gmail.com> >> >To: MyFaces Discussion <users@myfaces.apache.org>; Mark Struberg < >> strub...@yahoo.de> >> >Cc: "us...@openejb.apache.org" <us...@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 <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 >> >>>> > >> >>>> >> >>> >> >> >> > >> > >> > >> > >