I got a little further now. First,
http://weblogs.java.net/blog/ss141213/archive/2005/12/dont_use_persis_1.html explains the
problem a bit - you can't use injection in Web apps, which I assume translates to Web
Services. So I used the technique listed in the blog.
This worked, eventually, after I added a couple of lines to my persistence.xml, as
suggested by the JBOSS App Server entity config documentation
(
http://docs.jboss.org/ejb3/app-server/reference/build/reference/en/html/e...).
updated persistence.xml
<persistence>
|
| <persistence-unit name="Crunch">
| <jta-data-source>java:/CrunchDS</jta-data-source>
| <properties>
| <property name="hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect"/>
| <property name="hibernate.connection.driver_class"
value="com.mysql.jdbc.Driver"/>
| <property name="hibernate.connection.url"
value="jdbc:mysql://localhost/crunch"/>
| <property name="hibernate.connection.username"
value="root"/>
| <property name="jboss.entity.manager.jndi.name"
value="java:/CrunchPersistence"/>
| <property name="jboss.entity.manager.factory.jndi.name"
value="java:/CrunchFactory"/>
| </properties>
| </persistence-unit>
| </persistence>
The two jndi related properties bound the names specified in the property to the
application so that they could be referenced an InitialContext.lookup() (see code below).
Now I can see the Session Bean retrieving the data from the database, but then it
immediately complains about some "lazy" thing:
17:11:24,689 INFO [STDOUT] Subscriber.find(): em is not null; returning subscriber for
guid = CRUNCH-DEFAULT-SUPERUSER
| 17:11:25,015 INFO [STDOUT] Subscriber name : SuperUser
| 17:11:25,015 INFO [STDOUT] Subscriber email: admin@localhost
| 17:11:25,176 ERROR [LazyInitializationException] failed to lazily initialize a
collection of role: com.cei.crunch.ejb.Subscriber.crunchroleses, no session or session was
closed
It should be noted that "crunchroleses" is a field in a generated class. The
class, com.cei.crunch.ejb.Subscriber, is generated by the reverse engineering process
provided through Hibernate in order to generate EJB code for an existing database. So
maybe there is some (yet more) additional configuration of Hibernate that needs to be
done.
My Web Services code now looks like this:
package com.cei.crunch.server.ws.SubscriberServices;
|
| import javax.ejb.*;
| import javax.jws.WebService;
| import javax.jws.WebMethod;
| import javax.jws.soap.SOAPBinding;
| import javax.persistence.*;
| import javax.naming.InitialContext;
|
| import com.cei.crunch.server.util.SubscriberUtil;
| import com.cei.crunch.ejb.Subscriber;
|
| /* Make this an EJB3 service endpoint. */
| @Stateless
| @Remote(SubscriberServices.class)
|
| /* Make this an Web Services endpoint. */
| @WebService(endpointInterface =
"com.cei.crunch.server.ws.SubscriberServices.SubscriberServicesEndpoint")
| @SOAPBinding(style = SOAPBinding.Style.RPC)
|
| /**
| * The .Crunch interface to Subscriber Services
| */
| public class SubscriberServices implements SubscriberServicesEndpoint {
|
| @WebMethod
| public Subscriber findSubscriber(String guid)
| {
| Subscriber s;
| SubscriberUtil su = new SubscriberUtil();
|
| s = su.find(guid);
| if ( s == null )
| System.out.println("su.find() returned null.");
| return s;
| }
|
| }
My Session Bean code, which is called by the Web Services code above, looks like this:
package com.cei.crunch.server.util;
|
| import javax.ejb.*;
| import javax.jws.soap.SOAPBinding;
| import javax.persistence.*;
| import javax.naming.InitialContext;
| import javax.transaction.UserTransaction;
| import javax.annotation.Resource;
|
| import com.cei.crunch.ejb.Subscriber;
|
| /* Make this an EJB3 service endpoint. */
| @Stateless
|
| /**
| * The .Crunch interface to Subscriber Services
| */
| public class SubscriberUtil implements SubscriberUtilInterface {
|
| @Resource
| private UserTransaction utx;
|
| public Subscriber find(String guid)
| {
| InitialContext ctx = null;
| EntityManager em = null;
| try {
| ctx = new InitialContext();
| em = (EntityManager) ctx.lookup("java:/CrunchPersistence");
| }
| catch (Exception e)
| {
| // throw new WebServiceException(ex);
| System.out.println("Subscriber.find(): context lookup
failure.");
| e.printStackTrace();
| return null;
| }
|
| if ( em == null )
| {
| System.out.println("Subscriber.find(): em is null; can't find
subscriber");
| return null;
| }
| else
| {
| Subscriber s = null;
| System.out.println("Subscriber.find(): em is not null; returning
subscriber for guid = " + guid);
| try {
| utx = (UserTransaction)
ctx.lookup("java:/comp/UserTransaction");
| utx.begin();
| s = em.find(Subscriber.class, guid);
| utx.commit();
| }
| catch (Exception e)
| {
| System.out.println("Subscriber.find(): find problem.");
| e.printStackTrace();
| }
| if ( s != null )
| {
| System.out.println("Subscriber name : " +
s.getFirstname());
| System.out.println("Subscriber email: " +
s.getEmailAddress());
| }
| return s;
| }
| }
|
| }
You'll note that I manually create a UserTransaction here. This is because if I
don't do this, no transaction is injected into the Session Bean by the @Resource (I
don't know why). And if I don't create the UserTransaction before referencing the
EntityManager (em), I get a null pointer exception when I do reference it.
My best guess at this is that the UserTransaction is in the wrong place - it may need to
go in the Web Services class before it calls the Session Bean. However, that's pretty
much a WAG at this point.
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4117235#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...