29 Eylül 2009 Salı

jpa annotation reference documentation

for jpa annotations 

A cycle is detected in the object graph. This will cause infinitely deep XML

while trying to call a web service with the explained structure, such an error pops up at the client side:
com.sun.istack.internal.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: 

Parent.java
package deepxml;

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

public class Parent {

    private String name;
    private List childList = new ArrayList();

    public List getChildList() {
        return childList;
    }

    public void setChildList(List childList) {
        this.childList = childList;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Child.java
package deepxml;

public class Child {

    private String name;
    private Parent myParent;

    public Parent getMyParent() {
        return myParent;
    }

    public void setMyParent(Parent myParent) {
        this.myParent = myParent;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

DeepXml.java
package deepxml.service;

import deepxml.Child;
import deepxml.Parent;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService()
public class DeepXml {

    @WebMethod(operationName = "deepXml")
    public Parent deepXml(@WebParam(name = "parent")
    Parent parent, @WebParam(name = "childList")
    List childList) {
        parent.setChildList(childList);
        
        for(Child child: childList) {
            child.setMyParent(parent);
        }

        return parent;
    }
}

Main.java for client side
package deepxmlclient;

import deepxml.service.Child;
import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {
        try { // Call Web Service Operation
            deepxml.service.DeepXmlService service = new deepxml.service.DeepXmlService();
            deepxml.service.DeepXml port = service.getDeepXmlPort();
            deepxml.service.Parent parent = new deepxml.service.Parent();
            parent.setName("Parent");

            java.util.List childList = new ArrayList();
            Child child1 = new Child();
            child1.setMyParent(parent);
            child1.setName("Child1");

            Child child2 = new Child();
            child2.setMyParent(parent);
            child2.setName("Child2");

            parent.getChildList().add(child1);
            parent.getChildList().add(child2);

            deepxml.service.Parent result = port.deepXml(parent, childList);
            System.out.println("Result = "+result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

The bold lines in the client code results in the specified error, if you try with those lines commented out, there will be no problem at all.. Lucyly, this works in our situation :)

However, this may not be the correct solution in all cases, so lets try to find a real solution..
Here is the offered solution to the condition: https://jaxb.dev.java.net/guide/Mapping_cyclic_references_to_XML.html



18 Eylül 2009 Cuma

java deep clone library

http://robust-it.co.uk/clone/index.php

TODO: details will be given soon.. DONE!

Edit on 28/09/2009, 11:02:

maybe beanlib is a better, more talented alternative: http://beanlib.sourceforge.net/

here is call sample for both:

for cloner..
    Cloner cloner = new Cloner();
     cloner.nullInsteadOfClone(SessionImplementor.class,
                    JDBCTransaction.class,
                    SessionImpl.class,
                    org.hibernate.collection.PersistentBag.class); 

     List cloneResult = cloner.deepClone(result);

for beanlib..
    HibernateBeanReplicator r = new Hibernate3BeanReplicator();
     List cloneResult = r.deepCopy(result);

and 

10 Eylül 2009 Perşembe

read/write file with web service

after a totally sleepless night, this morning i was googling to find a binding for java.io.File in web services with an unclear mind and very upset since i was not even close to my intention :((

you know, type of the file parameter in the following service becomes string in the client side..

@WebMethod(operationName = "retrieveFile")
@Oneway
public void retrieveFile(@WebParam(name = "file")
File file) {
}

the wsdl

<xs:complexType name="retrieveFile"
>
<xs:sequence>
<xs:element name="file" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>

so, what to do ?
lucily, a friend in the team has searched for it before and came back with a solution:

http://m-button.blogspot.com/2008/07/building-jax-rpc-or-jax-ws-webservices.html

it is checked, guaranteed to work..

9 Eylül 2009 Çarşamba

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role- no session or session was closed

the exception is:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.ws.Library.bookList, no session or session was closed


so, one possible solution is to clone the entity if it will be used out of session..

a simple example web service project:

Book.java

package com.example.ws;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String title;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Book)) {
return false;
}
Book other = (Book) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "com.example.ws.Book[id=" + id + "]";
}

}

Library.java

package com.example.ws;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Library implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String name;

@OneToMany(fetch = FetchType.LAZY, cascade= CascadeType.ALL)
private List bookList = new ArrayList();

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public List getBookList() {
return bookList;
}

public void setBookList(List bookList) {
this.bookList = bookList;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Library)) {
return false;
}
Library other = (Library) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "com.example.ws.Library[id=" + id + "]";
}

}

HibernateUtil.java

package util;

import com.example.ws.Book;
import com.example.ws.Library;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;

/**
*
* @author hilal.tarakci
*/
public class HibernateUtil {

@PersistenceUnit(unitName = "HibernateLazyInitFixPU")
private EntityManagerFactory emf = null;

public EntityManager getEntityManager() {
if (emf == null) {
emf = Persistence.createEntityManagerFactory("HibernateLazyInitFixPU");
}
return emf.createEntityManager();
}

public void create(Library item) throws Exception {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
em.persist(item);
em.getTransaction().commit();
} catch (Exception ex) {
try {
if (em != null) {
em.getTransaction().rollback();
}
} catch (Exception re) {
re.printStackTrace();
}
throw ex;
} finally {
if (em != null) {
em.close();
}
}
}

public List retrieveRecordsOfBook() {

EntityManager em = getEntityManager();
try {
Query q = em.createQuery("select object(o) from Book as o");

List bookList = new ArrayList();
List tempBookList = q.getResultList();

for (Book tempBook : tempBookList) {
Book book = new Book();
book.setId(tempBook.getId());
book.setTitle(tempBook.getTitle());

bookList.add(book);
}

return bookList;
} finally {
em.close();
}

}

public List retrieveRecordsOfLibrary() {

EntityManager em = getEntityManager();
try {
Query q = em.createQuery("select object(o) from Library as o");

List libList = new ArrayList();

List tempLibList = q.getResultList();

for (Library tempLib : tempLibList) {
Library lib = new Library();
lib.setId(tempLib.getId());
lib.setName(tempLib.getName());

List bookList = new ArrayList();

for(Book tempBook: tempLib.getBookList()) {
Book book = new Book();
book.setId(tempBook.getId());
book.setTitle(tempBook.getTitle());

bookList.add(book);
}

lib.setBookList(bookList);

libList.add(lib);
}

return libList;

} finally {
em.close();
}

}
}

HibernateLazyInit.java
package com.example.ws.service;

import com.example.ws.Book;
import com.example.ws.Library;
import java.util.List;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebService;
import util.HibernateUtil;

@WebService()
public class HibernateLazyInit {

private HibernateUtil util = new HibernateUtil();

@WebMethod(operationName = "insertRecords")
@Oneway
public void insertRecords() {
try {
Book book1 = new Book();
book1.setTitle("A Good Story");

Book book2 = new Book();
book2.setTitle("A Bad Story");

Library library1 = new Library();
library1.setName("An Excellent Library");

library1.getBookList().add(book1);
library1.getBookList().add(book2);

util.create(library1);

} catch (Exception ex) {
ex.printStackTrace();
}
}

@WebMethod(operationName = "retrieveRecordsOfBook")
public List retrieveRecordsOfBook() {
return util.retrieveRecordsOfBook();
}

@WebMethod(operationName = "retrieveRecordsOfLibrary")
public List retrieveRecordsOfLibrary() {
return util.retrieveRecordsOfLibrary();


}
}

.. and the client call
public class Main {

void insertRecords() {

try { // Call Web Service Operation
com.example.ws.service.HibernateLazyInitService service = new com.example.ws.service.HibernateLazyInitService();
com.example.ws.service.HibernateLazyInit port = service.getHibernateLazyInitPort();
port.insertRecords();
} catch (Exception ex) {
// TODO handle custom exceptions here
ex.printStackTrace();
}

}

int retrieveRecordsOfBook() {

try { // Call Web Service Operation
com.example.ws.service.HibernateLazyInitService service = new com.example.ws.service.HibernateLazyInitService();
com.example.ws.service.HibernateLazyInit port = service.getHibernateLazyInitPort();
// TODO process result here
java.util.List result = port.retrieveRecordsOfBook();
System.out.println("Result = "+result);

return result.size();
} catch (Exception ex) {
// TODO handle custom exceptions here
ex.printStackTrace();

return 0;
}

}

int retrieveRecordsOfLibrary() {

try { // Call Web Service Operation
com.example.ws.service.HibernateLazyInitService service = new com.example.ws.service.HibernateLazyInitService();
com.example.ws.service.HibernateLazyInit port = service.getHibernateLazyInitPort();
// TODO process result here
java.util.List result = port.retrieveRecordsOfLibrary();
System.out.println("Result = "+result);

return result.size();

} catch (Exception ex) {
// TODO handle custom exceptions here
ex.printStackTrace();

return 0;
}

}

public static void main(String[] args) {
// TODO code application logic here

Main client = new Main();
client.insertRecords();
System.out.println("Size of books : " + client.retrieveRecordsOfBook() );
System.out.println("Size of library : " + client.retrieveRecordsOfLibrary() );
}

btw, the ide is netbeans 6.5.1 with glassfish.

Edit on 11:14 :
the above solution is good when you want to use standard jpa and stay away from hibernate specific solutions..
but if it is ok to use hibernate specific annotations, you can try @Fetch(FetchType.JOIN)..

Edit on 14/12/2010 :
HibernateBeanReplicator is also a solution.. see http://hilaltarakci.blogspot.com/2009/09/java-deep-clone-library.html for details..

7 Eylül 2009 Pazartesi

jpa inheritance mechanism

i do not reinvent the wheel by explaning jpa inheritance mechanism here, it is already well documented at many places one of which http://windhood.wordpress.com/2009/03/03/jpa-inheritance-overview/

instead, i mention a bug i have met.. i think it is a bug, correct me if i am wrong :)

assume there is a root class ClassA which ClassB inherits from.. and there is a ClassC which inherits from ClassB..

@Inheritance(strategy=InheritanceType.JOINED)
public ClassA {
...
}

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public ClassB extends ClassA {
...
}

public ClassC extends ClassB {
...
}

It does not matter which inheritance type you specified for ClassB, for all hierarchy, the inheritance type specified for ClassA, the very root class, is used. 
In above case, the inheritance strategy is JOINED for all..

well, that is all.. 

3 Eylül 2009 Perşembe

bpel fault handling - 2

i mentioned a bug in my previous post: http://hilaltarakci.blogspot.com/2009/09/bpel-fault-handling.html
(just read the lines in red ).. however, i was wrong, that was not the real bug..

the problem:
Lets repeat the scenario. There is a web service throwing some exception and there is a bpel process delegating exactly the same exception. Unfortunately, at the client side, the details of the exception comes null even though the exception is properly catched..


catch (FaultCatchWsdlOperationFault ex) {
MyException2 exc = ex.getFaultInfo();
}


the reason:
If the bpel process uses the same exception type with the invoked web service's exception, than there is something wrong and the detail of the exception (detail comes from the web service) does not come with exception.getFaultInfo() method in your client app.

the solution:
The workaround is using different types in web service and bpel faults.
i hope the explanation is clear enough :)

1 Eylül 2009 Salı

bpel fault handling

Understanding fault handling mechanism of bpel took time for me, so lets note down the issue..

i want to explain bpel fault handling in 2 steps.. In step 1, there is a bpel process which does nothing except for throwing an exception. In step 2, there is a sample web service throwing a user defined exception and bpel catches and throws that exception..

Process without web service :

Here are the files for the bpel module:
FaultWsdl.wsdl


<?xml version="1.0" encoding="UTF-8"?>
<definitions name="wsdl" targetNamespace="http://j2ee.netbeans.org/wsdl/wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl"
xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns0="http://xml.netbeans.org/schema/schema">
<types>
<xsd:schema targetNamespace="http://j2ee.netbeans.org/wsdl/wsdl">
<xsd:import schemaLocation="schema.xsd" namespace="http://xml.netbeans.org/schema/schema"/>
</xsd:schema>
</types>
<message name="wsdlOperationRequest">
<part name="part1" type="xsd:string"/>
</message>
<message name="wsdlOperationResponse">
<part name="part1" type="xsd:string"/>
</message>
<message name="wsdlOperationFault">
<part name="part1" element="ns0:faultstr"/>
</message>
<portType name="wsdlPortType">
<operation name="wsdlOperation">
<input name="input1" message="tns:wsdlOperationRequest"/>
<output name="output1" message="tns:wsdlOperationResponse"/>
<fault name="fault1" message="tns:wsdlOperationFault"/>
</operation>
</portType>
<binding name="wsdlBinding" type="tns:wsdlPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="wsdlOperation">
<soap:operation/>
<input name="input1">
<soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/wsdl"/>
</input>
<output name="output1">
<soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/wsdl"/>
</output>
<fault name="fault1">
<soap:fault use="literal" name="fault1" namespace="http://j2ee.netbeans.org/wsdl/wsdl"/>
</fault>
</operation>
</binding>
<service name="wsdlService">
<port name="wsdlPort" binding="tns:wsdlBinding">
<soap:address location="http://localhost:${HttpDefaultPort}/wsdlService/wsdlPort"/>
</port>
</service>
<plnk:partnerLinkType name="wsdl">
<!-- A partner link type is automatically generated when a new port type is added. Partner link types are used by BPEL processes.
In a BPEL process, a partner link represents the interaction between the BPEL process and a partner service. Each partner link is associated with a partner link type.
A partner link type characterizes the conversational relationship between two services. The partner link type can have one or two roles.-->
<plnk:role name="wsdlPortTypeRole" portType="tns:wsdlPortType"/>
</plnk:partnerLinkType>
</definitions>


schema.xsd i think jaxws wants the schema in a seperate file than the wsdl, at least netbeans web service client generation wizard does!


<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://xml.netbeans.org/schema/schema"
xmlns:tns="http://xml.netbeans.org/schema/schema"
elementFormDefault="qualified">
<xsd:element name="faultstr" type="xsd:string"></xsd:element>
</xsd:schema>


FaultProcess.bpel


<?xml version="1.0" encoding="UTF-8"?>
<process
name="FaultProcess"
targetNamespace="http://enterprise.netbeans.org/bpel/BpelFault1/Process1"
xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sxt="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Trace"
xmlns:sxed="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Editor"
xmlns:tns="http://enterprise.netbeans.org/bpel/BpelFault1/Process1">
<import namespace="http://j2ee.netbeans.org/wsdl/wsdl" location="FaultWsdl.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<partnerLinks>
<partnerLink name="PartnerLink1" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" partnerLinkType="tns:wsdl" myRole="wsdlPortTypeRole"/>
</partnerLinks>
<variables>
<variable name="Fault1FaultVar" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" messageType="tns:wsdlOperationFault"/>
<variable name="WsdlOperationOut" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" messageType="tns:wsdlOperationResponse"/>
<variable name="WsdlOperationIn" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" messageType="tns:wsdlOperationRequest"/>
</variables>
<sequence>
<receive name="Receive1" createInstance="yes" partnerLink="PartnerLink1" operation="wsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" portType="tns:wsdlPortType" variable="WsdlOperationIn"/>
<assign name="Assign1">
<copy>
<from>'This error is thrown from the bpel process'</from>
<to variable="Fault1FaultVar" part="part1"/>
</copy>
<copy>
<from variable="Fault1FaultVar" part="part1"/>
<to variable="WsdlOperationOut" part="part1"/>
</copy>
</assign>
<reply name="Reply1" partnerLink="PartnerLink1" operation="wsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" portType="tns:wsdlPortType" faultName="tns:fault1" variable="Fault1FaultVar"/>
</sequence>
</process>


and offcourse the client call code:


try {
org.netbeans.j2ee.wsdl.wsdl.WsdlService service = new org.netbeans.j2ee.wsdl.wsdl.WsdlService();
org.netbeans.j2ee.wsdl.wsdl.WsdlPortType port = service.getWsdlPort();
javax.xml.ws.Holder part1 = new javax.xml.ws.Holder();
part1.value = new String("test");
port.wsdlOperation(part1);
} catch (org.netbeans.j2ee.wsdl.wsdl.WsdlOperationFault ex) {
System.out.println("fault: " + ex.getFaultInfo() );
}


The expected output is :


fault: This error is thrown from the bpel process


and done :) However, when web service thrown exceptions are considered, not so easy :(

Process catching exception thrown by invoked web service:

The sample web service:

MyWebService.java


package ws;

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

@WebService()
public class MyWebService {

@WebMethod(operationName = "operation")
public String operation(@WebParam(name = "parameter")
String parameter) throws MyException {
throw new MyException("Exception thrown from web service :) ");
}
}


and the exception class..

MyException.java


package ws;

public class MyException extends Exception {
private String errorCode;

public MyException() {
}

public MyException(String msg) {
super(msg);
}

public String getErrorCode() {
return errorCode;
}

public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
}


Now the bpel module files:

FaultCatchProcess.bpel


<?xml version="1.0" encoding="UTF-8"?>
<process
name="FaultCatchProcess"
targetNamespace="http://enterprise.netbeans.org/bpel/BpelFault2/FaultCatchProcess"
xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sxt="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Trace"
xmlns:sxed="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Editor"
xmlns:tns="http://enterprise.netbeans.org/bpel/BpelFault2/FaultCatchProcess" xmlns:ns0="http://ws/">
<import namespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" location="FaultCatchWsdl.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<import namespace="http://enterprise.netbeans.org/bpel/MyWebServiceServiceWrapper" location="MyWebServiceServiceWrapper.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<import namespace="http://ws/" location="MyWebServiceService.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<partnerLinks>
<partnerLink name="PartnerLink2" xmlns:tns="http://enterprise.netbeans.org/bpel/MyWebServiceServiceWrapper" partnerLinkType="tns:MyWebServiceLinkType" partnerRole="MyWebServiceRole"/>
<partnerLink name="PartnerLink1" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" partnerLinkType="tns:FaultCatchWsdl" myRole="FaultCatchWsdlPortTypeRole"/>
</partnerLinks>
<variables>
<variable name="FaultToBpel" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" messageType="tns:FaultCatchWsdlOperationFault"/>
<variable name="OperationOut" xmlns:tns="http://ws/" messageType="tns:operationResponse"/>
<variable name="OperationIn" xmlns:tns="http://ws/" messageType="tns:operation"/>
<variable name="FaultCatchWsdlOperationOut" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" messageType="tns:FaultCatchWsdlOperationResponse"/>
<variable name="FaultCatchWsdlOperationIn" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" messageType="tns:FaultCatchWsdlOperationRequest"/>
</variables>
<faultHandlers>
<catch faultName="ns0:MyException" faultVariable="myExceptionFromWs" faultMessageType="ns0:MyException">
<sequence name="Sequence1">
<assign name="Assign3">
<copy>
<from variable="myExceptionFromWs" part="fault"/>
<to variable="FaultToBpel" part="part1"/>
</copy>
</assign>
<reply name="Reply2" partnerLink="PartnerLink1" operation="FaultCatchWsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" portType="tns:FaultCatchWsdlPortType" faultName="tns:fault1" variable="FaultToBpel"/>
</sequence>
</catch>
</faultHandlers>
<sequence>
<receive name="Receive1" createInstance="yes" partnerLink="PartnerLink1" operation="FaultCatchWsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" portType="tns:FaultCatchWsdlPortType" variable="FaultCatchWsdlOperationIn"/>
<assign name="Assign1">
<copy>
<from variable="FaultCatchWsdlOperationIn" part="part1"/>
<to variable="OperationIn" part="parameters"/>
</copy>
</assign>
<invoke name="Invoke1" partnerLink="PartnerLink2" operation="operation" xmlns:tns="http://ws/" portType="tns:MyWebService" inputVariable="OperationIn" outputVariable="OperationOut"/>
<assign name="Assign2">
<copy>
<from variable="OperationOut" part="parameters"/>
<to variable="FaultCatchWsdlOperationOut" part="part1"/>
</copy>
</assign>
<reply name="Reply1" partnerLink="PartnerLink1" operation="FaultCatchWsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" portType="tns:FaultCatchWsdlPortType" variable="FaultCatchWsdlOperationOut"/>
</sequence>
</process>


FaultCatchWsdl.wsdl


<?xml version="1.0" encoding="UTF-8"?>
<definitions name="FaultCatchWsdl" targetNamespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" xmlns:ns="http://ws/" xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<xsd:schema targetNamespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl">
<xsd:import namespace="http://ws/" schemaLocation="MyWebServiceService.xsd"/>
</xsd:schema>
</types>
<message name="FaultCatchWsdlOperationRequest">
<part name="part1" type="ns:operation"/>
</message>
<message name="FaultCatchWsdlOperationResponse">
<part name="part1" type="ns:operationResponse"/>
</message>
<message name="FaultCatchWsdlOperationFault">
<part name="part1" element="ns:MyException"/>
</message>
<portType name="FaultCatchWsdlPortType">
<operation name="FaultCatchWsdlOperation">
<input name="input1" message="tns:FaultCatchWsdlOperationRequest"/>
<output name="output1" message="tns:FaultCatchWsdlOperationResponse"/>
<fault name="fault1" message="tns:FaultCatchWsdlOperationFault"/>
</operation>
</portType>
<binding name="FaultCatchWsdlBinding" type="tns:FaultCatchWsdlPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="FaultCatchWsdlOperation">
<soap:operation/>
<input name="input1">
<soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl"/>
</input>
<output name="output1">
<soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl"/>
</output>
<fault name="fault1">
<soap:fault use="literal" name="fault1" namespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl"/>
</fault>
</operation>
</binding>
<service name="FaultCatchWsdlService">
<port name="FaultCatchWsdlPort" binding="tns:FaultCatchWsdlBinding">
<soap:address location="http://localhost:${HttpDefaultPort}/FaultCatchWsdlService/FaultCatchWsdlPort"/>
</port>
</service>
<plnk:partnerLinkType name="FaultCatchWsdl">
<!-- A partner link type is automatically generated when a new port type is added. Partner link types are used by BPEL processes.
In a BPEL process, a partner link represents the interaction between the BPEL process and a partner service. Each partner link is associated with a partner link type.
A partner link type characterizes the conversational relationship between two services. The partner link type can have one or two roles.-->
<plnk:role name="FaultCatchWsdlPortTypeRole" portType="tns:FaultCatchWsdlPortType"/>
</plnk:partnerLinkType>
</definitions>


The following wsdl and xsd are local copies for the web service wsdl..

MyWebServiceService.wsdl


<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3.1-hudson-749-SNAPSHOT. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3.1-hudson-749-SNAPSHOT. -->
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws/" name="MyWebServiceService">
<types>
<xsd:schema>
<xsd:import namespace="http://ws/" schemaLocation="MyWebServiceService.xsd"></xsd:import>
</xsd:schema>
</types>
<message name="operation">
<part name="parameters" element="tns:operation"></part>
</message>
<message name="operationResponse">
<part name="parameters" element="tns:operationResponse"></part>
</message>
<message name="MyException">
<part name="fault" element="tns:MyException"></part>
</message>
<portType name="MyWebService">
<operation name="operation">
<input message="tns:operation"></input>
<output message="tns:operationResponse"></output>
<fault message="tns:MyException" name="MyException"></fault>
</operation>
</portType>
<binding name="MyWebServicePortBinding" type="tns:MyWebService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding>
<operation name="operation">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
<fault name="MyException">
<soap:fault name="MyException" use="literal"></soap:fault>
</fault>
</operation>
</binding>
<service name="MyWebServiceService">
<port name="MyWebServicePort" binding="tns:MyWebServicePortBinding">
<soap:address location="http://localhost:8080/BpelFaultWS1/MyWebServiceService"></soap:address>
</port>
</service>
</definitions>


MyWebServiceService.xsd


<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3.1-hudson-749-SNAPSHOT. -->
<xs:schema xmlns:tns="http://ws/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://ws/">

<xs:element name="MyException" type="tns:MyException"></xs:element>

<xs:element name="operation" type="tns:operation"></xs:element>

<xs:element name="operationResponse" type="tns:operationResponse"></xs:element>

<xs:complexType name="operation">
<xs:sequence>
<xs:element name="parameter" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="operationResponse">
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="MyException">
<xs:sequence>
<xs:element name="errorCode" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="message" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>

MyWebServiceServiceWrapper.wsdl
<?xml version="1.0" encoding="UTF-8"?>

<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="MyWebServiceServiceWrapper" targetNamespace="http://enterprise.netbeans.org/bpel/MyWebServiceServiceWrapper" xmlns:tns="http://enterprise.netbeans.org/bpel/MyWebServiceServiceWrapper" xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype" xmlns:ns="http://ws/">
<import location="MyWebServiceService.wsdl" namespace="http://ws/"/>
<plnk:partnerLinkType name="MyWebServiceLinkType">
<plnk:role name="MyWebServiceRole" portType="ns:MyWebService"/>
</plnk:partnerLinkType>
</definitions>


However, i think there is a bug here when bpel called from a java or web client.. Yes, the exception thrown by the web service is caught properly, but the detail info just disappears :( While testing via test module of the composite app, there is not such bug..

Here is the test with xml:

input

<soapenv:Envelope xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:faul="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl">
<soapenv:Body>
<faul:FaultCatchWsdlOperation>
<part1>
<!--Optional:-->
<parameter>test</parameter>
</part1>
</faul:FaultCatchWsdlOperation>
</soapenv:Body>
</soapenv:Envelope>


output


<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode xmlns="">SOAP-ENV:Client</faultcode>
<faultstring xmlns="">fault1</faultstring>
<detail xmlns="">
<MyException xmlns="http://ws/">
<message>Exception thrown from web service :) </message>
</MyException>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>


here the client call:


try {
org.netbeans.j2ee.wsdl.faultcatchwsdl.FaultCatchWsdlService service = new org.netbeans.j2ee.wsdl.faultcatchwsdl.FaultCatchWsdlService();
org.netbeans.j2ee.wsdl.faultcatchwsdl.FaultCatchWsdlPortType port = service.getFaultCatchWsdlPort();
ws.Operation part1 = new ws.Operation();
part1.setParameter("test");
ws.OperationResponse result = port.faultCatchWsdlOperation(part1);
System.out.println("Result = "+result);
} catch (org.netbeans.j2ee.wsdl.faultcatchwsdl.FaultCatchWsdlOperationFault ex) {
System.out.println("My exception is : " + ex.getFaultInfo().getMessage());
}


and the output:

My exception is : null

PS: i wrote down whole files to make trying the code easier..
You know, most portions of the files are automatically generated..

Btw, my ide is Netbeans 6.5 and i deploy to glassfish v2, and i use openesb for bpel..
Ooohh, done finally :)

Edit on 03/09/2009, 12:07 : The format of the post was a mess, so it is fixed by now..
The next post is about the bug mentioned here (in red)..