Archive

Archive for the ‘Web Services’ Category

[wsdlc] [ERROR] A class/interface with the same name “com.mydomain.layer.inbound.ws.ValidateResponse” is already in use. Use a class customizat ion to resolve this conflict.

6 February 2016 Leave a comment

I got the error [wsdlc] [ERROR] A class/interface with the same name "com.mydomain.layer.inbound.ws.ValidateResponse" is already in use. Use a class customization to resolve this conflict. a few days ago when I tried to generate the Java code from a WSDL file, using Oracle’s wsdlc Ant task. The problem is caused by having two elements with the same name, but with a different namespace, in the WSDL file. For example the following bit of code will result in the error above:

<s:element name="ValidateResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="ValidateResult" type="tns:ValidateResponse" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:complexType name="ValidateResponse">
        <s:complexContent mixed="false">
          <s:extension base="tns:Response">
            <s:sequence>
              <s:element minOccurs="1" maxOccurs="1" name="Status" type="tns:ResponseStatus" />
              <s:element minOccurs="0" maxOccurs="1" name="SubscriptionExpiry" type="s:string" />
              <s:element minOccurs="0" maxOccurs="1" name="Allowed" type="tns:ArrayOfGuid" />
            </s:sequence>
          </s:extension>
        </s:complexContent>
      </s:complexType>

The solution to this is to use a JAXB Customisation Binding, as explained here. By using a JAXB Customisation Binding you can essentially bind a WSDL element to another type and therefore resolve the conflict, since in the generated Java code you end up with two different artifacts.

There are two ways do it. The first one is to use an external JAXB Customisation Binding file. Unfortunately this solution did not work for me. Not sure what the problem was. The second solution is to use inline JAXB Customisation Binding code. Fortunately this solution did work for me. By inlining the JAXB binding you end up with the following bit of code

      <s:element name="ValidateResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="ValidateResult" type="tns:ValidateResponse" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:complexType name="ValidateResponse">
        <s:annotation>
          <s:appinfo>
            <jaxb:class name="ValidateResponseComplexType"/>
          </s:appinfo>
        </s:annotation>
      <s:complexContent mixed="false">
        <s:extension base="tns:Response">
          <s:sequence>
            <s:element minOccurs="1" maxOccurs="1" name="Status" type="tns:ResponseStatus" />
            <s:element minOccurs="0" maxOccurs="1" name="SubscriptionExpiry" type="s:string" />
            <s:element minOccurs="0" maxOccurs="1" name="Allowed" type="tns:ArrayOfGuid" />
          </s:sequence>
        </s:extension>
      </s:complexContent>
      </s:complexType>

When the wsdlc runs you will end up with the different classes for the ValidateResponse element: ValidateResponse and ValidateResponseComplexType. Of course you will also need to define the jaxb namespace: xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" in the WSDL file.

Categories: Java, Web Services Tags: ,

SOAPException: faultCode=SOAP-ENV:Client; msg=For input string: "3773 "; targetException=java.lang.NumberFormatException

7 December 2012 1 comment

I get this warning with JMeter

WARN - jmeter.protocol.http.sampler.WebServiceSampler: [SOAPException: faultCode=SOAP-ENV:Client; msg=For input string: "3773 "; targetException=java.lang.NumberFormatException: For input string: "3773 "]

every time I try to test a web service by running a WebService(SOAP) Request. Strange it might seem, but I found out that the error is actually a network error; to be more specific an HTTP/1.1 504 Proxy Timeout ( The connection timed out. ). The original error is totally misleading.

The connection times out, so I get no SOAP response back. What I get though is the headers, the content and the content length back. But for some reason the content length is padded with some spaces at the end and when the HTTPUtils (the class that handles the SOAP request/response) tries to parse it with this statement

Integer.parseInt(value);

it fails. I had to rebuild jmeter and step through it with breakpoints in order to see what’s going on. The solution is as simple as adding a trim to the statement (a couple of lines above the offending statement):

String value = valuebuf.toString().trim();

This fixes the issue and you get the actual response back which is

Error Code 10060: The gateway could not receive a timely response from the website you are trying to access. This might indicate that the network is congested, or that the website is experiencing technical difficulties..

How to resolve circular dependency problems with a Document Literal Wrapped web service

15 June 2010 1 comment

A circular dependencies problem came up while I was trying to implement a Document Literal Wrapped style web service in JBoss. Having gone through several forums the main solution suggested was to use an RPC style web service since you cannot represent circular dependencies with a Document Literal. Alas, the jboss web services implementation does not support RPC ENCODED style web services since it considers it deprecated. An alternative solution was to use Axis but since the project was already using the JBoss implementation I didn’t want to add another one.

Before we delve into the solution lets see what a circular dependency is. In a few words, a circular dependency occurs when we have two objects, and each one refers to each other. For instance a payment and a receipt in the real world. You pay for something and you get a receipt. And the receipt you got refers to the payment you made. If we are to model this in Java we would have two classes, Payment and Receipt which could look like the following

class Payment
{
	private int paymentId;
	private Receipt receipt;
	
	public Payment() {
	}
	
	public void setPaymentId(int paymentId) {
		this.paymentId = paymentId;
	}

	public int getPaymentId() {
		return paymentId;
	}
	
	public void setReceipt(Receipt receipt) {
		this.receipt = receipt;
	}
	public Receipt getReceipt() {
		return receipt;
	}
}

class Receipt
{
	private int receiptId;
	private Payment payment;

	public Receipt() {
	}

	public void setReceiptId(int receiptId) {
		this.receiptId = receiptId;
	}

	public int getReceiptId() {
		return receiptId;
	}
	
	public void setPayment(Payment payment) {
		this.payment = payment;
	}

	public Payment getPayment() {
		return payment;
	}
}

This is circular dependency, Payment refers to Receipt and Receipt refers to Payment. Java can represent this easily in the object graph but in XML this is a bit tricky if you create the WSDL automatically.

Lets assume we have a web service that uses one of our classes.

@WebService(name="PaymentWS")
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT, use=SOAPBinding.Use.LITERAL, parameterStyle=SOAPBinding.ParameterStyle.WRAPPED) 
public class PaymentWS
{
	@WebMethod
	public void buy(Payment payment)
	{
	}
}

If we take the WSDL of our web service and generate the relevant classes and then we write a java client to connect to our web service we can write something like the following

public class Client {

    public static void main(String [] arguments)
    {
        PaymentWSService service = new PaymentWSService();
        PaymentWS ser = service.getPaymentWSPort();

        Payment payment = new Payment();
        payment.setPaymentId(10);

        Receipt receipt = new Receipt();
        receipt.setReceiptId(20);
        receipt.setPayment(payment);
        
        payment.setReceipt(receipt);
        
        ser.buy(payment);
    }
}

When we run this it throws a MarshalException

Caused by: javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.internal.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML:

This is because of the circular dependency of Payment and Receipt because the XML of the SOAP message tries to nest a chunk of XML Payment within the XML Receipt element, and a chunck or XML Receipt within the XML Payment and so on. We can get around this problem by using the @XmlIDREF and @XmlID annotations on the generated Java classes to instruct the runtime that instead of nesting the XML elements within each other simply to use a reference to them. Our generated java classes look like the following

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "payment", propOrder = {
    "paymentId",
    "receipt"
})
public class Payment {

    protected int paymentId;
    protected Receipt receipt;
    ...
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "receipt", propOrder = {
    "payment",
    "receiptId"
})
public class Receipt {

    protected Payment payment;
    protected int receiptId;
    ...
}

and after adding the annotations they become

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "payment", propOrder = {
    "paymentId",
    "receipt"
})
public class Payment {

    protected int paymentId;
    @XmlIDREF
    protected Receipt receipt;
    ...
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "receipt", propOrder = {
    "payment",
    "receiptId"
})
public class Receipt {

    protected Payment payment;
    @XmlID
    protected int receiptId;
    ...
}

Unfortunatelly this still does not work and it throws a WebServiceException which is caused by

Caused by: java.security.PrivilegedActionException: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
Property "receiptId" has an XmlID annotation but its type is not String.

This is because the runtime expects the type of the XmlId to be a string. Not sure why this is mandatory (I guess the designers where afraid that people might not implement the toString() method correctly). The workaround is to add an @XmlJavaTypeAdapter annotation which will adapt our non-String type to a String.

public class IntegerAdapter extends XmlAdapter<String, Integer> {
    
    public Integer unmarshal(String s) {
        return Integer.parseInt(s);
    }

    public String marshal(Integer number) {
        if (number == null) return "";
        
        return number.toString();
    }
}

Since the adapter works only with objects we will also need to modify the Receipt generated class to use an Integer intead of an int.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "receipt", propOrder = {
    "payment",
    "receiptId"
})
public class Receipt {

    protected Payment payment;
    @XmlID
    @XmlJavaTypeAdapter(IntegerAdapter.class)
    protected Integer receiptId;
    ...
}

That’s it. A bit tricky but at least it works.

Axis returned (0)null – a solution

15 April 2009 21 comments

This is a very weird error I was getting a few days ago when I was running Apache Axis. If you output the stack trace you will get the following error

AxisFault
faultCode: {http://xml.apache.org/axis/}HTTP
faultSubcode:
faultString: (0)null
faultActor:
faultNode:
faultDetail:
{}:return code:  0

{http://xml.apache.org/axis/}HttpErrorCode:0

(0)null
at org.apache.axis.transport.http.HTTPSender.readFromSocket(HTTPSender.java:744)
at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144)
at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
at org.apache.axis.client.Call.invokeEngine(Call.java:2784)
at org.apache.axis.client.Call.invoke(Call.java:2767)
at org.apache.axis.client.Call.invoke(Call.java:2443)
at org.apache.axis.client.Call.invoke(Call.java:2366)
at org.apache.axis.client.Call.invoke(Call.java:1812)

If you delve into the apache axis source code you will see that this is actually a network error. There is a variable that holds the network code. This variable is assigned to zero in the beginning of the axis class. At some point the developers of axis read the HTTP responses and assign the HTTP code to this network code variable. But along the flow of the class an exception occurs and this network code remains zero. The null you get next to it is the actual error message description which is null because the exception doesn’t assign a message to it (exactly like it happens with the zero).

This occurred to me when I tried to use a DIME attachment with axis. It seems that axis 1 (not sure about axis 2) does not support DIME attachments properly. In order to resolve this (and the error above) you will need to use another transport handler. There is a solution described in the Axis attachment problems page. Although the solution described in the link is for a different problem, the same solution can be applied for the (0)null issue.

As the page explains the solution is to change the client-config.wsdd file (from within the org\apache\axis\client) and assign a different handler to the file, like the following

<deployment name="defaultClientConfig" ...>
<transport name="http" pivot="java:org.apache.axis.transport.http.CommonsHTTPSender"/>
...
</deployment>

In order to do this you will need to extract all the classes in the axis.jar file, change the client-config.wsdd, and recreate the axis.jar file. You will also need to include the apache commons http client 3.1 and commons-codec 1.3 in your classpath.

The second solution, if you don’t want to recreate the axis.jar file, is to use an EngineConfiguration and pass the new handler to it programmatically.

EngineConfiguration engine = EngineConfigurationFactoryFinder.newFactory().getClientEngineConfig();
SimpleProvider provider = new SimpleProvider(engine);
provider.deployTransport("http", new CommonsHTTPSender());

Then you will need to pass this provider instance in your web service class that extends the org.apache.axis.client.Service. This can be done by passing it in the constructor of your service class.

Categories: axis, Web Services