Interceptors are not intercepting - java-ee-6

I am having problems setting up a Java EE 6 CDI interceptors. I am using embedded glassfish, I have specified the interceptor in beans.xml in the web application.
<beans
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<interceptors>
<class>ServiceInterceptor</class>
</interceptors>
</beans>
I am trying to secure this bean:
#Named
//#Stateless
#RequestScoped
public class SecuredMethodJSFBean /*implements Serializable*/{
#Inject
protected SecuredMethodSample securedMethodSample;
/*
#CurrentUser
#SessionScoped
#Inject
protected RuntimePrincipalAware principal;
//protected JSFLoginBean jsfLoginBean;
*/
public SecuredMethodJSFBean()
{
super();
System.out.println("creating secured method jsf bean");
}
#Secured("adfadfafd")
public void doSomething()
{
//System.out.println("\n\n\n\nprincipal:" + principal);
//System.out.println("principal:" + jsfLoginBean.getPrincipal());
//securedMethodSample.doSomething(jsfLoginBean.getPrincipal().getName());
//return(jsfLoginBean.getPrincipal().getName());
//securedMethodSample.doSomething(principal.getName());
//return(principal.getName());
//return("secured-method");
securedMethodSample.doSomething("testing ...");
}
}
What do I need to do to get my interceptors running?
Also, I am trying to use interceptors to intercept method invocations on beans used by servlets. Since those beans are beans, I should be able to intercept them. However, I am unable to do so. I was originally trying to intercept method invocations in servlets directly, but they're not CDI beans so that does not make sense.
Thanks,
Walter

"I have specified the interceptor in beans.xml in the web application"
Is #Secured defined in another project / jar? In that case you need to enable it in that beans.xml.

To answer my question better, I did the following:
I made the project ejb instead of jar (inside maven).
I created an ejb-jar.xml file specifying / declaring my interceptor (src/main/resources/META-INF).
in projects using this interceptor, I specified the type as ejb to it would pick it up correctly.
Walter

Related

Glassfish 4.1.1 / EAR / java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName XYZ

I have a huge problem deploying an EAR project on my Payara/Glassfish 4.1.1 server, which I can't solve since days.
Hope somebody can help me!
My setup ->
I have one EJB/JPA eclipse project "CommonPersistanceAndService" that contains my JPA entities, my Databaseproducer, and some basic serviceclasses.
I have a webproject that uses this EJB/JPA project so I know that my databaseproducer works correctly:
#Singleton
#Startup
public class DatenbankProducer implements Serializable{
private static final long serialVersionUID = 2605227297803488033L;
#PersistenceContext(unitName="XYZdb")
EntityManager emXYZProd;
#PersistenceContext(unitName="XYZtest")
EntityManager emXYZTest;
#Inject ApplicationConfig appConfig;
#Inject Logger logger;
public XYZDatenbankProducer() { }
#Produces
#XYZDatenbank
public EntityManager getEntityManager(){
if(appConfig.isBetriebsmodusTest())
return emXYZTest;
return emXYZProd;
}
#PostConstruct
public void initDBConnection(){
Query q = getEntityManager().createNativeQuery("select * from zconnectiontest");
q.getSingleResult();
logger.info("=== Connection to Database established");
}
}
Now using this same EJB/JPA project in an EAR project together with a project "Batchjobs" that only has a serviceclass with a scheduler
<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6">
<display-name>Batchjobs-EAR</display-name>
<module>
<ejb>Batchjobs.jar</ejb>
</module>
<module>
<ejb>CommonPersistanceAndService.jar</ejb>
</module>
</application>
I also copied all jar file dependencies from my EJB/JPA project to the EAR/lib directory. The EAR deploys correctly, but when the scheduler calls the service I get the following error:
Caused by: java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName XYZtest
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.init(EntityManagerWrapper.java:138)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper._getDelegate(EntityManagerWrapper.java:171)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.createNativeQuery(EntityManagerWrapper.java:557)
at com.isg.kis.application.XYZDatenbankProducer.initDBConnection(XYZDatenbankProducer.java:48)
... 122 more
When I debug the programm the object for emXYZTest, a EntityManagerWrapper, doesn't get an EntityManagerFactory injected!? When I do the same in my Webproject there is an EntityManagerFactory.
So the question is - why does the EntityManagerFactory not get injected in the EAR deployment!?
Nothing I tried so far worked. Any ideas what causes this problem?
thanks in advance
Thomas

Apache Camel + Spring (war) + Tomcat + REST

I am trying to develp a rest service using apache camel. My project is a spring mvc war deployed on tomcat.
I dont want to use apache cxf (cxf servlet).
public class SampleRouter extends RouteBuilder {
#override
public void configure() throws Exception {
from("cxfrs://http://localhost:1234/sample")
.process (new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("test");
}
})).setBody(constant("SUCCESS"));
}
}
#Path("/sample")
public class SampleResource {
#GET
public void test() {
}
}
web.xml has dispatcherservlet, contextloaderlistener.
dispatcher-servlet.xml has mvc:annotation-drivem, context:component-scan,
<camelContext id="server" trace="true" xmlns="http://camel.apache.org/schema/spring">
<contextScan />
</camelContext>
pom.xml has camel-core, camel-cxf, camel-stream, cxf-rt-transports-http-jetty, cxf-rs-frontend-jaxrs, camel-spring, spring-webmvc, spring-web, spring-context.
Tomcat runs on 8080, there seems to be no exception when server comes up. But, I tried hitting the url (http://localhost:1234/sample), nothing seems to be happening.
What am i missing? I would eventually extend this to REST to Spring DSL or REST to Java DSL with authentication, filters and interceptors.
I also tried cxf:rsServer and referred that in router class.
Also, in the future if i have to use https instead of http? or how do i have the url not hard-coded?
It may be too late, but to consume HTTP requests, one may use Apache Camel Servlet component
http://camel.apache.org/servlet.html
You need to setup the resourceClass option on the cxfrs endpoint. Here is an example
from("cxfrs://http://localhost:1234/sample?resourceClasses=my.pachage.SampleResource")
You can find some example in camel-cxfrs component page.
If you want to export a CXF service through servlet transport, you need to do some work as it said.
If you want to change the address dynamically, you can take look at the camel properties component.
If you are looking to start a camel route by a consuming cxf rest service which uses the servlet transport then you need to :
Clean up your pom.xml and remove any references to jetty.
Add the CXF servlet to your web.xml
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- all our webservices are mapped under this URI pattern -->
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
Add the servlet-transport dependency:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf-version}</version>
</dependency>
In your spring/camel configuration
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<cxf:rsServer id="rsServer" address="/restService"
serviceClass="com.something.test.SimpleServiceImpl"
loggingFeatureEnabled="true" loggingSizeLimit="20" />
Build a route from this consumer endpoint as:
from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer")
.to("log:TEST?showAll=true")
You can now view/(invoke with a method) the endpoint using : http://host:port/context/services/restService?_wadl

Override Built-in Principal Bean

In Java EE 6, there is a built in bean type javax.security.Principal which is available for injection like #Inject Principal principal;.
This is by default and I'm wondering if there is a way to change it, say, by supplying a producer method instead.
As it stands, writing a producer method will cause a deployment exception.
Example Producer:
my.package;
import javax.security.Principal;
public class MyProducer {
...
#Produces
public Principal obtainPrincipal() {
return getMyPrincipal();
}
}
The exception:
org.jboss.weld.exceptions.DeploymentException: WELD-001409 Ambiguous dependencies for type [Principal] with qualifiers [#Default] at injection point [[parameter 1] of [constructor] #Inject public my.package.MyType(Principal, SomeOtherType)]. Possible dependencies [[Producer Method [Principal] with qualifiers [#Any #Default] declared as [[method] #Produces #SessionScoped protected my.package.MyProducer.obtainPrincipal()], Built-in Bean [java.security.Principal] with qualifiers [#Default]]]
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:278)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:244)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:107)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:127)
at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:346)
at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:331)
at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:366)
at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:83)
at org.jboss.as.weld.services.WeldService.start(WeldService.java:76)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
So the question is - is there any way to replace the default built in types in CDI?
To give you an idea of why I need this, my project is switching from JAAS to Apache Shiro. There is a good amount of existing code that does something based on the injected principal. Shiro in a web environment however, only wraps the HttpServlet request / response and overrides the appropriate security related methods. That however does not propagate to CDI, which in that case always returns the anonymous principal.
Update
I also tried the following:
my.package;
import javax.security.Principal;
#Alternative
public class MyPrincipal implements Principal {
...
#Override
public String getName() {
return getMyPrincipalName();
}
}
Then enabling the alternative in beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<alternatives>
<class>my.package.MyPrincipal</class>
</alternatives>
</beans>
In this case, there are no deployment errors, but the injected principal is still the default one, not my enabled alternative.
The guys at Weld helped me out. My deployment structure was something like:
-- app.war
|-- module0.jar (beans.xml)
|-- module1.jar (beans.xml)
|-- ...
|-- other-lib.jar
But in CDI 1.0, alternatives are anabled per bean archive only. So, adding
<alternatives>
<class>my.package.MyPrincipal</class>
</alternatives>
in each beans.xml makes it all work.

arquillian persistence extension doesn't work

I'm trying to get my webservice tested. This webservice uses ejb with jpa to retrieve its data. So i want to use the arquillian extension to get this done.
This is my arquillian test class:
#RunWith(Arquillian.class)
public class PersonWebServiceIT {
private PersonWebService service;
#Deployment(testable = false)
public static Archive<?> createDeployment() {
return ShrinkWrap
.create(ZipImporter.class, "test.ear")
.importFrom(new File("simple-webservice-ear-1.0.0-SNAPSHOT.ear"))
.as(EnterpriseArchive.class);
}
#Test
#UsingDataSet("dataset.yml")
#SneakyThrows
public void testFindPersons(#ArquillianResource final URL deploymentUrl) {
loadService(deploymentUrl);
Assert.assertEquals(2, service.findPersons().size());
}
private void loadService(final URL deploymentUrl)
//load webservice
}
}
This is my datasets/dataset.yml file:
person:
- id: 1
firstName: "stijn"
- id: 2
firstName: "cremers"
my arquillian.xml:
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.com/arquillian" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian-1.0.xsd">
<extension qualifier="persistence">
<property name="defaultDataSource">java:/DefaultDS</property>
</extension>
</arquillian>
My test data never gets loaded. I even tried with a wrongly formatted yml file, but even then i get no error.
The problem is with your test run mode. When you define your #Deployment with the attribute testable=false, all tests are run in the client mode, i.e. they're not run in-container.
The Arquillian Persistence Extension (as of 1.0.0.Alpha5) does not support running tests in client mode; only in-container tests are supported for now. Support for client mode tests in APE may come in a future release.
<property name="defaultDataSource">java:/DefaultDS</property>
U're specifying the Datasource which is defined in the server.
In client mode, test cases are run outside the Container(ie. Other JVM)
So that only persistence extension can not make use of data source and hence you can not use arquillian persistence extension client mode.
If there is anyway to specify jdbc url instead of datasource name in arquillian.xml file.Then u may use persistence extension

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