Problems With Persistence Context Injection
p4781c Feb 3, 2006 12:02 PMI'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