1 Reply Latest reply on Feb 3, 2006 12:42 PM by Richard Jones

    Problems With Persistence Context Injection

    Richard Jones Newbie

      I'm trying to create a simple web app using ejb3, jboss and the jbosside.
      The files come mainly from the persistence trailblazer. I'm trying to use a
      Mysql database in a persistence context ( and not using the jboss default datasource)
      as discussed in the TrailBlazer, found here:

      http://trailblazer.demo.jboss.com/EJB3Trail/persistence/config/index.html

      where it says:

      "It would be nice to configure the database and connections settings for each
      application or any set of entity beans. EJB 3.0 allows you do exactly via the
      concept of persistence context."


      However, no matter what I do the persistent context is,
      apparently, not injected into the slsb.

      I get the errors during deployment as follows:


      .
      .
      .
      08:21:59,515 WARN [ServiceController] Problem starting service jboss.j2ee:service=EJB3,name=org.jboss.ejb3demo.CalculatorBean
      java.lang.RuntimeException: unable to find: java:/managedEntityFactories/CalcPersistenceContext
      at org.jboss.ejb3.injection.PersistenceContextHandler.getManagedEntityManagerFactory(PersistenceContextHandler.java:85)
      at org.jboss.ejb3.injection.PersistenceContextHandler.loadFieldInjectors(PersistenceContextHandler.java:169)
      at org.jboss.ejb3.injection.PersistenceContextHandler.loadInjectors(PersistenceContextHandler.java:134)
      at org.jboss.ejb3.EJBContainer.resolveInjectors(EJBContainer.java:397)
      at org.jboss.ejb3.EJBContainer.initializePool(EJBContainer.java:330)
      at org.jboss.ejb3.EJBContainer.start(EJBContainer.java:283)
      at org.jboss.ejb3.SessionContainer.start(SessionContainer.java:48)
      at org.jboss.ejb3.stateless.StatelessContainer.start(StatelessContainer.java:63)
      at org.jboss.ejb3.stateless.StatelessManager.startService(StatelessManager.java:93)
      .
      .
      .
      at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.loop(AbstractDeploymentScanner.java:203)
      at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.run(AbstractDeploymentScanner.java:182)
      Caused by: javax.naming.NameNotFoundException: CalcPersistenceContext not bound
      at org.jnp.server.NamingServer.getBinding(NamingServer.java:514)
      at org.jnp.server.NamingServer.getBinding(NamingServer.java:522)
      at org.jnp.server.NamingServer.getObject(NamingServer.java:528)
      at org.jnp.server.NamingServer.lookup(NamingServer.java:281)



      I'm confused about how to package the files, about which dtd is valid for
      persistence.xml, persistence.xml location, the use/non-use of .par/.ear files, -ds.xml files, etc.

      My question is how do you package an EJB 3.0 project in JBoss
      that uses a persistence context, as in the code below? And, what am I
      doing wrong such that the persistent context is not being injected?

      Environment:
      Windows XP
      JBoss 4.0.3 SP1
      Java 1.5.0_05

      Here are the project files

      SLSB:
      Calculator.java
      package org.jboss.ejb3demo;
      
      import java.util.Collection;
      
      
      public interface Calculator {
      
       public void addFund (String name, double growthrate);
       public void addInvestor (String name, int start, int end);
      
       public double calculate (int fundId, int personId, double saving);
      
       public Collection<Fund> getFunds ();
       public Collection <Investor> getInvestors ();
       public Collection <TimedRecord> getRecords ();
       public Collection <TimedRecord> filterRecords (double low, double high);
       public Collection<TimedRecord> getRecordsById ();
       public void updateExchangeRate (double newrate);
      
      }
      


      CalculatorBean.java
      package org.jboss.ejb3demo;
      
      import javax.ejb.*;
      import javax.persistence.*;
      
      import java.sql.Timestamp;
      import java.util.Collection;
      import java.util.Iterator;
      
      @Stateless
      public class CalculatorBean implements Calculator {
      
       @PersistenceContext (unitName="CalcPersistenceContext")
       protected EntityManager em;
      
       public void addFund (String name, double growthrate) {
       Fund fund = new Fund (name, growthrate);
       em.persist (fund);
       }
      
       public void addInvestor (String name, int start, int end) {
       Investor investor = new Investor (name, start, end);
       em.persist (investor);
       }
      
       public double calculate (int fundId, int investorId, double saving) {
      
       Investor investor =
       em.find(Investor.class,
       Integer.valueOf(investorId));
       Fund fund =
       em.find(Fund.class,
       Integer.valueOf(fundId));
      
       int start = investor.getStartAge();
       int end = investor.getEndAge();
       double growthrate = fund.getGrowthrate();
      
       double tmp = Math.pow(1. + growthrate / 12., 12. * (end - start) + 1);
       double result = saving * 12. * (tmp - 1) / growthrate;
       Timestamp ts = new Timestamp (System.currentTimeMillis());
      
       TimedRecord rec =
       new TimedRecord (fund, investor, saving, result, ts);
       em.persist (rec);
      
       return result;
       }
      
       public Collection<Fund> getFunds () {
       return em.createQuery("from Fund f").getResultList();
       }
       public Collection <Investor> getInvestors () {
       return em.createQuery("from Investor p").getResultList();
       }
       public Collection <TimedRecord> getRecords () {
       return em.createQuery("from TimedRecord r order by r.ts desc").getResultList();
       }
       public Collection <TimedRecord> filterRecords (double low, double high) {
       return em.createQuery(
       "from TimedRecord r where r.result > :low AND r.result < :high")
       .setParameter ("low", new Double (low))
       .setParameter ("high", new Double (high))
       .getResultList();
       }
       public Collection <TimedRecord> getRecordsById () {
       return em.createQuery("from TimedRecord r order by r.id desc").getResultList();
       }
      
       public void updateExchangeRate (double newrate) {
       Collection <TimedRecord> rc = em.createQuery("from TimedRecord r").getResultList();
       for (Iterator iter = rc.iterator(); iter.hasNext();) {
       TimedRecord r = (TimedRecord) iter.next();
       r.setSaving(r.getSaving() * newrate);
       r.setResult(r.getResult() * newrate);
       }
       // em.flush();
       }
      
      }
      


      Entity Beans:

      Fund.java
      package org.jboss.ejb3demo;
      
      import javax.persistence.*;
      import java.io.Serializable;
      
      @Entity
      @Table(name = "fund")
      public class Fund implements Serializable {
       private int id;
       private String name;
       private double growthrate;
      
       public Fund () { }
      
       public Fund (String name, double growthrate) {
       this.name = name;
       this.growthrate = growthrate;
       }
      
       @Id(generate = GeneratorType.AUTO)
       public int getId () {
       return id;
       }
      
       public void setId (int id) {
       this.id = id;
       }
      
       public String getName () {
       return name;
       }
      
       public void setName (String name) {
       this.name = name;
       }
      
       public double getGrowthrate () {
       return growthrate;
       }
      
       public void setGrowthrate (double growthrate) {
       this.growthrate = growthrate;
       }
      
      }


      Investor.java
      package org.jboss.ejb3demo;
      
      import javax.persistence.*;
      import java.io.Serializable;
      
      @Entity
      @Table(name = "investor")
      public class Investor implements Serializable {
       private int id;
       private String name;
       private int startAge;
       private int endAge;
      
       public Investor () { }
      
       public Investor (String name, int startAge, int endAge) {
       this.name = name;
       this.startAge = startAge;
       this.endAge = endAge;
       }
      
       @Id(generate = GeneratorType.AUTO)
       public int getId () {
       return id;
       }
      
       public void setId (int id) {
       this.id = id;
       }
      
       public String getName () {
       return name;
       }
      
       public void setName (String name) {
       this.name = name;
       }
      
       public int getStartAge () {
       return startAge;
       }
       public void setStartAge (int startAge) {
       this.startAge = startAge;
       }
      
       public int getEndAge () {
       return endAge;
       }
       public void setEndAge (int endAge) {
       this.endAge = endAge;
       }
      
      }


      Record.java
      package org.jboss.ejb3demo;
      
      import javax.persistence.*;
      import java.io.Serializable;
      
      @Entity
      @Table(name = "record")
      @Inheritance(discriminatorValue="B")
      @DiscriminatorColumn(name="record_type")
      public class Record implements Serializable {
       protected int id;
       protected Fund fund;
       protected Investor investor;
       protected double saving;
       protected double result;
      
       public Record () { }
      
       public Record (Fund fund, Investor investor, double saving, double result) {
       this.fund = fund;
       this.investor = investor;
       this.saving = saving;
       this.result = result;
       }
      
       @Id(generate = GeneratorType.AUTO)
       public int getId () {
       return id;
       }
      
       public void setId (int id) {
       this.id = id;
       }
      
       @ManyToOne(optional=false)
       @JoinColumn(name="my_fundid")
       public Fund getFund () {
       return fund;
       }
      
       public void setFund (Fund fund) {
       this.fund = fund;
       }
      
       @ManyToOne(optional=false)
       // Use the system-specified join column
       public Investor getInvestor () {
       return investor;
       }
      
       public void setInvestor (Investor investor) {
       this.investor = investor;
       }
      
       public double getSaving () {
       return saving;
       }
      
       public void setSaving (double saving) {
       this.saving = saving;
       }
      
       public double getResult () {
       return result;
       }
      
       public void setResult (double result) {
       this.result = result;
       }
      
      }


      TimedRecord.java
      package org.jboss.ejb3demo;
      
      import javax.persistence.*;
      import java.sql.Timestamp;
      import java.io.Serializable;
      
      @Entity
      @Inheritance(discriminatorValue="T")
      public class TimedRecord extends Record
       implements Serializable {
      
       private Timestamp ts;
      
       public TimedRecord () { }
      
       public TimedRecord (Fund fund, Investor investor,
       double saving, double result,
       Timestamp ts) {
       this.fund = fund;
       this.investor = investor;
       this.saving = saving;
       this.result = result;
       this.ts = ts;
       }
      
       public Timestamp getTs () {
       return ts;
       }
      
       public void setTs (Timestamp ts) {
       this.ts = ts;
       }
      
      }


      JSP: ( I will elide these files for now, as I believe my problem is elsewhere )
      addfund.jsp
      addinvestor.jsp
      calculator.jsp
      filter.jsp
      hello.jsp
      update.jsp


      Other Files:
      web.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app version="2.4"
       xmlns="http://java.sun.com/xml/ns/j2ee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
      
      </web-app>


      persistence.xml
      <persistence>
       <persistence-unit name="CalcPersistenceContext">
       <jta-data-source>java:/MySqlDS</jta-data-source>
       <jar-file>../authors-beans.ejb3</jar-file>
       <properties>
       <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
       <property name="hibernate.hbm2ddl.auto" value="create"/>
       <property name="hibernate.connection.driver_class"
       value="com.mysql.jdbc.Driver"/>
       <property name="hibernate.connection.username"
       value="root"/>
       <property name="hibernate.connection.password"
       value="root"/>
       <property name="hibernate.connection.url"
       value="jdbc:mysql://localhost:3306/calc"/>
       <property name="hibernate.show_sql" value="true"/>
       </properties>
       </persistence-unit>
      </persistence>


      mysql-ds.xml in jbosshome/server/default/deploy (is this needed?)

      <?xml version="1.0" encoding="UTF-8"?>
      
      <!-- $Id: mysql-ds.xml,v 1.3.2.1 2004/12/01 11:46:00 schrouf Exp $ -->
      <!-- Datasource config for MySQL using 3.0.9 available from:
      http://www.mysql.com/downloads/api-jdbc-stable.html
      -->
      
      <datasources>
       <local-tx-datasource>
       <jndi-name>MySqlDS</jndi-name>
       <connection-url>jdbc:mysql://localhost:3306/calc</connection-url>
       <driver-class>com.mysql.jdbc.Driver</driver-class>
       <user-name>root</user-name>
       <password>root</password>
       <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
       <!-- sql to call when connection is created
       <new-connection-sql>some arbitrary sql</new-connection-sql>
       -->
       <!-- sql to call on an existing pooled connection when it is obtained from pool
       <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
       -->
      
       <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
       <metadata>
       <type-mapping>mySQL</type-mapping>
       </metadata>
       </local-tx-datasource>
      </datasources>


      I'm new to JBoss and EJB 3.0. I have used Hibernate in other projects. If this discussion has already been had, please give me short/terse answer letting me know where. I searched this forum and googled persistence context, but I haven't seen any definitive answer concerning my questions. One thing that has made this particularly confusing is that, given the recent release of the spec., I am not sure what I'm reading (in the forum/on the web) is for the new spec. or is out of date.

      Any help whatever is appreciated

      DJ

        • 1. Re: Problems With Persistence Context Injection
          Richard Jones Newbie

          The persistence.xml file should look like:

          <persistence>
           <persistence-unit name="CalcPersistenceContext">
           <jta-data-source>java:/MySqlDS</jta-data-source>
           <jar-file>../calc-beans.ejb3</jar-file>
           <properties>
           <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
           <property name="hibernate.hbm2ddl.auto" value="create"/>
           <property name="hibernate.connection.driver_class"
           value="com.mysql.jdbc.Driver"/>
           <property name="hibernate.connection.username"
           value="root"/>
           <property name="hibernate.connection.password"
           value="root"/>
           <property name="hibernate.connection.url"
           value="jdbc:mysql://localhost:3306/muos"/>
           <property name="hibernate.show_sql" value="true"/>
           </properties>
           </persistence-unit>
          </persistence>