13 Replies Latest reply on Mar 13, 2012 8:30 AM by komat

    Replacement for EntityQuery

    lukascz

      In my application that is based on Seam 2 and it's migrating to Seam 3, I use a lot the EntityQuery as a base class for all my searches. But EntityQuery is not in Seam 3. Do you have any suggestions how should I replace it with some similar component?


      Thanks, Lukas

        • 1. Re: Replacement for EntityQuery
          blabno
          • 2. Re: Replacement for EntityQuery
            blabno
            • 3. Re: Replacement for EntityQuery
              lukascz

              Looks good, thanks.


              Is this going to be integrated to Seam 3 in the future?

              • 4. Re: Replacement for EntityQuery
                blabno

                This is my private solution (actually seam2 stuff adapted to seam3) but i'm willing to contribute it.


                Vote for SEAMPERSIST-59.

                • 5. Re: Replacement for EntityQuery
                  lukascz

                  Just confirm that it's working perfectly. I didn't have to change any of my code from Seam 2. Thanks!

                  • 6. Re: Replacement for EntityQuery
                    blabno

                    If you want to learn more about the seam3-persistence-framework read this blog entry.

                    • 7. Re: Replacement for EntityQuery
                      lightguard

                      Here are a couple other ideas to look at:

                       

                      • 8. Re: Replacement for EntityQuery
                        komat

                        Hi :-)

                         

                        @Bernard Labno

                        We're somewhat porting and upgrading an old software from Seam2 to Seam3 and this seems very useful. I tried to add the dependency for your seam3-persistence-framework to our project. However, I have a problem with dependencies that are pulled in by your persistence framework and CDI.

                         

                        At Deployment time I get an DeploymentException for ambiguous dependencies:

                        WELD-001409 Ambiguous dependencies for type [ELContext] with qualifiers [@Default] at

                        injection point [[parameter 1] of [constructor] @Inject public org.jboss.seam.solder.el.Expressions(ELContext, ExpressionFactory)].

                        Possible dependencies

                        [[Producer Method [ELContext] with qualifiers [@Any @Default] declared as [[method] @Produces org.jboss.seam.solder.el.ELContextProducer.createELContext()],

                          Producer Method [ELContext] with qualifiers [@Any @Default] declared as [[method] @Produces org.jboss.solder.el.ELContextProducer.createELContext()]]]

                         

                        It turns out that the pom.xml in our project says that

                                <dependency>

                                    <groupId>org.jboss.solder</groupId>

                                    <artifactId>solder-impl</artifactId>

                                    <version>3.1.0.Final</version>

                                </dependency>

                        whereas yours wants

                                <dependency>

                                    <groupId>org.jboss.seam.solder</groupId>

                                    <artifactId>seam-solder</artifactId>

                                    <version>3.0.0.Final</version>

                                </dependency>

                         

                        Note the different versions and locations. I'm not sure how to fix this or what the correct fix could be.

                        Thanks for any hints and thanks for publishing this code !

                        • 9. Re: Replacement for EntityQuery
                          blabno

                          One thing you can do is:

                           

                          <dependency>

                              <groupId>pl.com.it-crowd</groupId>

                              <artifactId>seam3-persistence-framework</artifactId>

                                  <excludes>

                                        <exclude>

                                              <groupId>org.jboss.seam.solder</groupId>

                                             <artifactId>seam-solder</artifactId>

                                        </exclude>

                                  </excludes>

                          </dependency

                           

                          Or just upgrade to 1.0.2-SNAPSHOT which uses solder 3.1.0.Final

                          • 10. Re: Replacement for EntityQuery
                            komat

                            Thanks for the quick reply, Bernard :-) Upgrading ro 1.0.2-SNAPSHOT did the trick, but I'll keep the exclude mechanism in mind, should something similar happen again.

                            • 11. Re: Replacement for EntityQuery
                              komat

                              Hi again :-)

                               

                              Well, as your blog entry points here for questions, Bernard, I'll post one ... although the thread title seems a little too specific for this.

                              Note that I'm quite new to this stuff and this question may touch various subjects beyond the scope of the persistence framework.

                               

                              I want to do quite a simple thing: we have an entity bean "Employee" and a corresponding "EmployeeHome extends EntityHome<Employee>" bean in our app and two JSF-pages. The first has a list of all employees with a link on each entry that leads to the second page, a detailed profile of the employee. The employee's id is of type Long (we use the EntityConverter on this class somewhere else which needs the Employee-class to implement Identifiable<Long>). Now the link leading from the list to the detail page just gets an URL parameter so the detail page knows which employee to display.

                              Now my question is how to get the id correctly / elegantly into the EntityHome bean. Basically we use the approach from the seam documentation:

                               

                              <f:metadata>
                                  <!--<f:viewParam name="userIdFromSearch" value="#{employeeHome.idString}" />-->
                                  <!--<f:viewParam name="userIdFromSearch" value="#{employeeHome.instance.id}" />-->
                                  <!--<f:viewParam name="userIdFromSearch" value="#{employeeHome.idLong}" />-->
                                  <f:viewParam name="userIdFromSearch" value="#{employeeHome.id}" />
                                  <s:viewAction action="#{employeeHome.wire}"/>
                              </f:metadata>
                              

                               

                              As our EmployeeHome class extends EntityHome and therefor Home from the persistence framework, we have the methods setId() and getId() an thus the id property in EmployeeHome. But trying to use it with viewParam's value set to employeeHome.id leads to an Exception on accessing the page (the stack trace is quite large, but this seems to be the root cause - if you need more I'll happily supply it):

                               

                              org.hibernate.TypeMismatchException: Provided id of the wrong type for class de.ovsag.cooler.entity.Employee. Expected: class java.lang.Long, got class java.lang.String
                              

                               

                              That is, after some investigation, not all that surprising, as Home's setId() and getId() work with Object. So I guess seam doesn't know how to convert the parameter and just uses a String then.

                               

                               

                              The second way that looked nice to me was to use:

                               

                              <f:viewParam name="userIdFromSearch" value="#{employeeHome.instance.id}" />
                              

                               

                              This succeeds somewhat (the id is set and I can verify its value in the wire() method that starts the conversation), but apparently doesn't fetch the object belonging to the id from the database when doing a

                               

                              Employee emp = getInstance();
                              

                               

                              in the  wire() method. The getInstance() method is also from the Home superclass.

                               

                               

                              What actually works (even with type Long !) is to create a property named idLong like so and using it from the JSF-page (see commented part above):

                               

                              public void setIdLong(Long idLong) {
                                  log.info("setIdLong: " + idLong);
                                  if (idLong != null)
                                      setId(idLong);
                              }
                              
                              
                              public Long getIdLong() {
                                  log.info("getIdLong: " + getId());
                                  if (getId() != null)
                                      return (Long)getId();
                                  else
                                      return null;
                              }
                              

                               

                              But this seems rather redundant to me (I might be quite wrong from a architectural perspective though ? clean separation between model and view and stuff ?).

                               

                               

                               

                              So well ... I'd like to know the "right way" to do this, passing a type Long id through an URL parameter. If you could explain the "why" as well, it'd be awesome :-)

                               

                              Thanks,

                              Konstantin

                              • 12. Re: Replacement for EntityQuery
                                blabno

                                Konstantin,

                                 

                                You need to tell JSF to use particular converter:

                                    <f:viewParam name="userIdFromSearch" value="#{employeeHome.id}" converter="javax.faces.Long"/>

                                 

                                Don't use binding to instance attribute: #{employeeHome.instance.id} because Home uses #{home.id}, these are two different attributes.

                                • 13. Re: Replacement for EntityQuery
                                  komat

                                  Ah well, that makes sense :-) Works perfectly (and helped me with another problem as well). Thanks again, Bernard !