How to get Websphere to prompt for a database JNDI connection - jpa

I have an EAR application, containing an EJB and a WAR.
In the EJB I am using JPA to connect to the database, and then the WAR deals with the REST endpoints and calls methods defined in the EJB:
e.g - EJB Stateless Bean:
#PersistenceContext
private EntityManager em;
and EJB persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="WOTISEJB">
<jta-data-source>java:comp/env/jdbc/appds</jta-data-source>
<class>com...</class>
</persistence-unit>
</persistence>
Web class:
#Path("/getByType")
#ManagedBean
public class GetByTypeResource
{
#EJB
EjbDao ejbDao;
#GET
#Produces(MediaType.APPLICATION_JSON)
public String getData(#Context HttpServletRequest request, #PathParam("type") Type type)
{
JsonObject response = ejbDao.getByType(type);
StringWriter sw = new StringWriter();
try (JsonWriter jw = Json.createWriter(sw)) {
jw.write(response);
}
String retVal = sw.toString();
return retVal;
}
}
I presume I don't need anything in my web.xml as all of the EntityManager definitions are in the EJB code (and just called from the WEB application) - but just in case it's relevant:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>appname</servlet-name>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.app.ApplicationConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appname</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<display-name>App Name</display-name>
</web-app>
When I install the application onto Websphere 9.0.5, I was expecting to be prompted as part of the installation to map the jndi name java:comp/env/jdbc/appds to the JDBC datasource I have already created in the console; however it is just using the default datasource in WAS instead.
What configuration elements am I missing to get the installation process to prompt me for the DSN mapping? In order words I don't want to put the jbdc name directly in the config, but have an indirect lookup which is configured on deploy.
Additionally, am I missing any configuration in my web.xml so that it also knows about the DSN when it calls the methods on the EJB classes, or will that happen automatically?

Related

Spring MVC REST nohandler error

Im new to spring MVC and REST.. I'm having an issue with a simple test controller I've put together from example I've found here and from the spring docs..
When I hit the url http://localhost:8080/test-api/user/14 I get the error below
Im getting the error:
Sep 23, 2015 11:26:55 AM org.springframework.web.servlet.PageNotFound noHandlerFound
WARNING: No mapping found for HTTP request with URI [/test-api/user/14] in DispatcherServlet with name 'testapi'
Im using xml to config.. Im not ready to move to java config.
web.xml
Spring Web MVC Application
<servlet>
<servlet-name>springtest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springtest</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/testapi-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
testapi-servlet.xml - only contains the component scan and annotation driven elements
<context:component-scan base-package="com.springtest.testapi" />
<mvc:annotation-driven />
SpringTest.java
package com.springtest.testapi.api;
#RestController
public class SpringTest {
#RequestMapping(value="/user/{id}", method = RequestMethod.GET)
public User getUser(#PathVariable int id) {
User u = new User(id,"Test","Me");
return u;
}
What handler should I be defining.. None of the examples or docs state that a handler needs to be defined..
Remove the contextConfigLocation.
Replace the following:
<servlet-mapping>
<servlet-name>springtest</servlet-name>
<url-pattern>/test-api</url-pattern>
</servlet-mapping>
Make sure your xml file is test-api-servlet.xml and not testapi-servlet.xml
I found my issue. I mispelled the package in the component scan. The sample code I have was edited so It didn't fully represent what I had and was actually correct.

Cannot create JDBC driver of class '' for connect URL 'null" - HikariCP, Tomcat8, PostgreSQL

Firstly I have never setup a JDBC Pool before (So i am sorry if this seems mundane). I have been trying for some time to solve the problem but to no avail. I have explored the suggested options from various other stackoverflow posts but none have been successful.
I have tried:
Including the 'pgjdbc-ng' driver only in the /lib of tomcat and moving the context to the catalina home conf/
Swapping to using the example given by Hikari (but received same error) https://github.com/brettwooldridge/HikariCP/wiki/JNDI-DataSource-Factory-(Tomcat,-etc.)
I am using HikariCP with a PostgreSQL(pgjdbc-ng) driver. Tomcat8 deploys my war file which i build using maven. web.xml, context.xml, java code.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>Restful Web Application</display-name>
<resource-ref>
<res-ref-name>jdbc/postgresHikari</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.seng402.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/postgresHikari" auth="Container"
factory="com.zaxxer.hikari.HikariJNDIFactory"
type="javax.sql.DataSource"
minimumIdle="5"
maximumPoolSize="10"
connectionTimeout="300000"
dataSource.implicitCachingEnabled="true"
dataSource.user="docker"
dataSource.password="docker"
jdbcUrl="jdbc:postgresql://192.168.59.103:5432/docker"
driverClassName="com.impossibl.postgres.jdbc.PGDataSource"/>
</Context>
java code
Context initCtx = null;
try {
initCtx = new InitialContext();
Context envCtx;
try {
envCtx = (Context) initCtx.lookup("java:comp/env");
// Look up our data source
DataSource ds = (DataSource) envCtx.lookup("jdbc/postgresHikari");
try {
// Allocate and use a connection from the pool
Connection conn = ds.getConnection(); // throws the error
conn.close();
System.out.println("Connected!");
} catch (SQLException e) {
System.out.println("Failed to Connect!");
e.printStackTrace();
}
} catch (NamingException e) {
System.out.println("Failed to Lookup!");
e.printStackTrace();
}
} catch (NamingException e1) {
System.out.println("Fail to get Context!");
e1.printStackTrace();
}
Output:
Failed to Connect!
java.sql.SQLException: Cannot create JDBC driver of class '' for connect URL 'null'
ds.getConnection() throws the error.
Any suggestions as to how i could fix this or debug further would be greatly appreciated.
SOLVED !!! - context.xml was not being put into the META-INF folder
context.xml was not being put into the META-INF folder
With the JNDI provider, do not use the dataSourceClassName (or dataSource.URL) properties. Use jdbcUrl, and driverClassName if necessary (but try without it first).

Spring Integration with RESTEasy

In our existing integration, we are planning to replace Queue ( the entry point to our integration processing) with RESTEasy services.
We are processing the HTTP requests as below:
1) Asynchronous HTTP Request Processing for GET
2) Asynchronous Job Service for POST
I understand that spring integration provides and for HTTP requests. But this is not something we want, as the request processing is handled by RESTEasy.
Software stack:
RESTEasy 3.0.9 Framework
Spring Integration 4.1.2.RELEASE
JBOSS EAP 6.4.
Is there a component that we could use to integrate RESTEasy services with spring integration ?
There is no explicit component exist, it is all API work to be done. You need to use dependent jar files and integration code
Below are the minimal Jar files to be path in workspace environment using ant or maven:
org.jboss.resteasy:resteasy-jaxrs:3.0.10.Final
org.jboss.resteasy:resteasy-spring:3.0.10.Final
org.springframework.boot:spring-boot-starter-web:1.2.2.RELEASE
org.jboss.resteasy:resteasy-jackson2-provider:3.0.10.Final
Following listener entries in web.xml to be done:
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/project</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener- class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<listener>
<listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>RESTEasyService</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.concretepage.Application</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>RESTEasyService</servlet-name>
<url-pattern>/project/*</url-pattern>
</servlet-mapping>
Dispatch Servlet can be put into WEB-INF
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.concretepage" />
</beans>
Sample Java Service Code:
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Path("/manage" )
#Component
public class ExService {
#Autowired
private ExRepository repository;
#GET
#Path("/{id}")
#Produces("application/json")
public Response getEmp(#PathParam("id") String id) {
Map<String,String> map = repository.getEmpDetail(id);
return Response.ok(map).build();
}
}
For more detail You may refer to http://docs.jboss.org/resteasy/docs/3.0.9.Final/userguide/html_single/index.html#RESTEasy_Spring_Integration
Use <int:gateway> to do the integration with spring.
<int:gateway id="providerGateway" service-interface="com.stack.overflow.TestInterface"
default-request-channel="requestChannel">
<int:method name="getDataByID" request-channel="requestChannel"/>
<int:method name="postDataByID" request-channel="requestChannel"/>
</int:gateway>
Where com.stack.overflow.TestInterface is the Resource Interface see below:
#Path(RestConstants.SERVICES)
public interface TestInterface {
#Path(RestConstants.TEST1)
#GET
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response getDataByID();
#Path(RestConstants.TEST2)
#POST
#Produces({ MediaType.TEXT_PLAIN })
public Response postDataByID(String edi);
}
You can have different message channel if desired (see the gateway above) for a request. e.g. a request to getDataByID, will be put on the requestChannel. You can read from this channel and do the required processing as you require and then send a response back.

Seam 3 / REST / Injection

Blockquote
I am trying to make a REST application with Seam 3. Hello world works nice. But I tried to use injection within the Rest Application with the annotation #Inject but the object is still null.
Does someone has a piece of code that initialize a component called within a REST Class ?
thanks a lot.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>
REST Application
#ApplicationPath("object")
#Path("creation")
#RequestScoped
public class ObjectApplication extends javax.ws.rs.core.Application {
#Inject
ObjectManager objectManager;
....
#POST
#GET
#Path("create")
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_XML)
public String createObject(ObjectType objectType) {
...
}
}
and Object Manager
#Stateless
public class ObjectManager {
}
.
20:30:50,362 INFO [org.jboss.weld.deployer] (MSC service thread 1-5) JBAS016008: Starting weld service for deployment ObjectRest.war
20:30:50,420 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-5) MSC00001: Failed to start service jboss.deployment.unit."ObjectRest.war".WeldService: org.jboss.msc.service.StartException in service jboss.deployment.unit."ObjectRest.war".WeldService: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [ObjectManager] with qualifiers [#Default] at injection point [[field] #Inject com.qc.api.rest.ObjectApplication.objectManager]
How I succeed :
Put all in the same project in eclipse.
And remove :
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
It seems that the problem was that there was two project :
XXXRest
+--XXXCore
and the injection was not done...

How to get Container Managed Transactions (CMT) working with EJB 3.1, Hibernate 3.6, JPA 2.0 , JBoss and MySQL

I was trying to get CMT working with JPA EntityManagers and EJBs, but came up with the error below. (stack trance truncated):
Caused by: java.lang.RuntimeException: **Could not resolve #EJB reference: [EJB Reference: beanInterface 'com.mydomain.beans.TestBean2', beanName 'testBean2', mappedName 'null', lookupName 'null',** owning unit 'AbstractVFSDeploymentContext#2008455195{vfs:///Users/willtardy/Documents/workspace/.metadata/.plugins/org.jboss.ide.eclipse.as.core/JBoss_6.0_Runtime_Server1300532851414/deploy/mydomainWeb.war}']
for environment entry: env/com.mydomain.action.SearchAction/testBean in unit AbstractVFSDeploymentContext#2008455195{vfs:///Users/willtardy/Documents/workspace/.metadata/.plugins/org.jboss.ide.eclipse.as.core/JBoss_6.0_Runtime_Server1300532851414/deploy/mydomainWeb.war}
My classes:
Servlet that access the Session Bean:
public class SearchActionExample extends Action {
#EJB
private static TestBeanServiceInterface testBean;
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
testBean.addSource("TEST SOURCE NAME", 88, 99);
Service service = testBean.findService("HBA", "MEL");
return mapping.findForward("success");
}
}
Remote interface:
#Remote
public interface TestBeanServiceInterface {
// Source is my own custom entity
void addSource(String sourceName, int newthreadsleeptime, int maxactivehttpclients);
// Service is my own Custom entity
Service findService(String departureAirportCode, String arrivalAirportCode);
}
Stateless Session Bean definition:
#Stateless
public class TestBeanService implements TestBeanServiceInterface {
#PersistenceContext(unitName="mydomainJPA")
private EntityManager em;
public void addSource(String sourceName, int newthreadsleeptime, int maxactivehttpclients) {
Source source = new Source();
source.setName(sourceName);
source.setNewThreadSleepTime(newthreadsleeptime);
source.setMaxActiveHttpClients(maxactivehttpclients);
em.persist(source);
}
public Service findService(String departureAirportCode, String arrivalAirportCode) {
String queryString = "from Service where departureairportcode = '" + departureAirportCode + "' and arrivalairportcode = '" + arrivalAirportCode + "'";
Service service = (Service)em.createQuery(queryString).getSingleResult();
return service;
}
}
file persistnce.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
<persistence-unit name="mydomainJPA" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/MySqlDS</jta-data-source>
<class>com.mydomain.entities.Service</class>
<class>com.mydomain.entities.Source</class>
<properties>
<property name="hibernate.query.factory_class" value="org.hibernate.hql.classic.ClassicQueryTranslatorFactory"/>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.current_session_context_class" value="jta"/>
</properties>
</persistence-unit>
When it says "cannot resolve reference", where else can I define the beans? ejb-jar.xml isn't needed with EJB3. Is there some other config file that I'm missing?
UPDATE:
I have updated the code segments above so that the bean is created as the interface type instead, as per the answer below.
Do the EJBs need to be defined or mapped in web.xml?
Assuming that a reference is required in web.xml, I have added an EJB ref to web.xml (see below), but now I'm receiving a new error (see below)
lines added to web.xml:
<ejb-ref>
<ejb-ref-name>ejb/TestBeanEJBname</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>com.mydomain.action.TestBeanService</home>
<remote>com.mydomain.action.TestBeanServiceInterface</remote>
</ejb-ref>
new error message now being received:
12:11:00,980 ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController] Error installing to PostClassLoader: name=vfs:///Users/willtardy/Documents/workspace/.metadata/.plugins/org.jboss.ide.eclipse.as.core/JBoss_6.0_Runtime_Server1300532851414/deploy/purejetWeb.war state=ClassLoader mode=Manual requiredState=PostClassLoader: org.jboss.deployers.spi.DeploymentException: java.lang.IllegalStateException: Failed to find ContainerDependencyMetaData for interface: au.com.purejet.action.TestBeanServiceInterface
Caused by: java.lang.IllegalStateException: Failed to find ContainerDependencyMetaData for interface: com.mydomain.action.TestBeanServiceInterface
at org.jboss.deployment.MappedReferenceMetaDataResolverDeployer.resolveEjbInterface(MappedReferenceMetaDataResolverDeployer.java:1255) [:6.0.0.Final]
at org.jboss.deployment.MappedReferenceMetaDataResolverDeployer.resolveEjbRefs(MappedReferenceMetaDataResolverDeployer.java:1099) [:6.0.0.Final]
at org.jboss.deployment.MappedReferenceMetaDataResolverDeployer.resolve(MappedReferenceMetaDataResolverDeployer.java:807) [:6.0.0.Final]
at org.jboss.deployment.MappedReferenceMetaDataResolverDeployer.internalDeploy(MappedReferenceMetaDataResolverDeployer.java:181) [:6.0.0.Final]
... 39 more
Update:
"Local" interface works just fine (i.e. doesn't have to be Remote)
I got it to work by deploying within an Enterprise Application Project within Eclipse. No references to beans are required within web.xml, ejb-jar.xml, or application.xml.
Contents of application.xml within EAR being deployed to Jboss:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" id="Application_ID" version="6">
<display-name>myprojects</display-name>
<module>
<web>
<web-uri>myproject.war</web-uri>
<context-root>myproject</context-root>
</web>
</module>
<module>
<ejb>myprojectsEJB.jar</ejb>
</module>
</application>
SessionBean class:
#Stateless
#Local(SessionBeanLocal.class)
public class SessionBean implements SessionBeanLocal {
#PersistenceContext(unitName="JPAtestProjectPersistenceUnit")
private EntityManager em;
Interface class:
#Local
public interface SessionBeanLocal {
TestTiger addTestTiger(String testTigerName);
MOST IMPORTANT change that got things working: inside the class that holds the session been local variable, a setting was required for the container (JBoss AS) to create the bean:
#EJB()
private TestBean3Local beanVariable;
public void setBeanVariable(TestBean3Local beanVariable) {
System.out.println("=====\n\nSET BEAN VARIABE SETTER WAS CALLED. (BY CONTAINER?) \n\n=======");
this.beanVariable = beanVariable;
}
You need to inject the remote interface and not the Bean
public class SearchActionExample extends Action {
#EJB
private static TestBean2Remote testBean;
public class SearchActionExample extends Action {
#EJB
private static TestBeanServiceInterface testBean;
Don't do injections into static field, injections are instance members and happen when object is created, whereas static field is a class member. This is most probably the cause for exception.
I have obtained a working solution:
#Local interface works just fine (i.e. doesn't have to be Remote)
No references to beans are required within web.xml, ejb-jar.xml, application.xml, or any jboss config file.
I got it to work by deploying within an "Enterprise Application Project" (EAP) within Eclipse. This project contains "Deployment Assembly" that contains the .jar containing JPA Entity Classes, and another .jar that contains other business-logic classes. The EAP has those two projects PLUS the EJB project and the "Dynamic Web Project" (creates a .war) for a total of 4 projects on it's build path. Jboss AS tool within Eclipse publishes/deploys the EAP to the Jboss server. Contents of application.xml within EAP being deployed to Jboss:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" id="Application_ID" version="6">
<display-name>myprojects</display-name>
<module>
<web>
<web-uri>myproject.war</web-uri>
<context-root>myproject</context-root>
</web>
</module>
<module>
<ejb>myprojectsEJB.jar</ejb>
</module>
</application>
Local Interface class:
package com.myproject.beans;
import javax.ejb.Local;
import com.myproject.entities.Lion;
#Local
public interface SessionBeanLocal {
Lion addLion(String lionName);
}
SessionBean class:
package com.myproject.beans;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.myproject.Lion;
#Stateless
#Local(SessionBeanLocal.class)
public class SessionBean implements SessionBeanLocal {
#PersistenceContext(unitName="PersistenceUnitNameInPersistenceXML")
private EntityManager em;
public Lion addLion(String lionName) {
Lion lion = new Lion(lionName);
em.persist(lion);
}
MOST IMPORTANT change that got things working: inside the class that holds the session been variable (e.g. inside a Struts action servlet, but could be any servlet), a setter method was required for the container (JBoss AS) to create the bean:
#EJB()
private SessionBeanLocal bean;
public void setBean(SessionBeanLocal bean) {
System.out.println("setBean setter was called by container (e.g. Jboss)");
this.bean = bean;
}
public exampleStrutsServletMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
PrintWriter out = response.getWriter();
Lion lion = bean.addLion("Simba"); // this will persist the Lion within the persistence-context (and auto-generate an Id), and the container will manage when it's flushed to the database
out.print("<html>LION ID = " + lion.getLionId() + "<html>");
}
file persistnce.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
<persistence-unit name="PersistenceUnitNameInPersistenceXML" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/MySqlDS</jta-data-source>
<properties>
</properties>
</persistence-unit>
mysql-dx.xml (in directory jboss-server-dir/server/default/deploy):
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>MySqlDS</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/myProjectDatabase</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>username</user-name>
<password>mypassword</password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>
NOTE: Classes do not need to be defined in persistence.xml (via "< class >") if "Persistence Class Management" is set to "Discover annotated classes automatically" in "Java Persistence" project property panel for the Eclipse JPA project (i.e. the project that containers your JPA 2.0 Entity classes and persistence.xml)
NOTE: This solution is based on: EJB3.1, Eclipse Helios SR2, Hibernate 3.6, JPA 2.0, JBoss 6, MySQL 5.5.10
NOTE: Regarding "Container Managed Transactions" (CMT). The Hibernate manual references them, and indicates that you need to set persistence.xml properties such as "hibernate.transaction.factory_class" to value of: "org.hibernate.transaction.CMTTransactionFactory". This is not the case if you are using JPA EntityManager instead of native hibernate. I didn't required any such custom CMT properties in persistence.xml. This is where Hibernate gets confusing, between the two ways to implement it (i.e. SessionFactory vs EntityManager). Please feel free to comment more on this part of my solution as I'm still just wrapping my head around it! Will