Sunday, February 10, 2013

JPQL vs. Criteria


Document  Version 1.0
A simple  "User.java" persistence entity will be used in test. To make the test simple, we will just test "SELECT" behavior of the JPQL and Criteria.

1. The persistence entity "User.java":

The "User.java" class has only 2 fields:

  • id, of type Long
  • name,  of type String

2. Coding Effort: "SELECT" User


"SELECT" using JPQL:

...
Query q = em.createQuery("SELECT u From User u WHERE u.name=:name",
User.class);
q.setParameter("name", "hehe");

List<User> result = q.getResultList();
...
                     


"SELECT" using Criteria API:

...

CriteriaQuery<User> query =cb.createQuery(User.class);
Root<User> aUser = query.from(User.class);
query.where(cb.equal(aUser.<String>get("name"), cb.parameter(String.class, "userName")));

TypedQuery<User> tq = em.createQuery(query);
tq.setParameter("userName", "hehe");

List<User> result = tq.getResultList();
...

Apparently the coding effort using JPQL is less than that when using Criteria.



3. Usability: "SELECT" User

For someone who is familar with SQL, he might feel very comfortable with JPQL syntax, however Criteria is not so straightforward.

For someone who use Criteria, he must also know what is SQL "from", "where".., so he is not going to have big problem with JPQL.


4. Performance   

According to JPA documentation,  "JPQL query is parsed for each call", where Criteria NOT, so criteria should perfoms better.

We will take data retrieve as example, to see if and how much is the performance diference actually.

Test run 1:



Test run 2:


The averave of 2 test runs:


The conclusion:


Friday, February 8, 2013

Deploy JAX-WS Web Service on Tomcat and JBoss

Document  Version 1.0

Table of Contents

1. Create a Dynamic Web Project in Eclipse
2. Implement the "JaxWsSample" Web Service
3. Deploy the Web Service in JEE Container JBoss7
4.Test "HelloWorld" Web Service using SAOP UI
   4.1 Download and install SOAP UI
   4.2 Create a new SOAP UI project
   4.3 Call "HelloWorld" Web Service
5. Deploy the Web Service in Tomcat 7
    5.1 Download Tomcat Extras  -  "catalina-ws.jar"
    5.2 Down JAX-WS RI lib
    5.3 Configure JAX.WS Servlet and Listener
    5.4 Add "sun-jaxws.xml"
    5.5 Deploy "JaxWsSample.war" in Tomcat 7
    5.6 Test "HelloWorld" Web Service using SAOP UI
    5.7 Does the "HelloWorld" Web Service still work in JBoss 7 ?
6. To sum it up




With JAX-WS framework, developmet of Web Service  is made very easier and straightworward. No boilerplate code like interfaces are needed any more, configuration is reduced to minmum...  A developer can finally focus on the his work, i.e. the problem to solve.

However, dependend on if the underly container is a JEE container or Servlet container, the packaging, deplyoment, and even accessing of JAX-WS is also slightly different. In this post, we will show what are the differences exactly by implementing a simple web service, first deploly it in JBoss 7 application server, and than migrate to Servlet Container Tomcat 7.



1. Create a Dynamic Web Project in Eclipse

As development tool we will use "Eclipse IDE for Java EE Developers". We assume you have at least basic knowledge of using Eclipse IDE.

Following the steps to create a dynamic web project in Eclipse:


Select "Dynamic Web Project", click "Next"


Type "JaxWsSample" as Project Name. In the dropdown list of "Dynamic web module version", make sure "3.0" is selected. Click "Next".


Select checkbox "Genereate web.xml deployment descriptor", and click "Finish". Now you have created a web application project named "JaxWsSample" with following directory structure:




Click and open the file "web.xml", you will see the file is almost emtpy except the declaration of name space and schemas. For now will leave this file as it is, since no specific configuration is need to do here for deployment on JEE container.


<?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" 
                id="WebApp_ID" version="3.0">

     <display-name>JaxWsSample</display-name>
</web-app>



2. Implement the "JaxWsSample" Web Service

We will create a simple "HelloWorld" web service which has only  one operation "sayHello". As mentioned, for JAX-WS  style web service, boilerplate code like interfaces are NOT needed any more. In our case, the impementation of the "HelloWorld" service contains only one class, i,e. "HelloWorld.java":



package sample.ws;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService()
public class HelloWorld {

@WebMethod    //(operationName = "hello")
public String sayHello(@WebParam(name = "name") String name) {
          return "Hello " + name + "!";
}
}




3. Deploy the Web Service in JEE Container JBoss 7

To deploy the "HelloWorld" service in a JBoss 7 container, there is no extra coding or configuration necessary.

What still need to be done is nothing else than packaging the  "JaxWsSample" in a "war" archive, and put it in the "deployments" folder of a running JBoss 7 container.


  • Start JBoss 7 Application Server in standalone mode
  • Export  "JaxWsSample" as "JaxWsSample.war"




  • The "Destination" should point to the "deployments" directory of the JBoss installation:





We assume the JBoss is up and running, then click "finish" Button in the above window will  export the "JaxWsSinmple.war" to JBoss, and the "war" is deployed in JBoss.

Try opening following URL in your Web Browser "http://localhost:8080/JaxWsSample/HelloWorld?wsdl", you will be shown the "wsdl" file of the "HelloWorld" web service.



4. Test "HelloWorld" Web Service using SOAP UI

To test the "HelloWorld" Web Servcie, we need a Web Service Client. We will use SAOP UI for this.


4.1 Download  and install SOAP UI

Download SAOP UI from www.soapui.org. After installation, start SOAP UI.


4.2 Create a  new SAOP UI project


Create a Web Service (client) project using following WSDL location:
 "http://localhost:8080/JaxWsSample/HelloWorld?wsd

Check the option "Create sample requests for all operations".



After click on the "OK" button, a "HelloWorld" web service client is created in SOAP UI. Open "Request 1".

 



4.3 Call "HelloWorld" Web Service

Replace the "?"  with text "hehe" for the "name" tag of "Request 1". Click the green run button to execute the "sayHello" web service call. 

The result of the web service call is show in the "response window": 







5. Deploy the Web Service in Tomcat 7


In this section we will try to deploy the "HelloWorld"  web service in a servlet container, i.e. Tomcat 7.

Different from JEE Conainer, Tomcat does NOT support JAX-WS out of box. To enable JAX-WS, followings have to be done:

  • include "catalina-ws.jar" in Tomcat lib
  • include "JAX-WS RI" libs
  • configure "jax-ws servlet" in web.xml
  • add "sun-jaxws-xml"


5.1 Download Tomcat Extras - "catalina-ws.jar"


Standard Tomcat delivery does NOT has libs supporting JAX-WS. We need to import "catalina-ws.jar" in Tomcat's "lib" directory. "catlina-ws.jar" belongs to Tomcat Extras, which could be downloaded here:

http://mirror.synyx.de/apache/tomcat/tomcat-7/v7.0.35/bin/extras/


5.2 Download JAX-WS RI libs

We need to include the JAX-WS runtime libs, i.e. JAX-WS RI (referencial implementation) in Tomcat. The lateste JAX-WS RI (2.2.7) could be downloaded here:

http://jax-ws.java.net/2.2.7/


Download and extract the arcive to you favorite location, for example to:


he@linux-7s1k:~/programms/jaxws-ri>
drwxr-xr-x  2 he users  4096 13. Aug 13:54 bin
-rw-r--r--  1 he users  7405 13. Aug 13:54 build.xml
-rw-r--r--  1 he users 38052 13. Aug 13:54 CDDL+GPLv2.txt
-rw-r--r--  1 he users  1673 13. Aug 13:54 distributionREADME_WMforJava2.0.txt
drwxr-xr-x  6 he users  4096 13. Aug 13:54 docs
drwxr-xr-x  3 he users  4096  6. Jan 18:18 lib
-rw-r--r--  1 he users 38052 13. Aug 13:54 LICENSE.txt
-rw-r--r--  1 he users  1039 13. Aug 13:54 README
drwxr-xr-x 39 he users  4096 13. Aug 13:54 samples
-rw-r--r--  1 he users 38607 13. Aug 13:54 ThirdPartyLicense.txt



The JAX-WS RI jars could be made available to Tomcat by including them in Tomcat's lib directory. Or you can include the jars in you Web Application's lib directory, in such case, the jars will be only available to the including Web Application.

We will take the second option and copy all jar files under

"/jaxws-ri/lib/"

to

"JaxWsSample" Eclipse project, and put the jars under

 "/WebContent/WEB-INF/lib"


5.3 Configure jax-ws servlet

Change "web.xml" file by adding  a "WSServletContextListener" and a "WSServlet":


<?xml version="1.0encoding="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" 
                id="WebApp_ID" version="3.0">

              <display-name>JaxWsSample</display-name>
              
               <listener>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
</listener-class>
</listener>

<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
</web-app>


5.4 Add "sun-jaxws.xml"

  Create a "sun-jaxws.xml" file in "WEN-INF" directory with following content:


<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
<endpoint name="HelloWorld" implementation="sample.ws.HelloWorld" url-pattern="/hello"/>
</endpoints>


5.5 Deploy "JaxWsSample.war" in Tomcat 7


We assume the Tomcat 7 is up and running. Export the "JaxWsSample" project as "war" archive in Tomcat's "webapps" direcdory. The deployment will be successful ff you see following info in Tomcat console:



...
06.02.2013 19:21:49 org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive /home/he/apache-tomcat-7.0.29/webapps/JaxWsSample.war
06.02.2013 19:21:53 com.sun.xml.ws.transport.http.servlet.WSServletDelegate <init>
INFO: WSSERVLET14: Initialisierung von JAX-WS-Servlet
06.02.2013 19:21:53 com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextInitialized
INFO: WSSERVLET12: Initialisierung von JAX-WS-Kontext-Listener
06.02.2013 19:21:53 com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextInitialized
INFO: WSSERVLET12: Initialisierung von JAX-WS-Kontext-Listener
...


Try opening following URL in your Web Browser "http://localhost:8080/JaxWsSample/hello?wsdl", you will be shown the "wsdl" file of the "HelloWorld" web service.

Please NOTE, the URL to Web Service and WSDL is different as those in JBoss.
In Tomcat:
http://localhost:8080/JaxWsSample/hello?wsdl

In JBoss:
http://localhost:8080/JaxWsSample/HelloWorld?wsdl


5.6 Test "HelloWorld" web service using SAOP UI

Repeat section 4.2-4.3 to test "HelloWorld" web service, when create web service client in SOAP UI, be sure to use "http://localhost:8080/JaxWsSample/hello?wsdl" for WSDL location.

When you have followed all the steps without mistake till now, you would see the correct response of "sayHello".

5.7 Does the "HalloWorld" web service still work when deployed in JBoss 7

Now we have successed "migrated" a JAX-WS web service running on JBoss 7 to Tomcat 7. You might wounder, after all these changes, does the "HelloWorld" service still work in JBoss 7 ? We will find it out now.

Stop Tomcat 7, and hence stop "HelloWorld" in Tomcat.
Start JBoss 7 standardalone server
Copy "JaxWsSample.war" from Tomcat "webapps" directory to   "deployments" directory of the JBoss installation.

You would see following info in JBoss 7 console:


...
21:31:33,602 INFO  [org.jboss.wsf.stack.cxf.metadata.MetadataBuilder] (MSC service thread 1-2) Add Service
 id=sample.ws.HelloWorld
 address=http://localhost:8080/SampleWS/HelloWorld
 implementor=sample.ws.HelloWorld
 invoker=org.jboss.wsf.stack.cxf.JBossWSInvoker
 serviceName={http://ws.sample/}HelloWorldService
 portName={http://ws.sample/}HelloWorldPort
 wsdlLocation=null
 mtomEnabled=false
21:31:33,698 INFO  [org.jboss.wsf.stack.cxf.metadata.MetadataBuilder] (MSC service thread 1-1) Add Service
 id=sample.ws.HelloWorld
 address=http://localhost:8080/JaxWsSample/HelloWorld
 implementor=sample.ws.HelloWorld
 invoker=org.jboss.wsf.stack.cxf.JBossWSInvoker
 serviceName={http://ws.sample/}HelloWorldService
 portName={http://ws.sample/}HelloWorldPort
 wsdlLocation=null
 mtomEnabled=false
..

The above info indicates that the deployment in JBoss till works!

Further more, you would find that the "HelloWorld" web service works too, and the service is even access able under 2 URLs:
http://localhost:8080/JaxWsSample/hello?wsdl
http://localhost:8080/JaxWsSample/HelloWorld?wsdl

6. To sum it up