I have JPA mapping to HSQLDB and persistence.xml reads as below:
<persistence-unit name="HMC">
<jta-data-source>java:hmc</jta-data-source>
<class>org.hmc.jpa.models.BloodGroup</class>
<class>org.hmc.jpa.models.ContactInfo</class>
<properties>
<property
name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
</properties>
</persistence-unit>
But whenever application is deployed, it JBoss throws RuntimeException saying:
Specification violation [EJB3 JPA 6.2.1.2] - You have not defined a non-jta-data-source for a RESOURCE_LOCAL enabled persistence context named: ABC
I also have datasource defined in JBoss. Is there anything that I am missing in the configuration?
Regards,
Satya
if the transaction type of the persistence unit is JTA, the
jta-datasource element is used to declare the JNDI name of the JTA
data source that will be used to obtain connections. This is the
common case.
if the transaction type of the persistence unit is resource-local,
the non-jta-data-source should be used to declare the JNDI name of a
non-JTA data source.
hat is happening is that JBoss automatically scans and validates files named persistence.xml, since you are using spring to manage your beans, I guess you are not using EJB3.
What needs to be understood is if you want JBoss to control JTA transactions for you and if you want to use JBoss Transaction Manager, or if you just want to do JPA transactions, without JTA transaction control.
If you want to just use the JPA transactions and skip JBoss TransactionManagener, you can just rename your persistence.xml file to spring-persistence.xml (or whatever you like), and in spring-context.xml file you can change your entityManagerFactory to this:
<!-- JPA primary EntityManagerFactory -->
<bean id="entityManagerFactory" lazy-init="true"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:persistenceUnitName="ExamplePU"
p:persistenceXmlLocation="classpath:/META-INF/spring-persistence.xml"
p:jpaVendorAdapter-ref="jpaVendorAdapter"
p:jpaDialect-ref="jpaDialect"
p:dataSource-ref="dataSource"/>
What happens is that by renaming the file JBoss won't validate it, since you are working outside of the EJB spec and not using any EJB beans, JBoss shouldn't be scanning this file anyways. And since you renamed it, you need to tell spring where it is and under what name.
I got it working by removing transaction-type="RESOURCE_LOCAL" and changing java:hmc to java:/hmc. But now my application has another problem whenever I try to persist.
It throws : java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()
Can anybody tell me how to get a connection and start transaction in JTA mode?
Regards,
Satya
Related
I'm currently developing a REST service to replace an existing solution. I'm using plain Payara/JEE7/JAX-RS. I am not using Spring and I do not intent to.
The problem I'm facing is that we want to reuse as much of the original configuration as possible (deployment on multiple nodes in a cluster with puppet controlling the configuration files).
Usually in Glassfish/Payara, you'd have a domain.xml file that has some content like this:
<jdbc-connection-pool driver-classname="" pool-resize-quantity="10" datasource-classname="org.postgresql.ds.PGSimpleDataSource" max-pool-size="20" res-type="javax.sql.DataSource" steady-pool-size="10" description="" name="pgsqlPool">
<property name="User" value="some_user"/>
<property name="DatabaseName" value="myDatabase"/>
<property name="LogLevel" value="0"/>
<property name="Password" value="some_password"/>
<!-- bla --->
</jdbc-connection-pool>
<jdbc-resource pool-name="pgsqlPool" description="" jndi-name="jdbc/pgsql"/>
Additionally you'd have a persistence.xml file in your archive like this:
<persistence-unit name="myDatabase">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/pgsql</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<!-- bla -->
</properties>
</persistence-unit>
I need to replace both of these configuration files by a programmatic solution so I can read from the existing legacy configuration files and (if needed) create the connection pools and persistence units on the server's startup.
Do you have any idea how to accomplish that?
Actually you do not need to edit each domain.xml by hands. Just create glassfish-resources.xml file like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-connection-pool driver-classname="" pool-resize-quantity="10" datasource-classname="org.postgresql.ds.PGSimpleDataSource" max-pool-size="20" res-type="javax.sql.DataSource" steady-pool-size="10" description="" name="pgsqlPool">
<property name="User" value="some_user"/>
<property name="DatabaseName" value="myDatabase"/>
<property name="LogLevel" value="0"/>
<property name="Password" value="some_password"/>
<!-- bla --->
</jdbc-connection-pool>
<jdbc-resource pool-name="pgsqlPool" description="" jndi-name="jdbc/pgsql"/>
</resources>
Then either use
$PAYARA_HOME/bin/asadmin add-resources glassfish-resources.xml
on each node once or put it under WEB-INF/ of your war (note, in this case jndi-name SHOULD be java:app/jdbc/pgsql because you do not have access to global: scope at this context).
Note that your persistence.xml should be under META-INF/ of any jar in your classpath.
If you do not like this, you may use
#PersistenceUnit(unitName = "MyDatabase")
EmtityManagerFactory emf;
to create EntityManager on fly:
createEntityManager(java.util.Map properties).
By the way, using Payara you can share configuration with JCache across you cluster.
Since the goal is to have a dockerized server that runs a single application, I can very well use an embedded server.
Using an embedded sever, the solution to my problem looks roughly like this:
For the server project, create a Maven dependency:
<dependencies>
<dependency>
<groupId>fish.payara.extras</groupId>
<artifactId>payara-embedded-all</artifactId>
<version>4.1.1.163.0.1</version>
</dependency>
</dependencies>
Start your server like this:
final BootstrapProperties bootstrapProperties = new BootstrapProperties();
final GlassFishRuntime runtime = GlassFishRuntime.bootstrap();
final GlassFishProperties glassfishProperties = new GlassFishProperties();
final GlassFish glassfish = runtime.newGlassFish(glassfishProperties);
glassfish.start();
Add your connection pools to the started instance:
final CommandResult createPoolCommandResult = commandRunner.run("create-jdbc-connection-pool",
"--datasourceclassname=org.postgresql.ds.PGConnectionPoolDataSource", "--restype=javax.sql.ConnectionPoolDataSource", //
"--property=DatabaseName=mydb"//
+ ":ServerName=127.0.0.1"//
+ ":PortNumber=5432"//
+ ":User=myUser"//
+ ":Password=myPassword"//
//other properties
, "Mydb"); //the pool name
Add a corresponding jdbc resource:
final CommandResult createResourceCommandResult = commandRunner.run("create-jdbc-resource", "--connectionpoolid=Mydb", "jdbc__Mydb");
(In the real world you would get the data from some external configuration file)
Now deploy your application:
glassfish.getDeployer().deploy(new File(pathToWarFile));
(Usually you would read your applications from some deployment directory)
In the application itself you can just refer to the configured pools like this:
#PersistenceContext(unitName = "mydb")
EntityManager mydbEm;
Done.
A glassfish-resources.xml would have been possible too, but with a catch: My configuration file is external, shared by some applications (so the file format is not mine) and created by external tools on deployment. I would need to XSLT the file to a glassfish-resources.xml file and run a script that does the "asadmin" calls.
Running an embedded server is an all-java solution that I can easily build on a CI server and my application's test suite could spin up the same embedded server build to run some integration tests.
We have an application which needs to consume an external web service. To do this we have generated the set of Java artifacts from the WSDL via Maven using the wsdl2java goal provided by the cxf-codegen-plugin plugin.
We have written an integration test as part of our test suite which calls the real web service and everything works fine.
The code to integrate with the actual web service is then packaged into a set of JARs and used inside the front end application which needs to use the web service.
We are having an issue when the FE application uses the integration code. Exactly the same code is being executed by the FE application as is being used in our working integration test but the SOAP message which is ultimately generated is different between the two and the message generated by the actual application is incorrect.
The working SOAP request produced by our integration tests is:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns12:ProcessUIRequest xmlns:ns10="http://zzz/yyyentityview/validation/"
xmlns:ns11="http://zzz/yyyview/search/list/"
xmlns:ns12="http://zzz/yyywebservice/v5/types/"
xmlns:ns2="http://zzz/yyyentityview/app/"
xmlns:ns3="http://zzz/yyyentityview/client/"
xmlns:ns4="http://zzz/yyyview/search/postcode/"
xmlns:ns5="http://zzz/yyyview/app/"
xmlns:ns6="http://zzz/yyyview/search/app/"
xmlns:ns7="http://zzz/yyyview/search/bank/"
xmlns:ns8="http://zzz/yyyview/uw/"
xmlns:ns9="http://zzz/yyybase/">
<ns12:ProcessUIRequest CallType="Submit" DisplayError="false"
IsAnonymous="false" IsCompactRequest="false" IsError="false">
<ns9:ModelData>
<ns9:TransactionData ApplicationReference="20000003CR3.00000003"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="ns5:QuoteLoadTxnDataVO" />
</ns9:ModelData>
<ns9:Activity ActionCode="QuoteLoad" ActionMode="Default"
ActivityCode="QuoteApplicationFull" ActivityMode="Default"
ActivityReference="" ActivityStatus="Inital"
ActivityTransaction="StartNewActivityAndLogOffUser"
CanProceedWithValidationsOutstanding="true">
<ns9:BusinessKeys>
<item>
<key>
<string>ADVREF</string>
</key>
<value>
<BusinessKeyVO KeyName="ADVREF" KeyValue="AVAGT01">
<BusinessKey KeyName="ADVREF" KeyType="Unknown"
KeyValue="AVAGT01" />
</BusinessKeyVO>
</value>
</item>
</ns9:BusinessKeys>
</ns9:Activity>
</ns12:ProcessUIRequest>
</ns12:ProcessUIRequest>
</S:Body>
</S:Envelope>
The POJO which is marshalled into that SOAP request is:
<tcp.ssgbase.BaseVO>
<modelData>
<transactionData class="tcp.ssgview.app.QuoteLoadTxnDataVO">
<applicationReference>20000003CR3.00000003</applicationReference>
</transactionData>
</modelData>
<activity>
<businessKeys>
<item>
<tcp.serializable__dictionary.BusinessKeyItem>
<key>
<string>ADVREF</string>
</key>
<value>
<businessKeyVO>
<businessKey>
<keyName>ADVREF</keyName>
<keyValue>AVAGT01</keyValue>
<keyType>Unknown</keyType>
</businessKey>
<keyName>ADVREF</keyName>
<keyValue>AVAGT01</keyValue>
</businessKeyVO>
</value>
</tcp.serializable__dictionary.BusinessKeyItem>
</item>
</businessKeys>
<actionMode>DEFAULT</actionMode>
<activityMode>DEFAULT</activityMode>
<activityTransaction>START_NEW_ACTIVITY_AND_LOG_OFF_USER</activityTransaction>
<actionCode>QuoteLoad</actionCode>
<activityReference></activityReference>
<activityStatus>INITAL</activityStatus>
<activityCode>QuoteApplicationFull</activityCode>
<canProceedWithValidationsOutstanding>true</canProceedWithValidationsOutstanding>
</activity>
<displayError>false</displayError>
<isAnonymous>false</isAnonymous>
<isError>false</isError>
<isCompactRequest>false</isCompactRequest>
<callType>SUBMIT</callType>
</tcp.ssgbase.BaseVO>
The SOAP request generated by the actual FE application is:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns2:ProcessUIRequest xmlns:ns2="http://zzz/yyywebservice/v5/types/">
<processUIRequest>
<activity>
<actionCode>QuoteLoad</actionCode>
<actionMode>DEFAULT</actionMode>
<activityCode>QuoteApplicationFull</activityCode>
<activityMode>DEFAULT</activityMode>
<activityReference />
<activityStatus>INITAL</activityStatus>
<activityTransaction>
START_NEW_ACTIVITY_AND_LOG_OFF_USER</activityTransaction>
<businessKeys />
<canProceedWithValidationsOutstanding>
true</canProceedWithValidationsOutstanding>
</activity>
<callType>SUBMIT</callType>
<displayError>false</displayError>
<isAnonymous>false</isAnonymous>
<isCompactRequest>false</isCompactRequest>
<isError>false</isError>
<modelData>
<transactionData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="ns2:quoteLoadTxnDataVO">
<applicationReference>
20000003ESF.00000018</applicationReference>
</transactionData>
</modelData>
</processUIRequest>
</ns2:ProcessUIRequest>
</soapenv:Body>
</soapenv:Envelope>
The POJO which is marshalled into that SOAP request is:
<tcp.ssgbase.BaseVO>
<modelData>
<transactionData class="tcp.ssgview.app.QuoteLoadTxnDataVO">
<applicationReference>20000003ESF.00000018</applicationReference>
</transactionData>
</modelData>
<activity>
<businessKeys>
<item>
<tcp.serializable__dictionary.BusinessKeyItem>
<key>
<string>ADVREF</string>
</key>
<value>
<businessKeyVO>
<businessKey>
<keyName>ADVREF</keyName>
<keyValue>AVAGT01</keyValue>
<keyType>Unknown</keyType>
</businessKey>
<keyName>ADVREF</keyName>
<keyValue>AVAGT01</keyValue>
</businessKeyVO>
</value>
</tcp.serializable__dictionary.BusinessKeyItem>
</item>
</businessKeys>
<actionMode>DEFAULT</actionMode>
<activityMode>DEFAULT</activityMode>
<activityTransaction>START_NEW_ACTIVITY_AND_LOG_OFF_USER</activityTransaction>
<actionCode>QuoteLoad</actionCode>
<activityReference></activityReference>
<activityStatus>INITAL</activityStatus>
<activityCode>QuoteApplicationFull</activityCode>
<canProceedWithValidationsOutstanding>true</canProceedWithValidationsOutstanding>
</activity>
<displayError>false</displayError>
<isAnonymous>false</isAnonymous>
<isError>false</isError>
<isCompactRequest>false</isCompactRequest>
<callType>SUBMIT</callType>
</tcp.ssgbase.BaseVO>
You can see that the structure of the two requests are different even though the code being executed in our integration JARs is exactly the same and the structure of the POJOs used to create the SOAP message is the same (barring one value). From the request, it looks to be like the request generated in the FE application is not picking up the correct WSDL and associated XSDs.
Our code to generate the correct service endpoint interface implementation is:
private <T> T createServiceObject(final Class<T> p_seiClass) throws ApplicationException {
try {
final Service serviceFactory = Service.create(new URL(wsdlLocation), new QName(targetNamespace, serviceName));
final SoapHandlerResolver handlerResolver = new SoapHandlerResolver();
handlerResolver.addHandler(new SoapMessageLoggingHandler());
serviceFactory.setHandlerResolver(handlerResolver);
final T service = serviceFactory.getPort(p_seiClass);
((BindingProvider) service).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"endpoint");
return service;
} catch (MalformedURLException e) {
throw new ApplicationException(ApplicationErrorCode.COMM_ERR_UNEXPECTED_ERROR, e);
}
}
After doing some debugging, I have noticed that the instance of the serviceFactory is different in the integration test and when we are running within the FE application.
In the integration test, the instance of the class (taken from the Eclipse debugger where we run the integration test using jUnit) is: 'JAX-WS RI 2.1.6 in JDK 6: Stub for ' and it appears to be of type 'SEIStub'.
When running within the FE application, the instance of the class is org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler. The FE application is hosted and executed on WebSphere Application Server.
So, my question is what could be happening when running in the actual FE application to cause the incorrect WSDL and XSD definitions to be picked up when marshalling the POJO into the SOAP request? I have spent a long time trying to debug this but to no avail.
The two soap request are different because, as you already said, the two serviceFactory is different and using different specifications 1.1 and 1.2.
My suggestion is that you configure your maven project to import the right jars on your test enviroment or update the jar on the container (the jar that create the serviceFactory). As I'm not familiarized with cxf-codegen-plugin I can't suggest more than that.
This suggestion was originally posted as a comment. The OP ask to put it as an answer.
I had this experienced when I was trying to write a client application and deploy it in Web Logic Server. You need to use exact version of java which is used by the server while creating the classes.
Soap request is created internally by JVM. If JVM is different while creating the classes and testing them and while consuming it on real time, SOAP will or may be different.
I need to migrate a web service application from Tomcat 6 (using JDK 1.5) to Tomcat 7 (using JDK 1.6) (actually testing on 7.0.27). The JAX-WS framework is Metro 2.1.
I'm using two ServletContextListeners:
"WebAppListener" : to initialize the application (configuration, setup of database connections...).
"com.sun.xml.ws.transport.http.servlet.WSServletContextListener": the Metro listener that creates the web services.
The order is important, because I need my web app fully initialized before the #PostConstruct method is called on my web service.
In Tomcat 6, this works marvelously:
INFO: Starting Servlet Engine: Apache Tomcat/6.0.36
mars 16, 2013 5:13:13 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive WSWebApp.war
************************ IN WebAppListener.contextInitialized ***********************
************************ IN WSMyWebService.postConstruct ****************************
Exactly the same war however in Tomcat 7:
mars 16, 2013 6:45:24 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive C:\home\tomcat\webapps\WSWebApp.war
************************ IN WSMyWebService.postConstruct ****************************
************************ IN WebAppListener.contextInitialized ***********************
I thought that the order in which the listener's are called is the order in which they appear in the web.xml?
Why this order has been changed in Tomcat 7? But more importantly: What do I need to do to get the "Tomcat6" order back?
Thanks.
The answer lies in a difference between Servlet spec 2.5 and Servlet spec 3.0.
In Servlet spec 2.5, the order in which listeners are called is defined by the order of their declaration in the deployment descriptor (web.xml):
SRV.10.3.3 Listener Registration.
The Web container creates an
instance of each listener class and registers it for event
notifications prior to the processing of the first request by the
application. The Web container registers the listener instances
according to the interfaces they implement and the order in which
they appear in the deployment descriptor. During Web application
execution, listeners are invoked in the order of their registration.
In Servlet spec 3.0, the order in which listeners are called is defined by the element <absolute-ordering> in the deployment descriptor (web.xml):
8.2.3 Assembling the descriptor from web.xml, webfragment.xml and annotations. ... c. Prior to this release of the specification,
context listeners were invoked in random order.
This is wrong IMHO, as stated above in the version 2.5 spec. :-)
As of Servlet 3.0,
the listeners are invoked in the order in which they are declared in
the web.xml as specified below: i. Implementations of
javax.servlet.ServletContextListener are invoked at their
contextInitialized method in the order in which they have been
declared, and at their contextDestroyed method in reverse order.
This doesn't work at all like you'd expect and is the source of my trouble, confusion and a lost weekend. ;-)
It's NOT the same ordering as before (2.5 spec)!
But there is more... (the AHA moment is near!)
8.2.2 Ordering of web.xml and web-fragment.xml
Since the specification allows the application configuration resources
to be composed of multiple configuration files (web.xml and
web-fragment.xml), discovered and loaded from several different
places in the application, the question of ordering must be
addressed.
...
Two cases must be considered to allow application configuration
resources to express their ordering preferences.
1. Absolute ordering: an <absolute-ordering> element in the web.xml. a. In this case, ordering preferences that would have been handled by
case 2 below must be ignored.
2. Relative ordering: an <ordering> element within the web-fragment.xml. a. A web-fragment.xml may have an <ordering>
element. If so, this element must contain zero or one <before>
element and zero or one <after> element. The meaning of these elements
is explained below.
So, in my case, I had two options:
Stick with version 2.5 : This works well on Tomcat 6 and 7, but is only moving problems to the future.
Migrate to version 3.0 of the spec and adjust my deployment descriptor accordingly:
Update the version and schema in the web-app element, of course:
<web-app 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/web-app_3_0.xsd"
version="3.0">
Adding a <absolute-ordering> element that defines the order in which the listeners should be processed:
<absolute-ordering> <name>bootstrap</name><name>ws</name><others/></absolute-ordering>
<listener id="bootstrap">
<listener-class>lu.estiedi.ws.WebAppBootstrap</listener-class>
</listener>
<listener id="ws">
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
Note the <others/> element : if it's not present, then the listeners that are not named will not be processed.
EDIT:
This doesn't actually solve the problem.
It went away yesterday at home, but this morning at work the solution didn't work. :-(
It looks like Metro is using a service provider ServletContainerInitializer, which are called before the Listeners.
If this is the way it's supposed to work, then the PosConstruct method is always called before the contextInitialized on Listeners.
Where do we initialise our application then, before the web services are created?
It is not about order of Listeners, it is about a new feature of servlets spec 3.0 and the fact that you are probably using a JAX-WS implementatios like METRO, I suppose.
In servlets spec 3.0 (chapter 8.2.4) there is a way to add 3rd party plugins or APIs to containers (Tomcat in this case), for example JAX-WS, JAX-RS, JSF, etc. implementations. It is also known ad SCI (javax.servlet.ServletContainerInitializer).
In short, METRO JAX-WS jars use this way so it is not mandatory to add listener (com.sun.xml.ws.transport.http.servlet.WSServletContextListener) and servlet configuration in your web.xml descriptor file. It uses sun-jaxws.xml file to list ws endpoints and instantiate ws classes before deployment of web application and execution, for example, of methods contextInitialized of listeners.
To avoid this, just follow instructions for avoiding SCI mechanism in Tomcat: How do I make Tomcat startup faster?
There exists an attribute on Context element, containerSciFilter. It can be used to disable container-provided features that are plugged into Tomcat via SCI API: WebSocket support (in Tomcat 7 and later), JSP support (in Tomcat 8 and later).
The class names to filter can be detected by looking into META-INF/services/javax.servlet.ServletContainerInitializer files in Tomcat JARs. For WebSocket support the name is org.apache.tomcat.websocket.server.WsSci, for JSP support the name is org.apache.jasper.servlet.JasperInitializer.
It worked for me with JAX-WS and it just uses web.xml config to deploy web services.
i am creating a web service using 3rd party wsdl that helps me in getting a kind of notification. now i have to save that notification in DB and perform several other operations related to DataBase.
in My persistence.xml there are two persistence units as following:
<persistence-unit name="PU1" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/vsDS</jta-data-source>
<class>com.Response</class>
<class>com.Request</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
<persistence-unit name="PU2" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/vdDS</jta-data-source>
<class>com.LogRequest</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
till yet i have made a class named Service.java that have all functions i need to perform on DB as following:
public class Service {
private static Logger logger = Logger.getLogger(Service.class);
private EntityManagerFactory PU1;
private EntityManagerFactory PU2;
public Service(){
System.out.println("in service's constructer");
PU1=Persistence.createEntityManagerFactory("PU1");
PU2=Persistence.createEntityManagerFactory("PU2");
}
public void logSubRequest(String msg){
EntityManager em= PU1.createEntityManager();
try{
em.getTransaction().begin();
Request req=new Request();
req.setMessage(msg);
req.setStatus("Y");
em.persist(req);
em.getTransaction().commit();
}catch(Exception e){
logger.error("In logSubRequest="+e.getMessage());
e.printStackTrace();
}finally{
if(em.isOpen()){
em.close();
}
}
}
// there are several other methods of such kind that either persist entities or executeUpdate
}
My Question is: Am i going with standard approach to implement JPA with webservice or should i go with some other technology/method. kindly suggest and guide if i am doing any thing out of standard.
The combination of a Web services and JPA is often used, I see no reason to choose some other persistence mechanism. I'd recommend sticking with your current design until your requirements get more complex.
Larger applications where the equivalent of your Request object is more complex and the resulting business logic more challenging will add more layers of objects in order to control the structure and enable reuse.
I tend to think like this: The Web service interface is just one possible "way in" to the my business logic. So I might also have a RESTful service, or a JMS interface. Hence I tend to put my business logic inside an EJB, in simple cases a "No Interface" EJB. I focus on the EJB as a reusable piece of business logic that I can test in isolation. It will do all the JPA work. Then my Web service just uses that EJB to do its work. The EJB looks after the transactions so I don't need to write the transaction control code you have.
What does your Spring configuration for integration tests look like using an embedded h2 datasource and, optionally, JUnit?
My first try with a SingleConnectionDataSource basically worked, but failed on more complicated tests where you need several connections at the same time or suspended transactions. I think h2 in tcp based server mode might work as well, but this is probably not the fastest communication mode for a temporary embedded database in memory.
What are the possibilities and their advantages / disadvantages? Also, how do you create the tables / populate the database?
Update: Let's specify some concrete requirements that are important for such tests.
The database should be temporary and in memory
The connection should probably not use tcp, for speed requirements
It would be nice if I could use a database tool to inspect the content of the database during debugging
We have to define a datasource since we can't use the application servers datasource in unit tests
With the reservation that I do not know if there is any tool that can inspect the database, I think that a simple solution would be to use the Spring embedded database (3.1.x docs, current docs) which supports HSQL, H2, and Derby.
Using H2, your xml configuration would look like the following:
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:db-schema.sql"/>
<jdbc:script location="classpath:db-test-data.sql"/>
</jdbc:embedded-database>
If you prefer Java based configuration, you can instantiate a DataSource like this (note that EmbeddedDataBase extends DataSource):
#Bean(destroyMethod = "shutdown")
public EmbeddedDatabase dataSource() {
return new EmbeddedDatabaseBuilder().
setType(EmbeddedDatabaseType.H2).
addScript("db-schema.sql").
addScript("db-test-data.sql").
build();
}
The database tables are created by the db-schema.sql script and they are populated with test data from the db-test-data.sql script.
Don't forget to add the H2 database driver to your classpath.
I currently include in a test-only springconfig-file as a datasource:
<bean id="database.dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<constructor-arg>
<bean class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="org.h2.Driver" />
<property name="url"
value="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=2" />
</bean>
</constructor-arg>
</bean>
<!-- provides a H2 console to look into the db if necessary -->
<bean id="org.h2.tools.Server-WebServer" class="org.h2.tools.Server"
factory-method="createWebServer" depends-on="database.dataSource"
init-method="start" lazy-init="false">
<constructor-arg value="-web,-webPort,11111" />
</bean>
Creating / dropping the tables can be done by using executeSqlScript when overriding AbstractAnnotationAwareTransactionalTests.onSetUpBeforeTransaction, or with SimpleJdbcTestUtils.executeSqlScript in an appropriate place.
Compare also this posting.
H2 is bundled with a built-in connection pool implementation. The following XML provides an example of using it as a Datasource bean without a need to introduce additional dependencies on DBCP or C3P0:
<bean id="dataSource" class="org.h2.jdbcx.JdbcConnectionPool" destroy-method="dispose">
<constructor-arg>
<bean class="org.h2.jdbcx.JdbcDataSource">
<property name="URL" value="jdbc:h2:dbname"/>
<property name="user" value="user"/>
<property name="password" value="password"/>
</bean>
</constructor-arg>
</bean>
The database will be shut down by calling a dispose method when Spring application context closes.
I think it's best to use your production DataSource implementation (only with different connection-string) for the unit-tests.
Anyway "failed on more complicated tests" doesn't give enough information for a more detailed answer.
(Self-ad : check this)