28 Aralık 2010 Salı

revisited: migration from open esb + glassfish to apache tomcat + ode

please see http://hilaltarakci.blogspot.com/2010/03/migration-from-open-esb-glassfish-to.html for prior knowledge about the topic..
i have to migrate our processes from glassfish+open esb to apache tomcat+apache ode..
in this post, i simply note down differences or additions to the above prior post.
first of all, this time, i used latest versions:
  • apache ode : 1.3.4 instead of 1.3.3
  • apache tomcat: 7.0.5 instead of 6.0.24
  • metro: 2.0.1 instead of 2.0
CATALINA_HOME, JAVA_HOME and JRE_HOME environment variables are defined properly.

While installing metro on tomcat, i used the command
ant -f metro-on-tomcat.xml install
and there is luckily no problems due to version changes..

the correct arrangement of web.xml and creation of sun-jaxws.xml under project-home/web/WEB-INF is not straightforward this time, since there is a number of web services deployed in the same .war file. so, i want to explain the details..
here some links:

a small tip: after rewriting web.xml and sun-jaxws.xml, in order to prepare the .war file under dist folder, right click and build the project in netbeans ide.. choosing clean and build results in wiping out sun-jaxws.xml and overwriting web.xml..

a sample web.xml
<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" 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_2_5.xsd">
<description>Balistika2010Ws</description>
<display-name>Balistika2010Ws</display-name>
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<description>JAX-WS endpoint - Service1</description>
<display-name>Service1</display-name>
<servlet-name>Service1</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>Service1</servlet-name>
<url-pattern>/ode/processes/Service1</url-pattern>
</servlet-mapping>
<servlet>
<description>JAX-WS endpoint - Service2</description>
<display-name>Service2</display-name>
<servlet-name>Service2</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>Service2</servlet-name>
<url-pattern>/ode/processes/Service2</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

a sample corresponding sun-jaxws.xml
<?xml version="1.0" encoding="UTF-8"?>

<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>
<endpoint
name='Service1'
implementation='tr.gov.tubitak.service.Service1'
url-pattern='/ode/processes/Service1'/>
<endpoint
name='Service2'
implementation='tr.gov.tubitak.service.Service2'
url-pattern='/ode/processes/Service2'/>
</endpoints>

The url-pattern attributes in web.xml and sun-jaxws.xml should match.

The implementation attribute is the web service itself..

However, tomcat throws the following error:
SEVERE: WSSERVLET11: failed to parse runtime descriptor: javax.xml.ws.WebServiceException: Unable to create JAXBContext
javax.xml.ws.WebServiceException: Unable to create JAXBContext
at com.sun.xml.ws.model.AbstractSEIModelImpl.createJAXBContext(AbstractSEIModelImpl.java:166)
...
Caused by: java.security.PrivilegedActionException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
javax.persistence.EntityManager is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at javax.persistence.EntityManager
at public javax.persistence.EntityManager tr.gov.tubitak.uzay.balistika2010.sas.service.series.jaxws.MergeAbsEvidGrpsInCase.arg1
at tr.gov.tubitak.uzay.balistika2010.sas.service.series.jaxws.MergeAbsEvidGrpsInCase
javax.persistence.EntityManager does not have a no-arg default constructor.

The error is due to the fact that i pass EntityManager between (public) method calls in order to preserve my transactions.. see this for details: http://hilaltarakci.blogspot.com/2010/12/persistence-using-jpa.html

so, how to fix this? for now, i redesigned the code in such a way that EntityManager passing methods are all defined as private..

in fact, defining problematic methods as private solved some other weird errors as well.. i do not record them, since i did not understand their nature!!

at this point, web services are all deployed successfully and i can see wsdl s..

now the bpel part.. if you do not bind all partner links that is used in mentioned process in deploy.xml, you get the following error:
16:52:58,729 ERROR [NStateLatch] Latch error, was releasing for state 1 but actually in -1
16:52:58,731 WARN [ProcessStoreImpl] Deployment failed within the engine, store undeploying process.
java.lang.IllegalArgumentException: SecurityPL must be bound to an endpoint in deploy.xml
at org.apache.ode.bpel.engine.BpelProcess.setRoles(BpelProcess.java:519)

deploy.xml of ode-home/examples/DynPartner is a good sample..

now, it is time to test deployed processes from a java client.. i created client side artifacts from manually written wsdl in the deployed bpel module, not from the endpoint itself..

when i called the process from the client, i got the following error:

SEVERE: org.objectweb.asm.ClassWriter.(I)V
java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter.(I)V
at net.sf.cglib.core.DebuggingClassWriter.(DebuggingClassWriter.java:47)
...
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:126)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:51)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:33)
at tr.gov.tubitak.uzay.balistika2010.sas.dao.base.BlsEntityManager.getEm(BlsEntityManager.java:20)
at tr.gov.tubitak.service.Service1.method1(Service1.java:116)

no need to say, the process calls a web service which persists data inside a transaction.. according to http://www.myeclipseide.com/PNphpBB2-viewtopic-t-24287.html, the error was due to conflicting asm.jar s around.. actually, i faced the same problem before in a different environment: http://hilaltarakci.blogspot.com/2010/02/javalangnosuchmethoderror.html
in deployed web services library, asm.jar was of version 1.5.3; upgrading it to version 3.3.1 solved the mentioned error..

last update on 29.12.2010, 11:30..

22 Aralık 2010 Çarşamba

using blob field with jpa and web services

In the project, client side has to store local machine specific data in the cenral database and this field has to be binary large object (blob).. Jpa with hibernate is used as orm tool..Unfortunately, according to http://opensource.atlassian.com/projects/hibernate/browse/JPA-8 jpa does not support java.sql.Blob.. Indeed, the following error shows up when i tried to do so:
// bean
import java.sql.Blob;
import javax.persistence.Lob;

class MyClass{
@Lob
@Column(name = "FLD_BLOB")
private Blob myBlob;
...
}

// the error when deployed on Glassfish (jaxws is used for web services)
javax.xml.ws.WebServiceException: Unable to create JAXBContext ...
Caused by: java.security.PrivilegedActionException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
java.sql.Blob is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.sql.Blob
at public java.sql.Blob
...
java.sql.Blob does not have a no-arg default constructor.
...
java.sql.Blob is an interface, and JAXB can't handle interfaces.
...

So, use byte [] instead of java.sql.Blob

Web service using the bean with blob field is succesfully deployed and in the wsdl, the blob field is like this:
< xs:element name= " myBlob " type= " xs:base64Binary " minoccurs= " 0 " >
Moreover, when client side stubs are generated, the field is again generated as byte []..

Testing the blob field:
I used the code at http://www.java-tips.org/java-se-tips/java.io/reading-a-file-into-a-byte-array.html in order to prepare test data from a file and the following lines to write back the read bytes into a file to test correctness:

FileOutputStream fos = new FileOutputStream( "blobDataReadFromDB.png");
fos.write(myBean.getMyBlob());

The test data is a 5.4 MB-mp3.

Two test cases are considered.
In the first test case, the web services are treated as applications and tested without deployment. The blob field is successfully persisted and retrieved from database in this case..
In the second test case, web services are deployed and then tested.. The blob data is persisted successfully, but, the following error shows up when trying to retreive the data: (the underlying database is postgresql..)
ERROR org.hibernate.util.JDBCExceptionReporter - Large Objects may not be used in auto-commit mode.
...
sun-org.hibernate.exception.GenericJDBCException: could not execute query at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
....
Caused by: org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
at org.postgresql.largeobject.LargeObjectManager.open(LargeObjectManager.java:200)

Here is someone in a similar situation: https://forum.hibernate.org/viewtopic.php?f=1&t=994742&start=0 The following answer in this link, worked for me:

You might need to put your DB operations into a transaction:
session.beginTransaction();
...
session.getTransaction().commit();

Normally, retrieve operations do not require a transaction since they leave the database unchanged.. You only use transactions for create, update and delete operations since they change database state.. However, retrieval of blob field require transaction as well, maybe due to paging..

I also used and tested the blob field through a bpel process.. Again, persistence and retrieval is successful..

21 Aralık 2010 Salı

parsing an xml portion (without dom)

My problem is trying to parse an xml portion stored as a string. In trivial case, this is pretty easy by using indexOf() and lastIndexOf() methods, however, when the namespace is dynamic, the problem becomes a little tricky. For instance, when looking for foo, the data may come between
<foo>foo data < /foo> or
<ns1:foo>foo data< /ns1:foo> or
<ns2:foo>foo data< /ns2:foo> and so on..

In my case, i used such a simple solution:

String upToFooPre = fullMessage.substring(0,fullMessage.lastIndexOf("foo&gt ;"));
String upToFoo = upToFooPre.substring(0, upToFooPre.lastIndexOf("&lt ;"));
String foo = upToFoo.substring(upToFoo.lastIndexOf(("&gt ;")) + 4 );



15 Aralık 2010 Çarşamba

changing hibernate log level

In this link, hibernate log level is changed programmatically:
http://stackoverflow.com/questions/847041/how-do-i-change-hibernate-logging-level

I adopted this way..

Logger.getLogger("org.hibernate").setLevel(Level.ERROR);

However, as the link says, this solution makes you dependent on the logger implementation.

14 Aralık 2010 Salı

How to generate JAX-WS Client classes that implement the Serializable interface

The serializable interface vanishes when client side stubs are generated using jax ws..

Here is a solution to keep serializable interface:

There is also a plugin solution:

However, the binding file i previously used for XMLGregorian Calendar vs Date issue worked for that, too.. So, i stick to it:
For details, please see the previous post:

a correction may require in wsdl files if this error comes up:
[ERROR] XPath evaluation of "wsdl:definitions/wsdl:types/xsd:schema" results in too many (8) target nodes

<xsd:schema>
<xsd:import namespace="http://..." schemaLocation="http://...Service?xsd=1"></xsd:import>
</xsd:schema>
<xsd:schema>
<xsd:import namespace="http://..." schemaLocation="http://...Service?xsd=2"></xsd:import>
</xsd:schema>
<xsd:schema>
<xsd:import namespace="http://..." schemaLocation="http://...Service?xsd=2"></xsd:import>
</xsd:schema>

edit as follows, so it contains exactly one xsd:schema element:

<xsd:schema>
<xsd:import namespace="http://..." schemaLocation="http://...Service?xsd=1"></xsd:import>
<xsd:import namespace="http://..." schemaLocation="http://...Service?xsd=2"></xsd:import>
<xsd:import namespace="http://..." schemaLocation="http://...Service?xsd=2"></xsd:import>
</xsd:schema>

13 Aralık 2010 Pazartesi

persistence using jpa

I have one database, but the atomicity of transactions is large. In other words, many entities must be manipulated in one transaction. Therefore, the design is something like that:
  • a general superclass entity that holds shared stuff amongst all other entities that are subject to be persisted.
  • an entity manager class that is responsible for creation of emf and em.
  • a general dao for the superclass mentioned above, to accomplish shared, general persistence tasks (crud operations - create, retrieve, update, delete ). The entity class type and an entity manager is injected to this dao.
  • specific dao classes for entities that needs operations other than crud. Something to note down is that since transaction management must be done in an upper layer in this case, no begin, commit or rollback transaction operation appear at dao (persistence) layer.
// general superclass
@MappedSuperclass
public class MyBean implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id = -1L;
// ...
}

//////////////////////////////////////////////////////////////
// a specific class
public class SpecificBean extends MyBean {
// ...
}

//////////////////////////////////////////////////////////////
// entity manager class
public class MyEntityManager {

private static final String PERSISTENCE_UNIT = "MyPU";

@PersistenceUnit(unitName = PERSISTENCE_UNIT)
private EntityManagerFactory emf;

public EntityManager getEm() {
if (emf == null) {
emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
}
return emf.createEntityManager();
}
}

//////////////////////////////////////////////////////////////
// general dao for superclass MyBean
public class MyBeanDao {

private Class clazz;
protected EntityManager em;

public MyBeanDao(Class clazz, EntityManager em) {
this.clazz = clazz;
this.em = em;
}

public void create(MyBean bean) {
em.persist(bean);
}

public MyBean retrieve(Long id) {
return (MyBean) em.find(this.clazz, id);
}

public void remove(Long id) {
MyBean bean = retrieve(id);
if (bean != null) {
em.remove(bean);
}
}

public MyBean update(MyBean bean) {
MyBean updated = em.merge(bean);
return updated;
}

public void closeEm() {
em.close();
}

public void initTransaction() {
em.getTransaction().begin();
}

public void finishTransaction() {
em.getTransaction().commit();
}

public void rollbackTransaction() {
em.getTransaction().rollback();
}
}

//////////////////////////////////////////////////////////////
// specific dao classes
public class SpecificDao extends MyBeanDao {

public SpecificDao (EntityManager em) {
super(SpecificBean.class, em);
}
// extra methods
}

//////////////////////////////////////////////////////////////
// sample call

MyEntityManager mem = new MyEntityManager ();
EntityManager em = mem.getEm();

SpecificDao dao = new SpecificDao (em);

dao.initTransaction();
// do something
// ....
dao.finishTransaction();



more effective solutions may exist.. this is just a sample design..

11 Aralık 2010 Cumartesi

object cloning in java

java objects are manipulated via reference variables, there is no way to copy an object in java directly.. clone() method of Object class is used to provide a standard copying mechanism. clone() returns an Object, so dont forget to recast..
There is also the shallow copy - deep copy issue to deal with.. In shallow copy only the surface portion of the object is copied, as in the case of Arraylist s overrided clone().
A property of shallow copies is that fields that refer to other objects will point to the same objects in both the original and the clone. (http://javatechniques.com/blog/faster-deep-copies-of-java-objects/)
Copying the object entirely is the deep copy..
In order to make a class with the ability of deep copying itself:
  • default clone() implementation throws CloneNotSupportedException (if class is not implementing Cloneable interface)
  • implement Cloneable interface
  • make overrided clone() implementation public and do super.clone() (as in all Collections clone() methods)
  • Object s clone() only makes shallow copy, so write your implementation for a deep copy..

  • public class SampleClass implements Cloneable {
    ...
    public Object clone() throws CloneNotSupportedException {
    return super.clone();
    }
    }

    Serializing and reconstructing when the object is extremely complex, is also a solution to deep copying problem.. Besides, in http://javatechniques.com/blog/faster-deep-copies-of-java-objects/, the code presents a faster way of making deep copy..

    http://www.go4expert.com/forums/showthread.php?t=5424
    http://www.jguru.com/faq/view.jsp?EID=20435 (this is the solution i used, since i have complex serializable objects..)

    7 Aralık 2010 Salı

    WS-SecureConversation and WS-Atomic Transaction

    In our project, we needed a way to provide security in an efficient way and WS-Security is a bit heavy and inefficient.
    We have found a great WSIT tutorial and decided to use WS-SecureConversation which is almost twice faster than WS-Security according to our tests (tests carried out calling a simple web service 10000 times).
    The link to tutor: http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/reference/tutorials/wsit/doc/index.html
    and pdf version is at http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/reference/tutorials/wsit/doc/WSITTutorial.pdf

    We also need to manage transactions and worked on WS-AT by using the sample at http://wiki.open-esb.java.net/Wiki.jsp?page=HTTPBCWSAtomicTransaction which is linked from http://wiki.open-esb.java.net/Wiki.jsp?page=UsingWSTransaction

    However, our client is not a j2ee, so WS-AT is not appropriate for such an environment (http://java.net/jira/browse/WSIT-526)

    Now, our direction is to handle transactions in bpel processes themselves.. i will write about it, when we discover something.. a starting point : http://wikis.sun.com/display/JavaCAPS/Transactionality+-+BPEL2.0+SE
    And, a summary of the wsit tutorial i mentioned above, will be one of the next posts..