Java web service method receiving null argument from C# client - java

I'm working on a Java 6 application server which has a web service for receiving a SOAP messages containing an HL7 message. The Java application runs on Glassfish 3.1. The client is a third-party developed C# application (which runs on the Microsoft .net 4.0 framework) and it is sending these SOAP messages to the Java server.
My initial issue was that the client was unable to parse the WSDL generated by the server. I have since resolved that by implementing my own custom WSDL and tuning it accordingly. This allowed the client to parse the WSDL and send SOAP messages to my Java server application.
However, each time a message is received on the server side, the parameter (named "putXML") is receiving a null value.
The Glassfish server log shows the following when a message is received:
Received WS-I BP non-conformant Unquoted SoapAction HTTP header: http://MyProject.MyPackage/putHL7Data
Received Message: null
Here is the custom WSDL that I created and associated with my SOAP web service:
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions
targetNamespace="http://MyProject.MyPackage/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:tns="http://MyProject.MyPackage/"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://MyProject.MyPackage/">
<s:element name="putHL7Data">
<s:complexType>
<s:sequence>
<s:element name="putXML" type="s:string" minOccurs="0" maxOccurs="1"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="putHL7DataResponse">
<s:complexType>
<s:sequence>
<s:element name="return" type="s:string" minOccurs="0" maxOccurs="1"/>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="putHL7DataSoapIn">
<wsdl:part name="parameters" element="tns:putHL7Data"/>
</wsdl:message>
<wsdl:message name="putHL7DataSoapOut">
<wsdl:part name="parameters" element="tns:putHL7DataResponse"/>
</wsdl:message>
<wsdl:portType name="MyHandlerSoap">
<wsdl:operation name="putHL7Data">
<wsdl:input message="tns:putHL7DataSoapIn"/>
<wsdl:output message="tns:putHL7DataSoapOut"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MyHandlerSoap" type="tns:MyHandlerSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="putHL7Data">
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MyHandler">
<wsdl:port name="MyHandlerPort" binding="tns:MyHandlerSoap">
<soap:address location="REPLACE_WITH_ACTUAL_URL"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
And here is the Java web service:
#WebService(serviceName = "MyHandler", wsdlLocation = "WEB-INF/wsdl/MyHandler.wsdl")
public class MyHandler {
#WebMethod(operationName = "putHL7Data")
public String putHL7Data(#WebParam(name = "putXML") String xml) {
// Handle message
}
}
Is there anything I am doing wrong?
What can I do to fix the Java web service so that it properly receives a non-null value?
Is this an issue with the client? If so, would I need to create some sort of interceptor?
Update
Today I tried creating a quick C# client which uses my Java SOAP web service. Below is the code:
namespace TestSoap
{
class Program
{
static void Main(string[] args)
{
ServiceReference1.MyHandlerSoapClient ws = new ServiceReference1.MyHandlerSoapClient();
string result = ws.putHL7Data("Test");
Console.WriteLine("Response: " + result);
Console.ReadLine();
}
}
}
When I run this client, I receive the same null value in the parameter when I was expecting to see the Test string. Also, I'm expecting result to contain a response string but it too is returning a null value.
Remember, I cannot modify the third-party C# client application. Is there anything I can do on the Java end?
Update 2
I recently added a handler chain class which is capturing and logging the raw SOAP messages. The message being sent by the client looks like this:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header/>
<soap:Body>
<putHL7Data xmlns="http://MyProject.MyPackage/">
<putXML>... Encoded XML Here ...</putXML>
</putHL7Data>
</soap:Body>
</soap:Envelope>

After getting pointed in the right direction by #dlawrence, I was able to solve my issue. As I mentioned in the question, I still needed to use a custom built wsdl. I only needed to make a few changes to the wsdl and the Java code to solve the issue.
Here's a diff representing my changes to the wsdl:
--- /tmp/a 2011-09-19 15:05:21.132065003 -0400
+++ /tmp/b 2011-09-19 14:41:28.302064999 -0400
## -15,11 +15,11 ##
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
- <s:schema elementFormDefault="qualified" targetNamespace="http://MyProject.MyPackage/">
+ <s:schema targetNamespace="http://MyProject.MyPackage/">
<s:element name="putHL7Data">
<s:complexType>
<s:sequence>
- <s:element name="putXML" type="s:string" minOccurs="0" maxOccurs="1"/>
+ <s:element name="putXML" type="s:string" form="qualified" minOccurs="0" maxOccurs="1"/>
</s:sequence>
</s:complexType>
</s:element>
## -47,6 +47,6 ##
<wsdl:binding name="MyHandlerSoap" type="tns:MyHandlerSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="putHL7Data">
- <soap:operation soapAction="" style="document"/>
+ <soap:operation soapAction="http://MyProject.MyPackage/putHL7Data" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
Basically this was a three part fix...
1). I needed to remove the elementFormDefault="qualified" attribute from the <s:schema> tag.
2). Then I had to add the attribute form="qualified" on my <s:element name="putXML" ...> tag.
3). Finally, I needed to make sure I had the attribute soapAction="http://MyProject.MyPackage/putHL7Data" on my <soap:operation> tag.
Here's a diff representing my changes to the Java web method:
--- /tmp/a 2011-09-19 14:57:49.582065002 -0400
+++ /tmp/b 2011-09-19 15:00:06.942065007 -0400
## -1,7 +1,7 ##
#WebService(serviceName = "MyHandler", wsdlLocation = "WEB-INF/wsdl/MyHandler.wsdl")
public class MyHandler {
#WebMethod(operationName = "putHL7Data")
- public String putHL7Data(#WebParam(name = "putXML") String xml) {
+ public String putHL7Data(#WebParam(name = "putXML", targetNamespace="http://MyProject.MyPackage/") String xml) {
// Handle message
}
}
As you can see, all I had to do was add the targetNamespace attribute to my #WebParam.

Have you tried removing the #WebParam attribute? It shouldn't be required as there is no ambiguity with your web service here and it's possible you need to set the targetNamespace in order for it to correctly find the attribute.

i have the same Message in my glassfish console. In my android project with ksoap function i changed the following code:
soapEnvelope.setOutputSoapObject(soapReq);
HttpTransportSE httpTransport = new HttpTransportSE(url,timeOut);
try{
if (headers!=null){
// original code // my headers are null
httpTransport.call("http://service.iswitch.com/", soapEnvelope,headers);
}else{
httpTransport.call("\"http://service.iswitch.com/"\", soapEnvelope);
}
SoapObject result=(SoapObject)soapEnvelope.bodyIn;
if (result.hasProperty("moveResult"))
{
....
it works ... );
the class i generated with http://www.wsdl2code.com

Related

How to Return an Class with an Array in Java webservices Consumed by C#

I am having trouble creating a java webservice that returns an Array inside a class. I created a java websrevice with a class and inside the class I created a new Array that will return another Class. But when Importing the WSDL in a C# project I cant access the Array inside the class.
My java web service example :
My industry class :
public class Industry {
public int industryID;
public String industryName;
public Product[ ] products;
}
The Idea is to return the industry with all the products of the industry.
The Product Class :
public class Product {
public int productID;
public String productName;
}
My webservice that populates the industry and the Products for the Industry. Please nte I know I am suposed to create get and set methods to set the values.. I only created a small examle of my problem.
My Webservice class :
public class IndustryService {
/**
* #param industryID
* #return industry object
*/
public Industry getIndustryData(int industryID){
Product product1 = new Product();
product1.productID = 712;
product1.productName = "Sensor Light";
Product product2 = new Product();
product2.productID = 1774;
product2.productName = "Light Beamer";
Product [] products = new Product[] { product1, product2 };
Industry industry = new Industry();
industry.industryID = 2311;
industry.industryName = "Test";
industry.products = products;
return industry;
}
}
Here's the WSDL that gets generated in java :
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://server.com" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://server.com" xmlns:intf="http://server.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--WSDL created by Apache Axis version: 1.4
Built on Apr 22, 2006 (06:55:48 PDT)-->
<wsdl:types>
<schema elementFormDefault="qualified" targetNamespace="http://server.com" xmlns="http://www.w3.org/2001/XMLSchema">
<element name="getIndustryData">
<complexType>
<sequence>
<element name="industryID" type="xsd:int"/>
</sequence>
</complexType>
</element>
<element name="getIndustryDataResponse">
<complexType>
<sequence>
<element name="getIndustryDataReturn" type="impl:Industry"/>
</sequence>
</complexType>
</element>
<complexType name="Product">
<sequence>
<element name="productID" type="xsd:int"/>
<element name="productName" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<complexType name="ArrayOfProduct">
<sequence>
<element maxOccurs="unbounded" minOccurs="0" name="item" type="impl:Product"/>
</sequence>
</complexType>
<complexType name="Industry">
<sequence>
<element name="industryID" type="xsd:int"/>
<element name="industryName" nillable="true" type="xsd:string"/>
<element name="products" nillable="true" type="impl:ArrayOfProduct"/>
</sequence>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="getIndustryDataResponse">
<wsdl:part element="impl:getIndustryDataResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getIndustryDataRequest">
<wsdl:part element="impl:getIndustryData" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="IndustryService">
<wsdl:operation name="getIndustryData">
<wsdl:input message="impl:getIndustryDataRequest" name="getIndustryDataRequest">
</wsdl:input>
<wsdl:output message="impl:getIndustryDataResponse" name="getIndustryDataResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="IndustryServiceSoapBinding" type="impl:IndustryService">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getIndustryData">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getIndustryDataRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getIndustryDataResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="IndustryServiceService">
<wsdl:port binding="impl:IndustryServiceSoapBinding" name="IndustryService">
<wsdlsoap:address location="http://localhost:8080//IIIII/services/IndustryService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Now when consuming it using c# I expect to get a Industry Containing 2 products but C# shows that theres 0 inside of product array...
C# example created a normal form and imported the java WSDL as service reference:
private void Form1_Load(object sender, EventArgs e)
{
ServiceReference1.IndustryServiceClient client = new WindowsFormsApplication4.ServiceReference1.IndustryServiceClient();
ServiceReference1.Industry m = client.getIndustryData(2);
string a = "test";
}
When I debug windows form I get the following :
Notice the Product Array count is 0?
Why is this zero and What am I doing wrong?
Is the problem in the java side or c# side?
I am using eclipse to create the java webservice and Visual studio to import wsdl.
In soap UI I also imported the WSDL just to test the webservice to see the request and response and It looks correct :
Request :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://server.com">
<soapenv:Header/>
<soapenv:Body>
<ser:getIndustryData>
<ser:industryID>2</ser:industryID>
</ser:getIndustryData>
</soapenv:Body>
</soapenv:Envelope>
Response:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<getIndustryDataResponse xmlns="http://server.com">
<getIndustryDataReturn>
<industryID>2311</industryID>
<industryName>Test</industryName>
<products>
<productID>712</productID>
<productName>Sensor Light</productName>
</products>
<products>
<productID>1774</productID>
<productName>Light Beamer</productName>
</products>
</getIndustryDataReturn>
</getIndustryDataResponse>
</soapenv:Body>
</soapenv:Envelope>
Code in the reference.cs file I edited :
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.CollectionDataContractAttribute(Name="products", Namespace="http://server.com", ItemName="item")]
[System.SerializableAttribute()]
public class ArrayOfProduct : System.Collections.Generic.List<WindowsFormsApplication4.ServiceReference1.Product> {
}
In the Reference.cs file I changed the Name and ItemName tag to Products and now it is working.
[System.Runtime.Serialization.CollectionDataContractAttribute(Name = "products", Namespace = "http://server.com", ItemName = "products")]
Visual Studio creates the stub and expects the elements of products with the tag name "ArrayOfProduct" but the server sends them with the following tag
<products>
See the reference.cs file under the service reference (you need to check the Show All Files for the project).
It is not a good practice, but to resolve the issue, you can manipulate the reference.cs file manually to change the CollectionDataContractAttribute to "products" on top of the definition of public class ArrayOfProduct

Why does wsimport suddenly generate client code that uses wrapped parameters?

I learned web services a few years ago with Axis2, and so I've been using it since then.
I've always hated the fact that Axis2 generates client stubs using wrapped parameters instead of the original types. I understand that when you're using complex objects as parameters there's really no choice as those objects need to get serialized, but when your method requires a String and maybe returns a String, wrapping those in some xxx.yyy.Get and xxx.yyy.GetResponse parameters seems like overkill to me. Since I'm using JSON as input and output on all my services now, I'm working with Strings only.
Later in my learnings I discovered I could still create my services with Eclipse's Axis2 plugin, but instead of using the Axis2 stubs, I could use the Java JDK's wsimport tool instead to create clients without all the clutter of the wrapped types.
So, for a service method "String getData(String param)", I could have a client call that looks like "servicePort.getData(stringParam)", where "stringParam" is obviously a String.
That is, until today :-(
For some reason, today I created a new service, deployed it on my server, and called wsimport on it, only to find out that the generated client was using wrapped types.
For example, here's my service definition, from which I create a WSDL and then the service code using Eclipse's Axis2 plugin:
public String get(String param){
return null;
}
And, here's the wsimport-generated client:
#WebMethod
#WebResult(name = "getResponse", targetNamespace = "http://...", partName = "parameters")
public GetResponse get(
#WebParam(name = "get", targetNamespace = "http://...", partName = parameters)
Get parameters);
On a web service I had coded beforehand, I ended up with the following client code :
#WebMethod(action = "urn:get")
#WebResult(targetNamespace = "http://...")
#RequestWrapper(localName = "get", targetNamespace = "http://...", className = "xxx.yyy.Get")
#ResponseWrapper(localName = "getResponse", targetNamespace = "http://...", className = "xxx.yyy.GetResponse")
public String get(
#WebParam(name = "param", targetNamespace = "http://...")
String param);
Here's the wsimport command I'm using to generate the client (on Windows, from my JDK's bin directory) :
.\wsimport -p <package name> -s <target src directory> -extension -verbose -Xnocompile <webserviceUrl?wsdl>
And the wsdl:
<?xml version="1.0" encoding="UTF-8"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xsd="http://..." xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://...">
<wsdl:types>
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://...">
<xs:element name="get">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="param" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="getRequest">
<wsdl:part name="parameters" element="xsd:get"/>
</wsdl:message>
<wsdl:message name="getResponse">
<wsdl:part name="parameters" element="xsd:getResponse"/>
</wsdl:message>
<wsdl:portType name="ServicePortType">
<wsdl:operation name="get">
<wsdl:input message="xsd:getRequest" wsaw:Action="urn:get"/>
<wsdl:output message="xsd:getResponse" wsaw:Action="urn:getResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ServiceSoap11Binding" type="xsd:ServicePortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="get">
<soap:operation soapAction="urn:get" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="ServiceSoap12Binding" type="xsd:ServicePortType">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="get">
<soap12:operation soapAction="urn:get" style="document"/>
<wsdl:input>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="ServiceHttpBinding" type="xsd:ServicePortType">
<http:binding verb="POST"/>
<wsdl:operation name="get">
<http:operation location="get"/>
<wsdl:input>
<mime:content type="application/xml" part="parameters"/>
</wsdl:input>
<wsdl:output>
<mime:content type="application/xml" part="parameters"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Service">
<wsdl:port name="ServiceHttpSoap11Endpoint" binding="xsd:ServiceSoap11Binding">
<soap:address location="http://localhost:8080/axis2/services/Service"/>
</wsdl:port>
<wsdl:port name="ServiceHttpSoap12Endpoint" binding="xsd:ServiceSoap12Binding">
<soap12:address location="http://localhost:8080/axis2/services/Service"/>
</wsdl:port>
<wsdl:port name="ServiceHttpEndpoint" binding="xsd:ServiceHttpBinding">
<http:address location="http://localhost:8080/axis2/services/Service"/>
</wsdl:port>
</wsdl:service>
I have found other questions and answers here on StackOverflow and other forums for the "enableWrapperStyle" thing in a custom binding file, tried it, didn't work. Anyhow, this flag seems to allow either generating method signatures with wrapped types (which I don't want), or signatures returning void and using some Holder types in the signature for return values (which I don't want either).
Can someone tell me what I'm doing wrong ?

accessing a java webservice from the webservice client

I am trying to access a java webservice by sending a soap request to the service
the strange part is that until recently it worked fine, and now it gives me an internal server error
what am i doing wrong ??
this is my soap message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://webservice.lenabru.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <q0:register><q0:regFirstName></q0:regFirstName><q0:regLastName></q0:regLastName><q0:regLoginName></q0:regLoginName><q0:regPassword></q0:regPassword><q0:regAddress></q0:regAddress><q0:regEmail></q0:regEmail><q0:regPhone></q0:regPhone></q0:register></soapenv:Body></soapenv:Envelope>
and this is the response i get from the server
"<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>java.lang.reflect.InvocationTargetException</faultstring>
<detail>
<ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">Lena</ns1:hostname>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>"
this is the contents of the webmethod i am trying to reach:
#WebMethod
public boolean register(String regFirstName, String regLastName, String regLoginName, String regPassword, String regAddress, String regPhone, String regEmail) {
return false;
}
this is my wsdl:
<wsdl:definitions xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://webservice.lenabru.com" xmlns:intf="http://webservice.lenabru.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://webservice.lenabru.com">
<!--
WSDL created by Apache Axis version: 1.4
Built on Apr 22, 2006 (06:55:48 PDT)
-->
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://webservice.lenabru.com">
<element name="register">
<complexType>
<sequence>
<element name="regFirstName" type="xsd:string"/>
<element name="regLastName" type="xsd:string"/>
<element name="regLoginName" type="xsd:string"/>
<element name="regPassword" type="xsd:string"/>
<element name="regAddress" type="xsd:string"/>
<element name="regPhone" type="xsd:string"/>
<element name="regEmail" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="registerResponse">
<complexType>
<sequence>
<element name="registerReturn" type="xsd:boolean"/>
</sequence>
</complexType>
</element>
<element name="isUserExists">
<complexType>
<sequence>
<element name="userName" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="isUserExistsResponse">
<complexType>
<sequence>
<element name="isUserExistsReturn" type="xsd:boolean"/>
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<wsdl:message name="isUserExistsResponse">
<wsdl:part element="impl:isUserExistsResponse" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="registerRequest">
<wsdl:part element="impl:register" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="isUserExistsRequest">
<wsdl:part element="impl:isUserExists" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="registerResponse">
<wsdl:part element="impl:registerResponse" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:portType name="ElectronicArenaWebService">
<wsdl:operation name="register">
<wsdl:input message="impl:registerRequest" name="registerRequest"></wsdl:input>
<wsdl:output message="impl:registerResponse" name="registerResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="isUserExists">
<wsdl:input message="impl:isUserExistsRequest" name="isUserExistsRequest"></wsdl:input>
<wsdl:output message="impl:isUserExistsResponse" name="isUserExistsResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ElectronicArenaWebServiceSoapBinding" type="impl:ElectronicArenaWebService">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="register">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="registerRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="registerResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="isUserExists">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="isUserExistsRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="isUserExistsResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ElectronicArenaWebServiceService">
<wsdl:port binding="impl:ElectronicArenaWebServiceSoapBinding" name="ElectronicArenaWebService">
<wsdlsoap:address location="http://localhost:8080/ElectronicArenaLena/services/ElectronicArenaWebService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
First a note: if you're using Tomcat 7 (why not use Axis 2 ?)
Setup for Log4j (at the time axis 1 was still there there was log4j, now there is a better alternatives from the same author of Log4j it's called logback - however there is a new Log4j 2 now but I haven't tested it for this setup only the one that comes with axis downloaded here
http://archive.apache.org/dist/ws/axis/1_4/)
create a log4j.properties file and put it in your WEB-INF/classes folder
(I created a sample content so that you can get going, might need to look at log4j's documentation to modify the logs as you need - the below creates multiple log files(max 5) whenever one's size reaches 100k it creates another, you might need to change the size or number as needed or just use one)
log4j.rootLogger=DEBUG, R
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.File=axis.log
log4j.appender.R.MaxBackupIndex=5
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} – %m%n
# below line might not be needed, but I just had it there
log4j.R.org.apache.axis=DEBUG
now open axis.jar and remove whatever properties file you have directly in the folder structure (next to MANIFEST and org folders - I had simplelog.properties so I deleted it)
restart apache tomcat and check the apache logs to make sure log4j isn't throwing any warnings or errors
If everything works fine, you should be able to see axis.log in apache tomcat's bin directory
Note:
you might notice a lot of useless debug logs, however when an exception occurs or some issue happens it might be handy to have this level of details in your logs, plus you can disable it anytime you need, just replace rootLogger DEBUG into INFO or comment log4j.properties all together
References:
http://osdir.com/ml/text.xml.axis.user/2002-08/msg00436.html
http://axis.apache.org/axis/java/developers-guide.html#LoggingTracing

Axis2 and Webservices: File Upload

I'm trying to write a simple web service using Axis2. Its behaviour is really simple: it takes a file in input and stores it.
I've tried several things to do this "simple" file upload service. At the beginning i also tried to use Java2WSDL and WSDL2Java to create the WSDL file and the client hoping to pass the java.io.File datatype. Of course it didn't work.
I'm now trying to upload the file using SOAP attachments and MTOM or SwA.
I've enabled them both in axis2\WEB-INF\conf\axis2.xml
Server side, the signature of my service operation it is:
public String uploadAttachment(OMElement omEle);
And this is the WSDL generated using Java2WSDL tool:
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xsd="http://services.italsystem.it" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://services.italsystem.it">
<wsdl:types>
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://services.italsystem.it">
<xs:element name="uploadAttachment">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="omEle" nillable="true" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="uploadAttachmentResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="uploadAttachmentRequest">
<wsdl:part name="parameters" element="xsd:uploadAttachment"/>
</wsdl:message>
<wsdl:message name="uploadAttachmentResponse">
<wsdl:part name="parameters" element="xsd:uploadAttachmentResponse"/>
</wsdl:message>
<wsdl:portType name="ImportServicePortType">
<wsdl:operation name="uploadAttachment">
<wsdl:input message="xsd:uploadAttachmentRequest" wsaw:Action="urn:uploadAttachment"/>
<wsdl:output message="xsd:uploadAttachmentResponse" wsaw:Action="urn:uploadAttachmentResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ImportServiceSoap11Binding" type="xsd:ImportServicePortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="uploadAttachment">
<soap:operation soapAction="urn:uploadAttachment" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="ImportServiceSoap12Binding" type="xsd:ImportServicePortType">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="uploadAttachment">
<soap12:operation soapAction="urn:uploadAttachment" style="document"/>
<wsdl:input>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="ImportServiceHttpBinding" type="xsd:ImportServicePortType">
<http:binding verb="POST"/>
<wsdl:operation name="uploadAttachment">
<http:operation location="uploadAttachment"/>
<wsdl:input>
<mime:content type="application/xml" part="parameters"/>
</wsdl:input>
<wsdl:output>
<mime:content type="application/xml" part="parameters"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ImportService">
<wsdl:port name="ImportServiceHttpSoap11Endpoint" binding="xsd:ImportServiceSoap11Binding">
<soap:address location="http://localhost:8080/axis2/services/ImportService"/>
</wsdl:port>
<wsdl:port name="ImportServiceHttpSoap12Endpoint" binding="xsd:ImportServiceSoap12Binding">
<soap12:address location="http://localhost:8080/axis2/services/ImportService"/>
</wsdl:port>
<wsdl:port name="ImportServiceHttpEndpoint" binding="xsd:ImportServiceHttpBinding">
<http:address location="http://localhost:8080/axis2/services/ImportService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Client side, i've tried to call the service:
Options options = new Options();
options.setTo(new EndpointReference("http://localhost:8080/axis2/services/ImportModule"));
options.setProperty(Constants.Configuration.ENABLE_SWA, Constants.VALUE_TRUE);
options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
options.setSoapVersionURI(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
ServiceClient sender = new ServiceClient(null,null);
sender.setOptions(options);
OperationClient mepClient = sender.createClient(ServiceClient.ANON_OUT_IN_OP);
MessageContext mc = new MessageContext();
SOAPFactory factory = OMAbstractFactory.getSOAP12Factory();
SOAPEnvelope env = factory.getDefaultEnvelope();
mc.setEnvelope(env);
FileDataSource fileDataSource = new FileDataSource(new File("c:\\test.jpg"));
DataHandler dataHandler = new DataHandler(fileDataSource);
mc.addAttachment("FirstAttachment",dataHandler);
mepClient.addMessageContext(mc);
mepClient.execute(true);
But i get an Axis Fault on the execute call telling me "wrong number of arguments".
I've also tried calling the service using the client generated with WSDL2Java:
ImportServiceStub stub = new ImportServiceStub("http://localhost:8080/axis2/services/ImportModule");
UploadAttachment ua = new UploadAttachment();
FileDataSource fileDataSource = new FileDataSource(new File("c:\\test.jpg"));
DataHandler dataHandler = new DataHandler(fileDataSource);
ua.setOmEle(dataHandler);
UploadAttachmentResponse res = stub.uploadAttachment(ua);
But i get another Axis Fault: "org.apache.axiom.om.impl.llom.OMTextImpl cannot be cast to org.apache.axiom.om.OMElement".
But i don't know what i can give as a parameter to the generated method "setOmEle" since it is an Object type..
i thought to upload a file was one of the simples services that someone can imagine.. :P
i really hope someone can give me some advice, this problem is making me crazy!
thanks in advance :)
It is actually simple: enable MTOM (but not SwA) and use DataHandler as the argument type.
Take a look here, but also would ask to think about using Servlet's doPost; as the thread suggests - Axis2 File Upload by chunk
If you have not seen this, then check this one too for details about the method you are using http://axis.apache.org/axis2/java/core/docs/mtom-guide.html
Andreas' advice was really helpful!
I've tried passing an array of byte to the service, but i has some problems like the size of files on the server weren't of the same size of the files on the client..
With DataHandler i haven't such problems.
I've enabled MTOM in Axis (\WEB-INF\conf\axis2.xml).
My service operation signature was something like that:
public String importFile(String name, DataHandler dh);
And client side, after i've generated the client with WSDL2Java, i used the service as follows:
ImportServiceStub stub = new ImportServiceStub("http://localhost:8080/axis2/services/ImportModule");
ImportFile importFile = new ImportFile(); //operation name
DataSource fds = new FileDataSource(new File("FileName"));
importFile.setName("FileName");
importFile.setDh(new DataHandler(fds));
stub.importFile(importFile);
Thanks again for your support and your advices :)
I could do this successfully when I generate stubs using wsdltojava but when I tried same using wsimport command I am receiving null parameter data at server side.
I am following below process.
Wrote service side code using jax ws specification and mtom soap 11 binding #BindingType(value = SOAPBinding.SOAP11HTTP_MTOM_BINDING)
Generate .aar file to upload it to axis2 server (axis1.6.2 & tomcat 6/7)
Generate wsdl file from axis2 server just clicling on service name.
Generated stubs using wsimport -keep -verbose wsdl url
Test code with with mtom enable
//Enable MTOM
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
Result:- Passing i/p with Sting & byte but i/p received # service method is null

Java Webservice returning null object to a .net client

Can any one figure out my problem is...
I'm calling a webmethod of a Java Webservice (Axis 1.4) from a .Net client. That method returns a Map object, and if i call it from an Axis client works fine, but in my c# code it´s always null.
That's the WSDL:
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="urn:http.service.enlaces.portlet.ext.com" xmlns:intf="urn:http.service.enlaces.portlet.ext.com" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns1="http://model.enlaces.portlet.ext.com" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:http.service.enlaces.portlet.ext.com">
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://xml.apache.org/xml-soap">
<import namespace="urn:http.service.enlaces.portlet.ext.com"/>
<import namespace="http://model.enlaces.portlet.ext.com"/>
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="mapItem">
<sequence>
<element name="key" nillable="true" type="xsd:anyType"/>
<element name="value" nillable="true" type="xsd:anyType"/>
</sequence>
</complexType>
<complexType name="Map">
<sequence>
<element maxOccurs="unbounded" minOccurs="0" name="item" type="apachesoap:mapItem"/>
</sequence>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="getFoldersAndBookmarksRequest" />
<wsdl:message name="getFoldersAndBookmarksResponse">
<wsdl:part name="getFoldersAndBookmarksReturn" type="apachesoap:Map" />
</wsdl:message>
<wsdl:portType name="BookmarksEntryServiceSoap">
<wsdl:operation name="getFoldersAndBookmarks">
<wsdl:input name="getFoldersAndBookmarksRequest" message="intf:getFoldersAndBookmarksRequest" />
<wsdl:output name="getFoldersAndBookmarksResponse" message="intf:getFoldersAndBookmarksResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Portlet_Bookmarks_BookmarksEntryServiceSoapBinding" type="intf:BookmarksEntryServiceSoap">
<wsdlsoap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" />
<wsdl:operation name="getFoldersAndBookmarks">
<wsdlsoap:operation soapAction="" />
<wsdl:input name="getFoldersAndBookmarksRequest">
<wsdlsoap:body use="encoded" namespace="urn:http.service.enlaces.portlet.ext.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</wsdl:input>
<wsdl:output name="getFoldersAndBookmarksResponse">
<wsdlsoap:body use="encoded" namespace="urn:http.service.enlaces.portlet.ext.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
and my c# auto-generated code:
[System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="urn:http.service.enlaces.portlet.ext.com", ResponseNamespace="urn:http.service.enlaces.portlet.ext.com")]
[return: System.Xml.Serialization.SoapElementAttribute("getFoldersAndBookmarksReturn")]
public Map getFoldersAndBookmarks() {
object[] results = this.Invoke("getFoldersAndBookmarks", new object[0]);
return ((Map)(results[0]));
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3082")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace="http://xml.apache.org/xml-soap")]
public partial class Map {
private mapItem[] itemField;
/// <comentarios/>
public mapItem[] item {
get {
return this.itemField;
}
set {
this.itemField = value;
}
}
}
I,ve seen everywhere unfortunately, i don't find the solution.
Please, there are anyone what knows it?
I've faced the same problem a while ago. This happens when you try to get an array of elements through an axis webservice with a .net client.
The problem is "name=item" part of this line :
<element maxOccurs="unbounded" minOccurs="0" name="item" type="apachesoap:mapItem"/>
Try changing in that particular line "item" to "mapItem". Try one of these :
<element maxOccurs="unbounded" minOccurs="0" name="mapItem" type="apachesoap:mapItem"/>
or
<element maxOccurs="unbounded" minOccurs="0" name="key" type="apachesoap:mapItem"/>
or
<element maxOccurs="unbounded" minOccurs="0" name="value" type="apachesoap:mapItem"/>
So it very late to help you but I recently was running into the same problem.
Firstly I am using Eclipse to create a web service. The problem for me was that the wsdd generated was using the 'document/literal(wrapped)' style. Changing that to 'RPC' fixed the issue. No more nulls.
So maybe if you change your encoding to RPC that might fix your issue too.
And this is why web services generated from code are almost never interoperable :)
One good way of working around this is to make the wsdl first, and define a nice clear little bit of XSD, that should map nicely into both .Net and java. An alternative is something other than axis 1.4 (yech, the pain) for the server if you have any control over that.
Finally, try massaging the signatures in the java code, try replacing List with MapItem[], or vice versa, make sure you don't have Map anywhere in a return object or a parameter.
Reviewing your generated wsdl again, I'd say this is probably because of the xsd:anyType for the key/value part of the mapItem.
I think that's what is generated by axis if you have a java Object in a parameter. Trust me, you don't want that. Make it a string, or a complex type, or an Integer, but an Object can only imply open ended xml (xsd:anyType) and not many clients no how to parse that.
I faced that, and I had to change WSDL file so:
<wsdlsoap:body use="encoded" ...
to
<wsdlsoap:body use="literal" ...
Only to perform the proxy generation.
I faced same issue. My solution is to remove the Namespace in auto-generated function.
This is my function:
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://www.service-now.com/incident/getRecords", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Bare)]
[return: System.Xml.Serialization.XmlArrayAttribute("getRecordsResponse", Namespace = "")]
[return: System.Xml.Serialization.XmlArrayItemAttribute("getRecordsResult", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable = false)]
public getRecordsResponseGetRecordsResult[] getRecords([System.Xml.Serialization.XmlElementAttribute("getRecords", Namespace = "http://www.service-now.com/incident")] getRecords getRecords1)
{
object[] results = this.Invoke("getRecords", new object[] {
getRecords1});
return ((getRecordsResponseGetRecordsResult[])(results[0]));
}
I removed the Namespace in this line. Bacause when I test the web service via SoapUI, I realized that the response object has no namespace. But auto-generated code has namespace.
[return: System.Xml.Serialization.XmlArrayAttribute("getRecordsResponse", Namespace = "")]
SoapUI Response was as following:
<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">
<SOAP-ENV:Body>
<getRecordsResponse>
<getRecordsResult>
<active>0</active>
</getRecordsResult>
</getRecordsResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Categories