Monday, 17 August 2015

Primary key violation exception in JPA


How do we resolve Primary key violation exception, when we have our primary key Id being created by a sequence generator?

When we work in a cluster server environment, for example, in Weblogic server we have Admin server, managed1, managed2 and so on, there are multiple requests being handled simultaneously at the same time. This is generally done for to enable you to balance loads and provide fail over protection for critical applications.

When we have our Enterprise application or a Web Application being deployed in such a clustered environment, which have its database transaction handled by JPA specification for persistence, instead of a plane JDBC. Here, we usually concentrate on business requirement implementation and rely on the server and the framework to handle our database transaction.


Cause:

Creating a new record in a particular table requires creation of a new entity instance in the persistence context. A fully populated object would be in its persistent state and then after a commit would be in a detached state. We have a sequence generator, usually for our primary key Id generation instead of a manual Id creation ,to generate the value for Id, Weblogic does its own caching in persistent context.

In a cluster environment there are separate instances of persistence context per managed server. There could be problem when multiple new object created and remain in persistent state. This could result in the Id having the same value increment, and thus result a Primary key violation exception. 

Solution:


 There are two steps to resolve this issue:

1) In your Entity class, while writing a "sequenceGenerator" for your primary key ID generation, mention the attribute "allocationSize=0". By assigning Allocation size to zero disable the generation of  Id from persistence context cache and forces to query to fetch the latest Id value from database and then increment it to generate a new value. if we do not specify the allocation size attribute the default size for allocation size is 50.   

For example, as below:

@Entity
public class Employee implements Serializable {
 
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="empSeq")
@SequenceGenerator(name="empSeq",sequenceName="EMP_SEQ", allocationSize=0)
private long id;
  • In @GeneratorValue attribute generator refers to the @SequenceGenerator mentioned below.
  • In @SequenceGenerator the sequenceName attribute the name of the sequence created and defined in database.
2) This is the second step, and may be optional too. Required if you are still not able to resolve the issue after performing step one. 
Also, modify your existing SQL or create SQL query for EMP_SEQ sequence creation in database, in following manner:

 CREATE SEQUENCE EMP_SEQ START WITH start_num, INCREMENT BY increment_num, NOCYCLE, NOCACHE; 
  • The start_num mentioned above for START WITH must be a value greater than the  maximum record's Id value present in data base.
  • The increment_num could be any value to be any positive integer. This is the difference between two contiguous Id value.
  • NOCYCLE specifies the sequence cannot generate any more integers after reaching its maximum or minimum value.
  • CACHE cache_num specifies the number of integers to keep in memory. NOCACHE specifies no integers are to be stored.

Hopefully with above two mentioned resolutions we can overcome the primary key/ unique constraint violation exception when we are working in a weblogic clustered server environment and the persistence layer is implemented with JPA.  
Note: Do not forget to clear your weblogic cache and restarting the server after performing the above steps.  


Monday, 10 September 2012

Generate Web Service Client with JAX-WS

Generate Web Service Client with JAX-WS Maven Plugin:
 
There are many ways and techniques to create a web service client in java, however here, in my this blog I am creating a web service client project with JAX-WS using maven

JAX-WS allows us to invoke a web service, as if we were making a local method call. For this to happen a standard mapping from WSDL to Java has been defined.
The Service Endpoint Interface (SEI) is the Java representation of the web service endpoint.
At runtime JAX-WS creates an instance of a SEI that can be used to make web service calls by simply making method calls on the SEI.
The stubs have been generated by the WSDL. So the stubs are a prerequisite.


Now to begin with, create a simple project using maven, this project would be your web service client.


1) Maven Configuration:

Into your pom.xml file add the following plugin:

<plugin> 
   <groupId>org.jvnet.jax-ws-commons</groupId> 
      <artifactId>jaxws-maven-plugin</artifactId> 
<version>2.1</version> 
<executions>
<execution> 
<goals> 
<goal>wsimport</goal> 
</goals>
</execution> 
</executions>
<configuration> 
<packageName>com.sample.stub</packageName> 
<wsdlDirectory>WebServiceDescription</wsdlDirectory>
<sourceDestDir>src/main/java</sourceDestDir> 
</configuration> 
</plugin> 

 
Create a directory named WebServiceDescription, as specified in the above plugin (between the tag <wsdlDirectory>) and place your wsdl file into this directory.

2) Generating stub classes:

For generating stub use the following maven command

mvn clean jaxws:wsimport

The above command jaxws:wsimport generates JAX-WS portable artifacts used in JAX-WS clients and services. The tool reads a WSDL and generates all the required artifacts for web service development, deployment, and invocation.

Check the com.sample.stub package it should contain all the required stub classes. Which comprise of
Service class
Object-Factory class
service-method class
returntype class 
package-info class etc.

3) Access the Web service:

Here is a custom Java class code used to access




package com.sample.client;

import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import com.sample.stub.CustomerInfoBean;
import com.sample.stub.CustomerInfoBeanService;
import com.sample.stub.CustomerType;

public class CustomerInfoClient {

public static void main(String[] args) {

try {
QName qName = new QName("http://sample.com/","CustomerInfoBeanService");
URL url = new URL("http://localhost:7001/CustomerInfoBean/CustomerInfoBeanService?WSDL");
CustomerInfoBeanService wsClient = new CustomerInfoBeanService(url,qName);
CustomerInfoBean wsPort = wsClient.getCustomerInfoBeanPort();
CustomerType response = wsPort.getCustomerInfo(1);
System.out.println("Customer Id: "+response.getCustomerId());
System.out.println("Customer Name: "+response.getCustomerName());
} catch (MalformedURLException e) {
 e.printStackTrace();
}
catch (Exception e) {
 e.printStackTrace();
}

}
}

 Above I am accessing a web service which I had created in my previous blog.
  • Now, let me explain some of the above code snippet. Beginning with QName, QName object is an object that represents an XML qualified name. The object is composed of a namespace URI and the local part of the qualified name i.e. the service name CustomerInfoBeanService.
  • In the next line, the URL object file points to the WSDL that was deployed:
    http://localhost:7001/CustomerInfoBean/CustomerInfoBeanService?WSDL
  • With the next line of code we are able to get through the service. The  wsClient is the service object.
  • Further we create a port, this can be done by invoking the get port method on service object. The method name usually begin is getPortTypePort() where  PortType is as specified in wsdl.
  • At this point we have got the service port. We can now invoke our method on this port.


Output: 

Customer Id: 1
Customer Name: abc


Done, any comments are appreciated.


Visit blogadda.com to discover Indian blogs

Wednesday, 5 September 2012

EJB Web Service that returns complex response.

EJB Web Service that returns complex response.



Basically, one of the major advantage to create an EJB and present it as a Web service class is that, the Service could be accessed both using SOAP and RMI by simply adding a Remote Interface.
 We would be using JAX-WS approach for Web Service creation. JAX-WS relies on the annotation feature of Java 5. 

So first thing first: let's assume we are developing EJB application which is exposed as web service. This web service returns a complex type.

Create an EJB project. I have created using maven. Here is a sample Customer project that gets Customer info.

For your maven configuration, pom.xml file of EJB project should have the following:

Specify the packaging as ejb.

<packaging>ejb</packaging>

Include the following dependency-

                <dependency>
 <groupId>javax.ejb</groupId>
   <artifactId>ejb-api</artifactId>
     <version>3.0</version>
    </dependency>

Add the following plugin-

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-ejb-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <ejbVersion>3.0</ejbVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>



Following classes are needed:

1. A Customer POJO class.


package com.sample;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="customer")
@XmlType(name = "customerType", propOrder = {
     "customerId",
     "customerName"
 })
public final class Customer {
 private int customerId;
 private String customerName;

  @XmlElement(namespace="http://sample.com")
 public int getCustomerId() {
  return customerId;
 }

  public void setCustomerId(int customerId) {
  this.customerId = customerId;
 }

  @XmlElement(namespace="http://sample.com")
 public String getCustomerName() {
  return customerName;
 }

  public void setCustomerName(String customerName) {
  this.customerName = customerName;
 }
}


As you can see above the XML annotations- the JAXB annotation, the class JAXB annotated should be marked as final to support their usage as an immutable object. 

@XmlRootElement - Marks a java class as being mapped to an element in XML/XSD.
name parameter should be, by convention, the class name in lower camel case.
@XmlAccessorType - Specifies a default strategy for serializing all fields contained in the java class.
The value should always be set to XmlAccessType.NONE. This means that no fields are serialized to XML, including inherited fields, unless the fields are explicitly JAXB annotated. This allows us full control to dictate what elements are the type actually make it to/from XML during serialization instead of relying on JAXB to make best guesses or rely on default behavior.
@XmlType - Defines the schema for the Xml element.
name parameter should be, by convention, the name of the class (case preserved) appended with Type. E.g. Customer has a type of CustomerType
propOrder Every field in the class that is annotated as XmlElement needs to be in the propOrder array with a string that matches the field name exactly.

@XmlElement - Fields that are annotated would be serialized.
Each field must have an entry in the @XmlType propOrder array that matches the field name exactly.

2. A Remote Interface- Since I am making this bean Remote.

package com.sample;

import javax.ejb.Remote;
import javax.jws.WebService;

@WebService
@Remote
public interface CustomerInfo {
public Customer getCustomerInfo(int customerId);

}



@WebService- This is mandatory. Marks the interface as a SOAP service. It corresponds directly to the <wsdl:definitions> root element in a WSDL file.

@Remote- To make a remote Session bean.


3. A stateless session bean


package com.sample;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

@Stateless
@WebService
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class CustomerInfoBean implements CustomerInfo {
@WebMethod
@WebResult(name = "getCustomerInfoReturn", targetNamespace = "http://sample.com")
public Customer getCustomerInfo(@WebParam(name = "customerId") int customerId)
{
// Sample Implementation.. do it your way...
List<Customer> customerList = new ArrayList<Customer>();
Customer c1 = new Customer();
c1.setCustomerId(1);
c1.setCustomerName("abc");
Customer c2 = new Customer();
c2.setCustomerId(2);
c2.setCustomerName("pqr");
Customer c3 = new Customer();
c3.setCustomerId(3);
c3.setCustomerName("xyz");
customerList.add(c1);
customerList.add(c2);
customerList.add(c3);
Customer customer = null;
Iterator<Customer> it = customerList.iterator();
while (it.hasNext()) {
Customer element = (Customer) it.next();
if (customerId == element.getCustomerId()) {
customer = element;
}
}
return customer;
}
}


@Stateless- Specify the java class to be a stateless session bean.

@WebService- endpointInterface Specifies the full name of the SEI that the implementation class implements. This property is only used on a service implementation class.

@SOPBinding- This annotation is defined by the javax.jws.soap.SOAPBinding interface. It provides details about the SOAP binding used by the service when it is deployed.
style- Specifies the style of the SOAP message. In DOCUMENT The content of <soap:Body> is specified by XML Schema defined in the <wsdl:type> section.
use- Specifies how the data of the SOAP message is streamed.
parameterStyle- A parameter style of WRAPPED means that all of the input parameters are wrapped into a single element on a request message and that all of the output parameters are wrapped into a single element in the response message. 

@WebMethod- This annotation provides the information that is normally represented in the wsdl:operation element describing the operation to which the method is associated.

@WebResult- The this annotation allows you to specify the properties of the generated wsdl:part that is generated for the method's return value.
name- Specifies the name of the return value as it appears in the WSDL.For document bindings, this is the local name of the XML element representing the return value. 
targetNamespace- Specifies the namespace for the return value. It is only used with document bindings where the return value maps to an XML element. The defaults is to use the service's namespace.
Note: For Complex type response the attributes value would be null, if the @WebResult annotation is not used. 

@WebParam- This annotation is necessary as java interfaces do not store the Parameter name in the .class file. So if you leave out the annotation your parameter will be named arg0.
name-Specifies the name of the parameter as it appears in the WSDL.

Most of the annotations have sensible defaults and do not need to be specified. However, the more information you provide in the annotations, the better defined your service definition. 


By their nature, SOAP and Web services are stateless, and hence stateless session beans are an ideal choice for exposing as Web services. Stateful Session Bean  cannot have a Web Service Endpoint Interface (SEI). Therefore we cannot expose Stateful session beans as a web service.

After writing the code for EJB project, its time now to create an EAR project. EJB modules is packaged in an EAR file.
The EAR project here is again being created with maven. The EAR project's pom.xml file contains

Specify the packaging as ear


<packaging>ear</packaging>

Include the following dependency


  <dependency>
      <groupId>com.sample.test</groupId>
 <artifactId>CustomerEJBProject</artifactId>
     <version>1.0</version>
 <type>ejb</type>
  </dependency>
               

Add the following plugin 

  <plugin> 
    <artifactId>maven-ear-plugin</artifactId>
<configuration>
    <earSourceDirectory>earSources</earSourceDirectory>
        <defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
          <modules>
             <ejbModule>
                 <groupId>com.sample.test</groupId>
                    <artifactId>CustomerEJBProject</artifactId>
             </ejbModule>
  </modules>
</configuration>
</plugin>


Build both the projects. The EAR is generated in the target folder of EAR project. Deploy the EAR in any of the EJB container server. I have used Weblogic 11g/JBoss 5.0

Check the WSDL file generated. 

For testing our application, I personally found soapUI to be very helpful tool in my developer toolbox and I definitely recommend using it.

The SOAP Request is as follows:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sam="http://sample.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <sam:getCustomerInfo>
         <customerId>1</customerId>
      </sam:getCustomerInfo>
   </soapenv:Body>
</soapenv:Envelope>

And SOAP Response is:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <ns2:getCustomerInfoResponse xmlns:ns3="http://sample.com" xmlns:ns2="http://sample.com/">
         <ns3:getCustomerInfoReturn>
            <ns3:customerId>1</ns3:customerId>
            <ns3:customerName>abc</ns3:customerName>
         </ns3:getCustomerInfoReturn>
      </ns2:getCustomerInfoResponse>
   </S:Body>
</S:Envelope>



I would like to conclude with some information. There are several ways to create EJB Web service.    Due to the use of annotations, here most of the important xml files like the ejb-jar.xml, web-services.xml, mapping.xml, config.xml etc are not being manually created by me. 


Visit blogadda.com to discover Indian blogs