1 2 3 4 5 Previous Next 63 Replies Latest reply on Dec 11, 2007 4:57 AM by pmuir Go to original post
      • 15. Re: Seam Email - IllegalStateException: No Factories configu
        pmuir

        The only reason I ask for a seam-gen based project is that it comes with a build.xml/structure I'm familiar with hence reducing the complexity for me.

        I'm not going to ask you to send your whole project through as it would takes days to understand it. I'm pretty sure (as are you I think) the problem is to do with your project structure so you could (a) strip a copy of your project removing everything that is irrelevant or (b) try to replicate in another project (e.g. a seam-gen one or the mail example).

        Sorry, I'm not telepathic (I wish I was ;)

        • 16. Re: Seam Email - IllegalStateException: No Factories configu
          pmuir

          Also, I'll see if I can replicate the problem by restructuring the mail example along the ear layout you've described above. If you could post your application.xml that would help with this :)

          • 17. Re: Seam Email - IllegalStateException: No Factories configu

            I'll try to find some time this weekend to create something similar - it isn't going to be easy. In each method call, there is typically some persistence work, some jBPM work, followed by an attempt to send the email. It will be tricky to provide a sample that does all that

            Thanks,
            Brad Smith

            • 18. Re: Seam Email - IllegalStateException: No Factories configu
              pmuir

              Just to check, you're calling Renderer.instance().render(template) from a method that has been called "directly" from JSF not via a JBPM action (or some other indirect method e.g. Events) - i.e. the render is by the method called from JSF or by a method it calls etc.

              I know there are issues calling Renderer.render() from JBPM (which I need to work through)

              • 19. Re: Seam Email - IllegalStateException: No Factories configu

                sample Render calls...

                This method is in a SFSB - user clicks a link in UI: (this one works!)

                 public String dsaProvision() {
                
                 TaskInstance task = jbpmContext.getTaskInstance(taskId.longValue());
                
                 // Update the decision
                 Contexts.getEventContext().set("accessRequest", accessRequest);
                 String result = accessRequestProvisioner.applyAccessRequestToUser();
                 if (!"success".equals(result)) {
                 log.warn("There was a problem provisioning the user from the access request.");
                 return null;
                 }
                
                 EvergreenUser accessRequestUser = QueryEPeopleUtil.findUserByUid(accessRequest.getUserId());
                 Contexts.getEventContext().set(
                 "accessRequestUser",
                 accessRequestUser
                 );
                
                 // Send an email to the user and requester of the access request to let them know the request is done
                
                 if (TerminationRequestManager.TerminationId.equals(accessRequest.getRequesterUserId())) {
                 // termination request - only notify UserManager...
                 // TODO - implement this
                 } else {
                 if (!accessRequest.getRequesterUserId().equals(accessRequest.getUserId())) {
                 Contexts.getEventContext().set(
                 "accessRequestRequestor",
                 QueryEPeopleUtil.findUserByUid(accessRequest.getRequesterUserId())
                 );
                 //mailSenderBean.sendEmailMessage(EmailTemplateType.AccessRequestCompleteRequestor.getTemplateFilePath());
                 }
                 // always notify user for whom request has been provisioned
                 mailSenderBean.sendEmailMessage(EmailTemplateType.AccessRequestCompleteUser.getTemplateFilePath());
                 }
                
                 // Signal the task to move to next process in the work flow
                 task.end("provision application");
                
                 // Force a reload of the work queue
                EventType.AccessRequestSaved.name()); Events.instance().raiseEvent(EventType.AccessRequestSaved.name());
                 return "success";
                 }
                
                


                MailSenderBean is a SLSB

                @Stateless
                @Name("mailSenderBean")
                public class MailSenderBean implements MailSender {
                
                 private Log log = LogFactory.getLog(MailSenderBean.class);
                
                 @In(required=false)
                 private EmailMessage emailMessage;
                
                 //@Resource(mappedName = "java:/Mail")
                 @In(create = true)
                 private Session mailSession;
                
                 @PersistenceContext(unitName = "accessControlDatabase")
                 private EntityManager em;
                
                 @In(create = true)
                 private Renderer renderer;
                
                 ....
                
                 public String sendEmailMessage(String templateFile) {
                 try {
                 log.info("sending email: "+templateFile);
                 renderer.render(templateFile);
                 log.info("...mailt sent(?)");
                 return "success";
                
                 } catch (Exception e) {
                 log.error(e,e);
                 }
                 return null;
                 }
                
                }
                


                The SFSB call above is succeeding; what's really confusing is that another method in the same SFSB (shown below) is failing using an almost identical execution path and context (user clicks a link in a UI, etc...)

                This method is in a SFSB - user clicks a link in UI: (this one fails!)

                 public String userManagerApproveAccessRequest() {
                 TaskInstance task = jbpmContext.getTaskInstance(taskId.longValue());
                 //Long accessRequestId = (Long) task.getContextInstance().getVariable("accessRequestId");
                
                 // Update the status to user manager approved accessRequest.setRequestStatus(AccessRequestStatus.UserManagerApproved);
                
                 // Update the decision
                 AccessRequestDecision decision = accessRequest.getUserManagerDecision();
                 decision.setDecision(AccessRequestStatus.UserManagerApproved);
                 em.merge(decision);
                 em.merge(accessRequest);
                
                 // contextual email data
                 Contexts.getEventContext().set(
                 "accessRequest",
                 accessRequest
                 );
                 Contexts.getEventContext().set(
                 "accessRequestUser",
                 QueryEPeopleUtil.findUserByUid(accessRequest.getUserId())
                 );
                 mailSender.sendEmailMessage(
                 EmailTemplateType.AccessRequestCompleteUser.getTemplateFilePath()
                 );
                 // NOTE - I'm using the same mail template for troubleshooting...
                 // Signal the task to move to next process in the work flow
                 task.end("approve");
                 // This event forces a reload of the work queue (in what component?)
                Events.instance().raiseEvent(EventType.AccessRequestSaved.name());
                 return "approve_success";
                
                 }
                
                


                if you go back in to my previous posts on this issue - you'll see, I've dumped what facelets is saying in the console log. The point of success or failure in all cases is facelets and its ability to load jars with taglibs in it. I really can't understand why the first case succeeds and the second doesn't.

                Thanks for your help!

                Brad Smith

                • 20. Re: Seam Email - IllegalStateException: No Factories configu

                  I have more data - I hacked Facelets 1.1.2 to spit out some ClassLoader info. What I found is that in one case, when calling Renderer.render(myTemplate), the Classloader is the EAR's classloader.

                  In the other case, the classloader is the war's classloader.

                  not working - ear's classloader

                  11:42:20,157 INFO com.evergreen.accesscontrol.impl.MailSenderBean -
                  Classloader funtime:Me: com.evergreen.accesscontrol.impl.MailSenderBean@62f2d1
                  My Classloader: org.jboss.mx.loading.UnifiedClassLoader3@1d52240{ url=file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859access-control-1.0.ear ,addedOrder=49}
                  My Classloader's parent: org.jboss.mx.loading.HeirarchicalLoaderRepository3$NoParentClassLoader@f579de
                  My Classloader's parent's parent: org.jboss.system.server.NoAnnotationURLClassLoader@ab95e6
                  
                  11:42:20,157 INFO com.sun.facelets.compiler.Compiler - Initializing
                  11:42:20,157 INFO com.sun.facelets.compiler.TagLibraryConfig - I am using a classloader obtained from 'Thread.currentThread().getContextClassLoader()'.
                  11:42:20,157 INFO com.sun.facelets.compiler.TagLibraryConfig - Classloader -> org.jboss.mx.loading.UnifiedClassLoader3@1d52240{ url=file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859acc
                  ess-control-1.0.ear ,addedOrder=49}
                  11:42:20,157 INFO com.sun.facelets.compiler.TagLibraryConfig - Classloader.parent -> org.jboss.mx.loading.HeirarchicalLoaderRepository3$NoParentClassLoader@f579de
                  11:42:21,017 INFO com.sun.facelets.compiler.Compiler - UILibrary.Namespace ->http://java.sun.com/jsf/facelets
                  11:42:21,017 WARN com.sun.facelets.compiler.Compiler - Missing Built-in Tag Libraries! Make sure they are included within the META-INF directory of Facelets' Jar
                  11:42:21,017 INFO com.sun.facelets.compiler.Compiler - Initialization Successful
                  
                  


                  working - war's classloader
                  11:45:35,928 INFO com.evergreen.accesscontrol.impl.MailSenderBean - sending email: mail/access-request-complete-user.xhtml
                  11:45:35,928 INFO com.evergreen.accesscontrol.impl.MailSenderBean -
                  Classloader funtime:Me: com.evergreen.accesscontrol.impl.MailSenderBean@e530d5
                  My Classloader: org.jboss.mx.loading.UnifiedClassLoader3@1d52240{ url=file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859access-control-1.0.ear ,addedOrder=49}
                  My Classloader's parent: org.jboss.mx.loading.HeirarchicalLoaderRepository3$NoParentClassLoader@f579de
                  My Classloader's parent's parent: org.jboss.system.server.NoAnnotationURLClassLoader@ab95e6
                  
                  11:45:35,928 INFO com.sun.facelets.compiler.Compiler - Initializing
                  11:45:35,928 INFO com.sun.facelets.compiler.TagLibraryConfig - I am using a classloader obtained from 'Thread.currentThread().getContextClassLoader()'.
                  11:45:35,928 INFO com.sun.facelets.compiler.TagLibraryConfig - Classloader -> WebappClassLoader
                   delegate: false
                   repositories:
                   /WEB-INF/classes/
                  ----------> Parent Classloader:
                  java.net.FactoryURLClassLoader@146eb1b
                  
                  11:45:35,928 INFO com.sun.facelets.compiler.TagLibraryConfig - Classloader.parent -> java.net.FactoryURLClassLoader@146eb1b
                  11:45:36,819 INFO com.sun.facelets.compiler.TagLibraryConfig - Added Library from: jar:file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859access-control-1.0.ear-contents/access-control-w
                  ebapp-1.0-exp.war/WEB-INF/lib/jsf-facelets-1.1.12E.jar!/META-INF/jsf-ui.taglib.xml
                  11:45:36,819 INFO com.sun.facelets.compiler.TagLibraryConfig - Added Library from: jar:file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859access-control-1.0.ear-contents/access-control-w
                  ebapp-1.0-exp.war/WEB-INF/lib/jsf-facelets-1.1.12E.jar!/META-INF/jstl-fn.taglib.xml
                  11:45:36,834 INFO com.sun.facelets.compiler.TagLibraryConfig - Added Library from: jar:file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859access-control-1.0.ear-contents/access-control-w
                  ebapp-1.0-exp.war/WEB-INF/lib/jsf-facelets-1.1.12E.jar!/META-INF/jstl-core.taglib.xml
                  11:45:36,834 INFO com.sun.facelets.compiler.TagLibraryConfig - Added Library from: jar:file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859access-control-1.0.ear-contents/access-control-w
                  ebapp-1.0-exp.war/WEB-INF/lib/jsf-facelets-1.1.12E.jar!/META-INF/jsf-html.taglib.xml
                  11:45:36,850 INFO com.sun.facelets.compiler.TagLibraryConfig - Added Library from: jar:file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859access-control-1.0.ear-contents/access-control-w
                  ebapp-1.0-exp.war/WEB-INF/lib/jboss-seam-ui-1.1.6.jar!/META-INF/seam-ui.taglib.xml
                  11:45:36,850 INFO com.sun.facelets.compiler.TagLibraryConfig - Added Library from: jar:file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859access-control-1.0.ear-contents/access-control-w
                  ebapp-1.0-exp.war/WEB-INF/lib/jboss-seam-mail-1.1.6.jar!/META-INF/seam-mail.taglib.xml
                  11:45:36,866 INFO com.sun.facelets.compiler.TagLibraryConfig - Added Library from: jar:file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp44859access-control-1.0.ear-contents/access-control-w
                  ebapp-1.0-exp.war/WEB-INF/lib/jsf-facelets-1.1.12E.jar!/META-INF/jsf-core.taglib.xml
                  11:45:36,866 INFO com.sun.facelets.compiler.Compiler - Initialization Successful
                  


                  So how is it that in one case, the ear classloader is used, in another, nearly iidentical case, the webapp's classloader is used?

                  Thanks,
                  Brad Smith

                  • 21. Re: Seam Email - IllegalStateException: No Factories configu
                    pmuir

                    This is very useful information :) I'm hoping to work on this at some point this weekend.

                    • 22. Re: Seam Email - IllegalStateException: No Factories configu

                      One last bit of info...

                      A colleague of mine suggested putting the taglibs (seam-email, seam-ui, facelets, etc...) in both the ear and the war - a hack he had to do with weblogic in the past. I tried this, now email is working!

                      Thanks,
                      Brad Smith

                      • 23. Re: Seam Email - IllegalStateException: No Factories configu
                        pmuir

                        So, to sumamrise the problem as I understand it:

                        * the FaceletsRenderer calls out to facelets to render the page (making no alteration to the classloader used)
                        * Normally the classloader used is the WebappClassLoader (it is in the examples always afaics) HOWEVER sometimes it ends up being the JBoss UCL
                        * In the example the Seam component (mailExample) is using the WebAppClassLoader (is this to do with using session beans vs java beans?)
                        * If its using the WebappClassLoader it works. If its not it doesn't
                        * The placement of jars in the ear is possibly related (but IMO probably not)

                        • 24. Re: Seam Email - IllegalStateException: No Factories configu
                          pmuir

                          And

                          * If you place everything in the ear myfaces blows up when rendering email
                          * Placing the relevant taglibs where both classloaders can get them is a workaround

                          I *think* that the FaceletsRenderer needs to make sure its using the correct classloader?

                          • 25. Re: Seam Email - IllegalStateException: No Factories configu

                             

                            I *think* that the FaceletsRenderer needs to make sure its using the correct classloader?


                            -- yes - that's what it seems like to me, I was thinking of putting another hack into Facelets to try and force it to use the classloader obtained from the ServletContext....

                            Thanks,
                            Brad Smith

                            • 26. Re: Seam Email - IllegalStateException: No Factories configu
                              pmuir

                              Brad, I've managed to replicate your problem doing this:

                              Thread.currentThread().setContextClassLoader(facesContext.getClass().getClassLoader());


                              inside FaceletsRenderer.render() (in the mail example facesContext is using the UCL).

                              I'm not sure under what circumstances the context's classloader wouldn't be WebAppClassLoader, so can you print out the classloader on entry to both the working and not-working methods (i.e. before you do anything else) and post it - I'm wondering if something is altering the classloader in your code?!

                              Thanks

                              • 27. Re: Seam Email - IllegalStateException: No Factories configu

                                Pete,

                                Here is a report on the classloader situation just before I invoke my SLSB that sends email:

                                15:15:36,972 INFO [WorkItemManagerBean]
                                Just before asking my SLSB to send email using Seam Renderer...
                                15:15:36,972 INFO [WorkItemManagerBean] me -> com.evergreen.accesscontrol.impl.WorkItemManagerBean
                                15:15:36,987 INFO [WorkItemManagerBean] my classloader -> org.jboss.mx.loading.UnifiedClassLoader3@112bd54{ url=file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp20053access-co
                                ntrol-1.0.ear ,addedOrder=44}
                                15:15:36,987 INFO [WorkItemManagerBean] my classloader's parent -> org.jboss.mx.loading.HeirarchicalLoaderRepository3$NoParentClassLoader@189346e
                                
                                15:15:37,534 INFO [MailSenderBean] sending email: mail/access-request-user-manager-rejected.xhtml
                                


                                In this first case above, the mail typically fails because Facelets is trying to load taglibs via the EAR's class loader - facelets is (was) packaged in the war - the ear classloader can't see down into the war so the attempt to find the taglibs fails. For now, I've put the facelets (and other) jars in both the ear and the war - the emails are going out, but there are still some issues with some of the libraries.

                                In this next case, the emails were going out, in one of my previous posts, this is the case where I discovered that when facelets gets invoked, it is correctly(?) using the webapp classloader to hunt for taglibs. Here is the classloader report for the bean that calls my SLSB mailsender:

                                Just before asking my SLSB to send email using Seam Renderer...
                                15:20:35,206 INFO [WorkItemManagerBean] me -> com.evergreen.accesscontrol.impl.WorkItemManagerBean
                                15:20:35,206 INFO [WorkItemManagerBean] my classloader -> org.jboss.mx.loading.UnifiedClassLoader3@112bd54{ url=file:/C:/jboss-4.0.4.EJB.3RC8/server/default/tmp/deploy/tmp20053access-co
                                ntrol-1.0.ear ,addedOrder=44}
                                15:20:35,206 INFO [WorkItemManagerBean] my classloader's parent -> org.jboss.mx.loading.HeirarchicalLoaderRepository3$NoParentClassLoader@189346e
                                
                                15:20:35,206 INFO [WorkItemManagerBean] Notifying requested
                                15:20:35,206 INFO [WorkItemManagerBean] dsaProvision() - about to send email...
                                15:20:35,206 INFO [MailSenderBean] sending email: mail/access-request-complete-user.xhtml
                                


                                this data may not be too helpful as to me, it looks like that at the starting point, both method calls occur within the scope the same classloader....

                                looking at your classloader code in the previous post, I would thing you'ld want to do something like:

                                facesContext.getExternalContext().getClass().getClassLoader()
                                


                                instead because, for example, in my case, the myfaces jars are packaged in the ear. However the external context is supposed to return a ServletContext or PortletContext - I assume that the Servlet/Portlet contexts use the webapp classloader...?

                                I appreciate your looking into this!

                                Thanks,
                                Brad Smith

                                • 28. Re: Seam Email - IllegalStateException: No Factories configu
                                  pmuir

                                   

                                  "bsmithjj" wrote:
                                  Pete,

                                  Here is a report on the classloader situation just before I invoke my SLSB that sends email:


                                  Sorry, I meant on entry to the method called by JSF (i.e. is something changing your classloader between JSF calling the action method and you calling the MailSenderBean) or is the action method being called with the UCL as the class loader? Something like:

                                  public String dsaProvision() {
                                   System.out.println(this.getClass().getClassLoader());
                                   // rest of the method


                                  public String userManagerApproveAccessRequest() {
                                   System.out.println(this.getClass().getClassLoader());
                                   // rest of the method


                                  For me (at least in the mail example where I'm working on this) at the entry to a send method (called directly by JSF) the classloader is WebAppClassLoader, whether it's a Seam managed JavaBean or a SLSB.

                                  For now, I've put the facelets (and other) jars in both the ear and the war - the emails are going out, but there are still some issues with some of the libraries.


                                  Sure, but this strikes me as a hack that could come back and bite you later on...

                                  I assume that the Servlet/Portlet contexts use the webapp classloader...?


                                  On testing this I found that facesContext, externalContext and externalContext.response all were using the UCL not the WebAppClassLoader (which was unexpected).

                                  Perhaps the UCL is getting used because myfaces is in the ear, not in a jsf-libs/the war?

                                  Lets see which classloader is getting for calling your methods, and I'll check some more examples/projects and see whether its always the WebAppClassLoader or whether it can be the UCL. I suspect we need someone who actually knows about JBoss and it's classloaders at this point though (I *certainly* don't :( ).

                                  • 29. Re: Seam Email - IllegalStateException: No Factories configu

                                    These methods are not called by JSF - rather, they are the points at which I invoke my MailSenderBean.sendEmailMessage() method. In both (all) cases, I put some objects in event scope (for rendering) and invoke sendEmailMessage(). Here's the code for one invokation:

                                     // contextual email data
                                     Contexts.getEventContext().set(
                                     "accessRequest",
                                     accessRequest
                                     );
                                     Contexts.getEventContext().set(
                                     "accessRequestUser",
                                     QueryEPeopleUtil.findUserByUid(accessRequest.getUserId())
                                     );
                                     mailSender.sendEmailMessage(
                                     EmailTemplateType.UserManagerRejectedRequest.getTemplateFilePath()
                                     );
                                    


                                    Here is the relevant portions of MailSenderBean:

                                    @Stateless
                                    @Name("mailSenderBean")
                                    public class MailSenderBean implements MailSender {
                                    
                                     private Log log = LogFactory.getLog(MailSenderBean.class);
                                    
                                     @In(required=false)
                                     private EmailMessage emailMessage;
                                    
                                     @In(create = true)
                                     private Session mailSession;
                                    
                                     @PersistenceContext(unitName = "accessControlDatabase")
                                     private EntityManager em;
                                    
                                     @In(create = true)
                                     private Renderer renderer;
                                    
                                     ....
                                    
                                     public String sendEmailMessage(String templateFile) {
                                     try {
                                     log.info("sending email: "+templateFile);
                                     renderer.render(templateFile);
                                     log.info("...mailt sent(?)");
                                     return "success";
                                    
                                     } catch (Exception e) {
                                     log.error(e,e);
                                     }
                                     return null;
                                     }
                                    
                                    }
                                    


                                    The only other thing I could do is dump the classloaders from a factory method that supplieds a 'mailConfiguration' object during rendering of the email - I tried this, but since the factory method is an SLSB method, both calls show the same classloader - the EAR classloader.