10 Replies Latest reply on Jan 14, 2013 1:42 AM by nickarls

    How to initialize JpaTemplate through Constructor with EntityManager.

    samwun9988

      Hi, with JBOSS 7.1.1 Final and Hibernate 3.5 (for lucuene Search), I created an ejb module with the following Facade object and its interface:

       

       

      Facade class:

      @Stateless(name = "MyisamProductArticleFacade")

      @Local(value = MyisamProductArticleFacadeLocal.class)

      @Transactional

      public class MyisamProductArticleFacade implements MyisamProductArticleFacadeLocal {

          private static final Logger logger = Logger.getLogger(MyisamProductArticleFacade.class);

         

          @PersistenceContext(unitName = "ForestSurfPU")

          private EntityManager em;

       

       

          JpaTemplate jpaTemplate;

       

       

          public MyisamProductArticleFacade() {

          }

       

       

          /**

           *

           * @param entityManagerFactory

           */

          @Autowired

          public MyisamProductArticleFacade(EntityManagerFactory entityManagerFactory) {

                  this.jpaTemplate = new JpaTemplate(entityManagerFactory);

          }

       

       

          protected EntityManager getEntityManager() {

              return em;

          }

       

      @Override

          public List<MyisamProductArticle> search(final String queryString) {

                  final String[] fields = new String[]{"header", "a_desc"}; // search on these fields

                 return (List) this.jpaTemplate.execute(new JpaCallback() {  // this.jpaTempalte is null.

                          @Override

                          public Object doInJpa(EntityManager em) throws PersistenceException {

                                  List<MyisamProductArticle> results = new ArrayList<MyisamProductArticle>();

                                  try {

                                          FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);

                                          org.apache.lucene.analysis.standard.StandardAnalyzer

                                                  standardAnalyzer = new org.apache.lucene.analysis.standard.StandardAnalyzer(Version.LUCENE_35);

                                          MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_35, fields, standardAnalyzer);

                                          org.apache.lucene.search.Query query = parser.parse(queryString);

                                          FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(query, MyisamProductArticle.class);

                                          results = fullTextQuery.getResultList();

                                  }

                                  catch (Exception e) {

                                          throw new PersistenceException(e);

                                  }

                                  return results;

                          }

                  });

          }

       

       

      Facacde interface:

       

       

      @Local

      public interface MyisamProductArticleFacadeLocal {

       

       

         public List<MyisamProductArticle> search(String queryString);

      }

       

       

      But I ecounted the following exception when executing method search:

       

       

      Caused by: java.lang.NullPointerException

              at ForestSurf.entity.facade.MyisamProductArticleFacade.search(MyisamProductArticleFacade.java:81) [ForestSurf-ejb-1.0.jar:]

              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_07]

       

       

      But this.jpaTemplate is not being initialised in the constructor, which is still null here.

       

      Is there anyway initilize the Facade object with constructor when the ejb project is loaded or somehow invoke this initialisation?

       

      Any suggestion is very appreciated.

      Thanks

      Sam

        • 1. Re: How to initialize JpaTemplate through Constructor with EntityManager.
          nickarls

          Tried a @PostConstruct?

          • 2. Re: How to initialize JpaTemplate through Constructor with EntityManager.
            samwun9988

            I can't make @PostConstruct work for this constructor. It is not a springframework annotation.

            How can I instruct spring mvc to initialise it?

            I thought the following code will do:

             

             

            @Autowired

                public MyisamProductArticleFacade(EntityManagerFactory entityManagerFactory) {

                        this.jpaTemplate = new JpaTemplate(entityManagerFactory);

                }

             

             

            but it doesn't get executed by spring.

             

            Thanks

            Sam

            • 3. Re: How to initialize JpaTemplate through Constructor with EntityManager.
              samwun9988

              I found an example have the entityManagerFactory written in an ApplicationContext.xml file:

               

               

               

              <?xml version="1.0" encoding="UTF-8"?>

              <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

               

               

                  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

                      <property name="driverClassName" value="${jdbc.driverClassName}"/>

                      <property name="url" value="${jdbc.url}"/>

                      <property name="username" value="${jdbc.username}"/>

                      <property name="password" value="${jdbc.password}"/>

                      <property name="initialSize" value="5"/>

                      <property name="maxActive" value="10"/>

                      <property name="maxIdle" value="10"/>

                      <property name="maxWait" value="1000"/>

                      <property name="defaultAutoCommit" value="false"/>

                  </bean>

               

               

                <!-- Spring-enabled container-managed JPA without any EJB container -->

                  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

                      <property name="dataSource" ref="dataSource"/>

                <property name="persistenceUnitName" value="dbschema"/>       

                <property  name="jpaVendorAdapter">

                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

                <property name="showSql" value="true"/>

                <property name="generateDdl" value="true"/>

                <property name="database" value="MYSQL"/> <!-- dialect -->

                </bean>

                </property>

               

                <!--

                <property name="loadTimeWeaver">

                <bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver"/>

                </property>

                -->

                  </bean>

               

               

                <!-- needed for Local JDBC Transaction -->

                <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>

               

               

                  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

                      <property name="entityManagerFactory" ref="entityManagerFactory"/>

                      <property name="jpaDialect" ref="jpaDialect"/>

                  </bean>

               

               

              </beans>

               

               

              But my ejb project is using a persistence.xml file.

              How do I tell my ejb project to inject entityManagerFactory?

               

              Thanks

              Sam

              • 4. Re: How to initialize JpaTemplate through Constructor with EntityManager.
                nickarls

                I'm no Spring user,  but isn't @Stateless and @PersistenceContext standard EE annotations? Spring doesn't create the EJB:s themself, does it? Why doesn't @PostConstruct fire?

                • 5. Re: How to initialize JpaTemplate through Constructor with EntityManager.
                  samwun9988

                  With @PostConstruct, I got this error:

                   

                  annotation type not applicable to this kind of declaration

                   

                  Here is the constructor:

                   

                  @PostConstruct

                      public MyisamProductArticleFacade(EntityManagerFactory entityManagerFactory) {

                              this.jpaTemplate = new JpaTemplate(entityManagerFactory);

                      }

                   

                  Thanks

                  Sam

                  • 6. Re: How to initialize JpaTemplate through Constructor with EntityManager.
                    nickarls

                    Try just

                     

                    @PersistenceUnit

                    EntityManagerFactory emf;

                     

                    @PostConstruct

                    public init() {

                      jpaTemplate = ...

                    }

                    1 of 1 people found this helpful
                    • 7. Re: How to initialize JpaTemplate through Constructor with EntityManager.
                      samwun9988

                      Thank you for you for the suggestion. This has got rid of the exception.

                      The issue is the Hibernate Lucene Search does not return any result.

                       

                      Here is the search function in the Facade class:

                       

                       

                      @Override

                          public List<MyisamProductArticle> search(final String queryString) {

                                  final String[] fields = new String[]{"header", "a_desc"}; // search on these fields

                                  return (List) this.jpaTemplate.execute(new JpaCallback() {

                                          @Override

                                          public Object doInJpa(EntityManager em) throws PersistenceException {

                                                  List<MyisamProductArticle> results = new ArrayList<MyisamProductArticle>();

                                                  try {

                                                          FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);

                                                          org.apache.lucene.analysis.standard.StandardAnalyzer

                                                                  standardAnalyzer = new org.apache.lucene.analysis.standard.StandardAnalyzer(Version.LUCENE_35);

                                                          MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_35, fields, standardAnalyzer);

                      //                                    parser.setDefaultOperator(QueryParser.AND_OPERATOR); // overrides the default OR_OPERATOR, so that all words in the search are required

                                                          org.apache.lucene.search.Query query = parser.parse(queryString);

                                                          FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(query, MyisamProductArticle.class);

                                                          results = fullTextQuery.getResultList();

                                                  }

                                                  catch (Exception e) {

                                                          throw new PersistenceException(e);

                                                  }

                                                  return results;

                                          }

                                  });

                          }

                       

                       

                      Thanks

                      Sam

                      • 8. Re: How to initialize JpaTemplate through Constructor with EntityManager.
                        samwun9988

                        This is the indexes of the database table of mysql:

                         

                         

                        mysql> show index from myisam_product_article;

                        +------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

                        | Table                  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

                        +------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

                        | myisam_product_article |          0 | PRIMARY  |            1 | article_id  | A         |           1 |     NULL | NULL   |      | BTREE      |         |               |

                        | myisam_product_article |          1 | a_desc   |            1 | a_desc      | NULL      |        NULL |     NULL | NULL   | YES  | FULLTEXT   |         |               |

                        | myisam_product_article |          1 | a_desc   |            2 | header      | NULL      |        NULL |     NULL | NULL   | YES  | FULLTEXT   |         |               |

                        +------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

                        3 rows in set (0.00 sec)

                         

                        • 9. Re: How to initialize JpaTemplate through Constructor with EntityManager.
                          samwun9988

                          For reference, here is my MyisamProductArticle class:

                           

                           

                          @Indexed

                          @Analyzer(impl = org.apache.lucene.analysis.standard.StandardAnalyzer.class)

                          public class MyisamProductArticle implements Serializable {

                              private static final long serialVersionUID = 1L;

                              @Id

                              @Basic(optional = false)

                              @DocumentId

                              @NotNull

                              @Column(name = "article_id")

                              private Integer articleId;

                              @Basic(optional = false)

                              @NotNull

                              @Column(name = "product_id")

                              private int productId;

                              @Lob

                              @Size(max = 65535)

                              @Column(name = "a_desc")

                              // This annotation tells that this field has to be indexed and also analyzed (break the long sentence and ignore common words), store tells if this field

                              // will be part of Index, by Store.Yes it means it will be part of Index, so that query will be faster, downside is that size of Index increases

                              @Field(index = Index.YES, analyze = Analyze.YES, store = Store.YES)

                              private String aDesc;

                              @Size(max = 64)

                              @Column(name = "header")

                              // This annotation tells that this field has to be indexed and also analyzed (break the long sentence and ignore common words), store tells if this field

                              // will be part of Index, by Store.Yes it means it will be part of Index, so that query will be faster, downside is that size of Index increases

                              @Field(index = Index.YES, analyze = Analyze.YES, store = Store.YES)

                              private String header;

                           

                          • 10. Re: How to initialize JpaTemplate through Constructor with EntityManager.
                            nickarls

                            I think you will have more luck at the Lucene forum end (unless you can point some finger back at the AS)