EJB Mapping
Hello,
I've been developing a small EJB application, using Entity Beans mapped to a MySQL DB. The problem I am facing is that the EJBs seem to be auto mapped to the DB that JBoss runs in, rather than to the DB that I want them to be connected with - the only get around I've had luck with is to run JBoss in the DB that I want Entity Beans to have access too. This is a hacky way of doing things and so I've been looking for the correct solution.
I presume it's an edit in ejb-jar.xml, or jboss-standardcmp - both of which I place references to my Entity Beans within. I tried moving the ref's from jboss-standardcmp to my mysql-ds xml file and they work fine, but still give the same issue of being mapped to the same DB.
Having looked through forums, googled and searched for files that contain DefaultDS, I cant find where this mapping is located and so would very much appreciate any help on the matter.
Many thanks,
Terry
[968 byte] By [
not_terrya] at [2007-11-26 17:31:09]

# 1
You simply want to add another datasource? Create a new file ending in .ds and place it in server/default/deploy. You can copy-paste one of the example .ds files already in the directory. Make sure you give it a unique JNDI name.- Saish
# 2
Hey,
Thanks for the reply! I have got two DS's working, and can connect to my second one normally using a Context look up and grabbing a Connection from the DS. The issue is how to tell the Entity Beans to look at that DS, as at present they seem to be looking at the default DS where JBoss runs and stores its tables/data, rather than my new second Test DS......
Hope that makes my problem more clear!
Many thanks,
Terry
# 3
Source: http://trailblazer.demo.jboss.com/EJB3Trail/persistence/config/
Injecting an EntityManager from a specific context
As we can see, the persistence.xml file in the JAR file can define multiple persistence contexts with different names. To obtain an EntityManager from a named persistence context, you just need to specify the name in the unitName attribute of the @PersistenceContext annotation. The following example injects the ejb3trail persistence context to the EntityManager.
@PersistenceContext(unitName="ejb3trail")
EntityManager em;
You can omit the unitName attribute if the following conditions are met:
* You only have one persistence context defined in the persistence.xml file in the entire application.
* You are using a scoped classloader for the application.
The second item probably needs more explanation. In a web application deployed in an EAR file, that means you need a jboss-app.xml file in the EAR file's META-INF directory. The file can specify an arbitrary name for the classloader. Here is an example:
<jboss-app>
<loader-repository>
trailblazer:app=ejb3
</loader-repository>
</jboss-app>
If you do not have a scoped classloader for the application, all the persistence contexts defined in the applications would be globally available in the entire server, and the @PersistenceContext injection look for an EntityManager in the global context as well. That allows you to use persistence context defined outside of your own application. But you also have to explicitly specify the persistence context name via the unitName attribute.
- Saish
# 4
Saish,
Thanks so much for your replies and patience! I've searched about and read up on what you've provided but am still at a loss. I'm very new to JBoss/EJBs/etc and self taught - so my knowledge has massive gaps in places. I have ejb-jar.xml only, and the various ejb classes themselves. Could you give me a little more 'idiot-proof' guideance on how to force an EJB to reference a certain database/context/ds...?
Many thanks,
Terry
# 5
You will need some kind of data access object (DAO) to interact with your JPA entities. (Alternatively, you can have your stateless session bean directly interact with your JPA entities). In any case, you will need a PersistenceContext.You probably already have this coded as:
@PersistenceContext
EntityManager em;
All you want to change is to supply the name of the JNDI data source that you defined earlier by creating a [name of data source]-ds.xml file and placing it in JBoss's /server/default/deploy directory. There are already several -ds.xml files in that directory that you can model your data source after (ideally, find the one named after your database, duplicate the file and rename it, then custom edit it). Here is the change in your code:
@PersistenceContext(unitName="myOtherDataSource")
EntityManager em;
You would therefore need to create myOtherDataSource.ds. I have included the oracle-ds.xml that ships with JBoss. You can edit it for your own settings. Make sure the JNDI name you reference in your code matches the one you use in the file. Good luck!
<datasources>
<local-tx-datasource>
<!-- THIS IS WHAT MUST MATCH THE JNDI NAME YOU USE IN YOUR EJB'S -->
<jndi-name>myOtherDataSource</jndi-name>
<connection-url>jdbc:oracle:thin:@localhost:1521:TEST</connection-url>
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
<user-name>foo</user-name>
<password>bar</password>
<valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
<metadata>
<type-mapping>Oracle9i</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>
[
- Saish
# 6
Well, not exactly the one that ships with JBoss. :^)- Saish
# 7
Saish,
You have the patience of a saint! Hehe - thanks, I understand the above and now where the reference fits in to the EJB... although have one (final I hope) question on the matter..
My current code is:
public abstract class ExampleEntityBean implements EntityBean{
private transient EntityContext ec;
.... methods
}
& it works fine, can be looked up, etc.
If I place a @PersistenceContext(unitName="xxxxxx") above it, Eclipse says it cant compile with annotations unless source level is set to 5:0?
:-S
I'm nearly there, honestly! :-) Many thanks!
Terry
# 8
Well, first of all, you have an abstract class. If you were using xdoclet and J2EE (rather than EE 5), you needed abstract classes, but no longer. Make it a concrete class by removing the abstract keywords.
In Eclipse, you have two options. You can 'globally' (at the workbench level) set the default compiler compliance to 5.0. Or, you can set the level for a specific Java project. If you want to set it globally, go to the menu -> Window -> Preferences. If you want to set it for your project, go to the menu -> Project -> Properties.
Either way, you will get a similar screen popping up. Navigate in the list on the left to 'java compiler'. (If you are using project-level settings, check the checkbox labelled 'project-specific settings', if going workbench level, this option will not be there). Regardless, once you click on 'java compiler', you should see an option to change the JDK compilation levels.
- Saish
# 9
Saish,
The comment regarding abstract scared me - I have spent a fair bit learning it this way, and it's out of date! :-)
I got Eclipse to compile with your advice, sadly it appears still to be looking in to the wrong database.
@PersistenceContext(unitName="java:TestDB")
private EntityContext ec;
java:TestDB is the ref I use when making a direct connection to the DB, pulling out that DS - so I know thats correct - and it also matches the -TestDB-ds.xml file.
If you have any other suggestions that would be fantastic - but can understand if you're sick of this now!
Terry
# 10
Remove the preceding java: and simply use the name after. - Saish
# 11
Sorry, I should of said...tried that and a combination of other ones, still no luck :-(
# 12
I may not have mentioned this, but did you also set-up your persistence.xml for the new data source?
<persistence>
<persistence-unit name="myOtherDataSource">
<jta-data-source>java:/myOtherDataSource</jta-data-source>
<properties>
</properties>
</persistence-unit>
</persistence>
- Saish
# 13
Hey there,
OK Let's try and sort this out by giving everything! :-)
I have:
My class:
public abstract class ContentBean implements EntityBean{
@PersistenceContext(unitName="TestDB")
private EntityContext ec;
public ContentBean(){ }
public Integer ejbCreate(Integer contentid) throws CreateException {
return contentid;
}
...other methods
}
* Home & Remote classes are ok.
* I've left abstract in for now, as I can't see how the rest would work - going to get this up and then move over to EJB 3.0.
XML Files:
xxx.jar/META-INF/ejb-jar.xml
<ejb-jar >
<description>EJB Examples</description>
<display-name>EJB Examples</display-name>
<enterprise-beans>
<entity>
<description>ContentView</description>
<ejb-name>ContentView</ejb-name>
<home>p.ContentHome</home>
<remote>p.ContentRemote</remote>
<ejb-class>p.ContentBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.Integer</prim-key-class>
<primkey-field>contentid</primkey-field>
<abstract-schema-name>cview</abstract-schema-name>
<reentrant>False</reentrant>
<cmp-field><field-name>contentid</field-name></cmp-field>
<cmp-field><field-name>contenttitle</field-name></cmp-field>
</entity>
</enterprise-beans>
xxx.jar/META-INF/persistence.xml ( HUGE thanks for this one matie - I found a great URL about it too at http://trailblazer.demo.jboss.com/EJB3Trail/persistence/config/ for any newbies like me reading this )
<persistence>
<persistence-unit name="TestDB">
<jta-data-source>java:/TestDB</jta-data-source>
<properties>
</properties>
</persistence-unit>
</persistence>
*I have tried combinations of TestDB and java:TestDB for the data-source
jboss/.../deploy/TestDB-ds.xml
<datasources>
<local-tx-datasource>
<jndi-name>TestDB</jndi-name>
.....[details of my other db]
</datasources>
* I can manually connect to this DB via the DS using a Context look up so believe this is ok too.
test.jsp:
javax.naming.Context ctx = new javax.naming.InitialContext();
p.ContentHome home = (p.ContentHome) javax.rmi.PortableRemoteObject.narrow(ctx.lookup("ContentView"),p.ContentHome.class);
p.ContentRemote he = home.findByPrimaryKey(new Integer( 1 ));
out.println("Hello");
out.println("Content ID: " + he.getContentid());
out.println("title: " + he.getContenttitle());
Phew! Ok that should give a full picture of what I'm doing - if you could take a look that'd be fantastic. Also; how can I give you more stars? It says I have 20 but has limited me to allocating 10!?! :-(
Thanks,
Terry
# 14
Made a breakthrough!My JBoss installation was not supporting EJB3.0, so I doubt the persis file was even being read! Now it generates lots of errors when it deploys - but at least I can work with errors! Will update soon.Terry
# 15
Phew. Glad to see you are making progress. Best of luck!- Saish
Saisha at 2007-7-21 17:05:35 >

# 16
Done! Ok the issue came down to the fact I was using a mix of concepts between EJB3 and EJB, with Remote, Home, yet also trying your presis and non abstract ideas :)
I've since learnt about @ann's and have it working in a nice test.
Thank you so much! :-D You've taught me loads and I doubt many others would have such patience. Hope everyone else who Google's and has this issue finds help.
Finally, S, please let me know how I can give you my other Duke Points. :-)
Thanks!
Terry
# 17
You are very welcome, glad I could help. I think at the top of the thread, there is an option to add/distribute Dukes. Best of luck.- Saish
Saisha at 2007-7-21 17:05:35 >
