1 2 Previous Next 19 Replies Latest reply on Sep 26, 2006 4:16 AM by bfo81

    Seam component as converter with EntityManager/PersistenceCo

      Hi All

      Is there any way of injecting a entitymanager into a converter class.

      My example code is :

      @Name("ContractConverter")
      @Scope(ScopeType.EVENT)
      @Intercept(InterceptionType.ALWAYS)
      public class ContractConverter2 extends LookupConverter<Contract> {
      
       @In(create=true)
       EntityManager em;
      
       public ContractConverter2(Class<Contract> entityClass) {
       super(entityClass);
       }
      
       public ContractConverter2()
       {
       super(Contract.class);
       }
      
       /**
       * Fetches the contract object direct from the database each time it is selected
       */
       public Object getAsObject (FacesContext context, UIComponent component, String value){
       return (Object)(Contract)em.find(Contract.class, value);
       }
      }


      Everything works except that em is null when getAsObject() is called.

      I am trying to generalise the SelectItems lookup so that a hashmap in the application/session context is not the only way of doing it.

      Thanks for any of your help.

      James

        • 1. Re: Seam component as converter with EntityManager/Persisten
          gavin.king

          That code looks ok to me. Should work.

          You do need to have a seam-managed persistence context named "em", however. Probably you have not got that configured, or it has a different name....

          • 2. Re: Seam component as converter with EntityManager/Persisten

            Hi Gavin

            Unfortuneatly I know the EntityManager em (Factory) exists as I can see it being deployed, and it is used in many other places in my application.

            I thought the problem could be in one of two areas:

            1. I have an ejb3 and a war packaged inside an ear. Obviously the converter is being called from within the war, is it possible to instantiate a seam component in the war file. I know that I had classpath issues (with converters) (to resolve this I created a ejbclient.jar which is imported into the war). I imagine it could be using the class file from the jar rather than the ejb3? I am also using RepositoryLocatorURL = local for my deployments.

            2. Could it be that seam components are not injected by the time it gets the conversion phase in the jsf lifecycle?

            Now I have written it down, I imagine it is more likely to be 1.

            How have other people got round seam component type jsf converters and classpath issues between ejb3 and war deployements.

            Many thanks,

            James

            • 3. Re: Seam component as converter with EntityManager/Persisten
              gavin.king

              Which JSF phase are converters called in? Apply request values, right? So it should not be a problem. AFTER_RESTORE_VIEW is the default Seam interception type, and conversational components are available from the end of the restore view phase.

              • 4. Re: Seam component as converter with EntityManager/Persisten

                After further reading, the problem probably lies in the method that jsf uses to create/lookup the Converter class.

                With variables Seam is able to plug-in a SeamVariableResolver which allows Seam to intercept the call to Seam components and do the appropriate actions. However on a converter object, myfaces/jsf has an internal hashmap of converters that it looks up in via the converterid (which it creates at deployement time).

                This means Seam does not have an opportunity to manage the instantiation of the Converter object, and therefore @In(create=true) EntityManager em; does not work.

                Therefore the only way of fetching seam components or the persistence context would be to use a manual referencing technique, byassing the seam framework. This should not be a problem architecturaly if it is pratical.

                If anyone has anything to correct/clarify please chip in.

                Thanks,

                James

                • 5. Re: Seam component as converter with EntityManager/Persisten
                  gavin.king

                  So what happens if you do:

                  Component.getInstance("em", true);

                  • 6. Re: Seam component as converter with EntityManager/Persisten

                    Hi

                    Worked like a treat.

                    /**
                     * Fetches the contract object direct from the database each time it is selected
                     */
                     public Object getAsObject (FacesContext context, UIComponent component, String value){
                     log.debug("getAsObject: Called with value = " + value);
                    
                     // Fetch the entity manager from the one managed in seam.
                     EntityManager em = (EntityManager)Component.getInstance("em", true);
                     return (Object)(Contract)em.find(Contract.class, Long.valueOf(value).longValue());
                     }
                    


                    Thanks for the help.

                    Thinking about the reverse engineering tool, it would be possible to automatically generate the different converters as long as each entity had a @Id and a field that could be used as the name element (the tricky part).

                    As far as extending seam with further annotations, I will have to think about this further (i.e. how the converter could be generalised further, to lookup any type of entity, rather than converter per entity type). Allow possibly the converters could be created and cached at seam scanner time for each entity component that had @Selectable annotation?, this scanner task would also need to dynamically register the converters with jsf/myfaces which I believe is possible using the myfaces Application class (don't know about the RI implementation).

                    The entity class annotated with @Selectable would have to have an @Id attribute and a attribute annotated with something like @SelectionName for the displayed name of the object in the selectItems. I don't know if it possible to pass in the function that you want to use dynamically to a function, but if it is then its a possibility?

                    Just thoughts currently.

                    James

                    • 7. Re: Seam component as converter with EntityManager/Persisten

                      Hi All

                      added note with performing conversion in this manner. Myfaces uses the equals comparator of the converted object to validate that it is the same as the original field value, as the converted value is a new object fetched from the database, this allways fails, and produces a validation error.

                      So make sure that any object you use in this manner has a user defined equals comparator.

                      Thanks,

                      James

                      • 8. Re: Seam component as converter with EntityManager/Persisten
                        paper

                        Just a Question relatetd to using a Seam component as converter:
                        If I'm doin so, do I also have to put the following part to my config?

                        Greetings
                        Dennis

                        <converter>
                         <converter-id>StateConverter</converter-id>
                         <converter-class>
                         org.termtimer.controller.StateConverter
                         </converter-class>
                         </converter>




                        • 9. Re: Seam component as converter with EntityManager/Persisten
                          cesarizurieta

                          You can use your converter like this:

                          <h:selectOneMenu id="s" value="#{usuarioSesion.sexo}"
                           converter="#{enumTypeConverter}">
                           <f:selectItems value="#{items.itemsSexo}" />
                          </h:selectOneMenu>


                          Where enumTypeConverter is the seam component name.

                          • 10. Re: Seam component as converter with EntityManager/Persisten
                            paper

                            Thanks for help!
                            Figured out a solution thats perfect for my app, you can find the Code here:
                            http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3925444#3925444

                            Dennis

                            • 11. Re: Seam component as converter with EntityManager/Persisten
                              jboss-nth-fan

                              Hello,

                              Got same problem, tried same approach,
                              but I still get a null instance of EntityManager after adding getInstance to the getAsObject method in the custom converter:

                              Component.getInstance("em", true);


                              Questions:
                              1. Is it that I need to declare the Seam Managed bean "em" somewhere else for this to be referenced ?
                              2. Do I need to declare this class as SLSB to be able to use the EntityManager instance?


                              This is the custom converter class : (same as original posting)

                              ....
                              @Name("MyCustomConverter")
                              @Scope(ScopeType.EVENT)
                              @Intercept(InterceptionType.ALWAYS)
                              public class MyCustomConverted implements Converter
                               @In(create=true)
                               EntityManager em;
                               ....
                              


                              Could you please provide any directions, hints or ideas ?

                              Thanks !


                              "js8523" wrote:
                              Hi

                              Worked like a treat.

                              /**
                               * Fetches the contract object direct from the database each time it is selected
                               */
                               public Object getAsObject (FacesContext context, UIComponent component, String value){
                               log.debug("getAsObject: Called with value = " + value);
                              
                               // Fetch the entity manager from the one managed in seam.
                               EntityManager em = (EntityManager)Component.getInstance("em", true);
                               return (Object)(Contract)em.find(Contract.class, Long.valueOf(value).longValue());
                               }
                              


                              Thanks for the help.

                              Thinking about the reverse engineering tool, it would be possible to automatically generate the different converters as long as each entity had a @Id and a field that could be used as the name element (the tricky part).

                              As far as extending seam with further annotations, I will have to think about this further (i.e. how the converter could be generalised further, to lookup any type of entity, rather than converter per entity type). Allow possibly the converters could be created and cached at seam scanner time for each entity component that had @Selectable annotation?, this scanner task would also need to dynamically register the converters with jsf/myfaces which I believe is possible using the myfaces Application class (don't know about the RI implementation).

                              The entity class annotated with @Selectable would have to have an @Id attribute and a attribute annotated with something like @SelectionName for the displayed name of the object in the selectItems. I don't know if it possible to pass in the function that you want to use dynamically to a function, but if it is then its a possibility?

                              Just thoughts currently.

                              James



                              • 12. Re: Seam component as converter with EntityManager/Persisten

                                Have a look at my post on a different matter.

                                http://www.jboss.com/index.html?module=bb&op=viewtopic&t=85986

                                I was using an inner class like in the DVD Store example and passing the entitymanager to the constructor.

                                I used @PersistenceContext to inject the EntityManager into the SLSB.

                                • 13. Re: Seam component as converter with EntityManager/Persisten
                                  jboss-nth-fan

                                  Works great ! Thanks for the reference to the example !


                                  "supernovasoftware.com" wrote:
                                  Have a look at my post on a different matter.

                                  http://www.jboss.com/index.html?module=bb&op=viewtopic&t=85986

                                  I was using an inner class like in the DVD Store example and passing the entitymanager to the constructor.

                                  I used @PersistenceContext to inject the EntityManager into the SLSB.


                                  • 14. Re: Seam component as converter with EntityManager/Persisten

                                     

                                    "gavin.king@jboss.com" wrote:
                                    You do need to have a seam-managed persistence context named "em", however. Probably you have not got that configured, or it has a different name....


                                    How is this done? Is it different than any other seam managed object?

                                    1 2 Previous Next