How to customise web service response xml - java

I am trying to migrate a web service from IIS to Websphere. I have created a Java class containing the services as well as the necessary supporting classes. I have used exactly the same names in Java as were used in C#.
The web service is then generated from the service class using a wizard. JAX-WS and Document/Wrapped are selected. However, the service response differs from the original.
Original:
<StaffAttendingResponse xmlns="http://acme.com/">
<StaffAttendingResult>
<StaffAttendance>
<Guid>edffd67b-c7dc-4fe6-bc3c-846bf04e4ac6</Guid>
<Name>Wonka</Name>
<Vorname>Willy</Vorname>
...
Websphere:
<StaffAttendingResponse xmlns="http://acme.com/">
<return>
<guid>edffd67b-c7dc-4fe6-bc3c-846bf04e4ac6</guid>
<name>Wonka</name>
<vorname>Willy</vorname>
...
The response is a list of StaffAttendance objects. The Java version is missing the StaffAttendingResult node, the StaffAttendance nodes are called return and the object attributes are all lowercase.
I have tried using the Document/Bare option but wsgen throws an exception and does not complete the generation.

Related

Webservice communication between Java EE applications

I have two Java EE applications on two separate application servers. One of them already contains a working EJB. I want to be able to communicate with this EJB from the other application by using a JAX-WS webservice (the communication has to work between different application servers and different server versions, so remote EJB call is no option). It is no problem to expose the server api to the client application.
The server side is quite clear, adding #Webservice annotation seems to work quite well. But i wonder what is the best way to build the client: I don't really want to generate the client stub from the wsdl (which itself has been generated from the ejb code by the container in my case) and pack all these generated classes into the client ear - but this seems to be the only way i can make use of #WebServiceRef annotations.
The alternative to make a dynamic proxy myself with the help of the static methods of javax.xml.ws.Service (sth. like service=Service.create() and service.getPort()) is not recommended by the Spec and "container providers are not required to support managed Service Instances created using these methods".
But that is exactly sth. that I want to use:
Is there a way to get a dynamic proxy injected in my code, managed by the application server? Or is the only way to get a managed webservice client instance to be done with generated client stub classes?
Read JAX-WS 2.2 spec, Chapter 4: Client APIs.
1. Static Client Generation
Is really the simplest way to work with JAX-WS. From a web services perspective, the WSDL is the interface AND the connection properties. Even if you choose not to work with it physically, you still need to know it in a logical sense to make meaningful SOAP calls.
Note from JAX-WS spec: An Endpoint that uses the SOAP 1.1/HTTP binding MUST
make its contract available as a WSDL 1.1 document at the publishing address suffixed with ?WSDL or ?wsdl
2. Dynamic Client Programming
Is there a way to get a dynamic proxy injected in my code, managed by the application server?
This approach involves dynamic programming against the JAX-WS API to connect to a web service either with or without using WSDL. There's no way to just "inject" a dynamic proxy out of nowhere. You need to construct & configure one with the SEI's port URLs. The WSDL document is the standard place to store such configuration information, although it is possible to avoid it and to programmatically insert the info.
2A) Dynamic programming with WSDL:
javax.xml.ws.Service service = Service.create(
new URL("http://example.org/stocks.wsdl"),
new QName("http://example.org/stocks", "StockQuoteService"));
com.example.StockQuoteProvider proxy = service.getPort(portName,
com.example.StockQuoteProvider.class)
javax.xml.ws.BindingProvider bp = (javax.xml.ws.BindingProvider)proxy;
Map<String,Object> context = bp.getRequestContext();
context.setProperty("javax.xml.ws.session.maintain", Boolean.TRUE);
proxy.getLastTradePrice("ACME");
Advantages over (1): can dynamically dynamically change the WSDL doc after app is deployed, provided such changes do not affect the java interface to client.
i.e. very little benefit to you. Your WSDL is static. Whilst you could point your client to <service endpoint URL>?wsdl to dynamically lookup, this means you need to manually configure <service endpoint URL> AND that leaves little else that can change in the SEI/WSDL without impacting your client logic.
2B) Dynamic programming without WSDL:
String endpointUrl = ...;
QName serviceName = new QName("http://example.org/wssample/echo/", "EchoService");
QName portName = new QName("http://example.org/wssample/echo/", "EchoServicePort");
/** Create a service and add at least one port to it. **/
Service service = Service.create(serviceName);
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl);
/** Create a Dispatch instance from a service.**/
Dispatch<SOAPMessage> dispatch = service.createDispatch(portName,
SOAPMessage.class, Service.Mode.MESSAGE);
/** Create SOAPMessage request. **/
// compose a request message
MessageFactory mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
// Create a message. This example works with the SOAPPART.
SOAPMessage request = mf.createMessage();
SOAPPart part = request.getSOAPPart();
// Obtain the SOAPEnvelope and header and body elements.
SOAPEnvelope env = part.getEnvelope();
SOAPHeader header = env.getHeader();
SOAPBody body = env.getBody();
// Construct the message payload.
SOAPElement operation = body.addChildElement("invoke", "ns1",
"http://com/ibm/was/wssample/echo/");
SOAPElement value = operation.addChildElement("arg0");
value.addTextNode("ping");
request.saveChanges();
/** Invoke the service endpoint. **/
SOAPMessage response = dispatch.invoke(request);
Advantage (not really): can eventually get it to carry out same behaviour as above.
Disadvantages: Complex programming. Non-standard configuration (outside of WSDL). Need to avoid hard-coding settings. Brittle to interface changes. Manually synchronising settings between server and client - easy to omit something, extremely difficult to debug.
Answer:
Go back to (1). Generate a client stub from the WSDL. Use it as an interface contract - it should be designed well and not change.
Then spend the time you save solving real problems... ;) ;)

Axis2 with JSON Support

I have an Axis2 web service that's already deployed, and which communicates with clients using SOAP. There's a new requirement now to enable REST calls by sending JSON requests and receiving JSON formatted responses.
Following this small tutorial: http://code.google.com/p/jsonp-support-for-axis2/wiki/OneStopPage
I was able to configure my Axis 2 web service correctly. Using my browser, I used the following URL to return a Student object:
http://localhost:8181/Axis2Json/services/StudentService/getStudent?response=application/json&value=3
OUTPUT :
{"return":{"#type":"ax21:Student","age":25,"firstName":"Mouhammed","lastName":"Soueidane"}}
The problem is that the returned JSON, doesn't look like a standard JSON representation (Not even in badgerfish format). So for instance, if I want to call a method called "setStudent" which takes in a Student object, I really have no clue of the JSON string that I need to pass to it.
I tried so many stuff, most of which resulted in a casting exception (java.lang.ClassCastException: java.lang.String cannot be cast to org.codehaus.jettison.json.JSONObject)
Does anyone have an idea about how to allow an Axis 2 web service to use both SOAP and JSON, based on the content type of the client?

How to implement Soap Faults in Java webservices?

Am pretty new to web services and have been trying to implement Soap Faults. I used Apache Axis2 to generate webservice in the following manner.
public interface XYZ{
public String myMethod(User[] user)
}
Here I have created a User class with some variables so that I can generate User object at .Net environment to pass User[] of objects.
Public class Webservice implements XYZ
{
Public String myMethod(User[] user){
//My implementation
}
}
Now, I created a dynamic project using Eclipse and with the help of Axis2 plugin I created webservice for my "Webservice" class which generates wsdl file. I deployed the webcontent in the Tomcat folder and able to access the WSDL file in the .Net environment. I am able to pass array of objects (User[]) from .Net to Java and able to do my task. Now, I need to implement Soap Faults in Java which I am not sure how to implement.
Can anyone help me with an example or tutorial ?
Your best bet is to Google for something like "jax-ws faults". For example:
http://www.ibm.com/developerworks/webservices/library/ws-jaxws-faults/index.html
You can also implement an error handler, as discussed under "Using handlers in JAX-WS Web services" here:
http://axis.apache.org/axis2/java/core/docs/jaxws-guide.html#BottomUpService
Most frameworks will trigger a SOAP fault when you throw an Exception in the method implementing your operation. That will not give you much control on the SOAP fault content though.
See here for some details on Axis
Generally, You don't need any specific coding for implementing SOAP fault.. Whenever there is any exception thrown by the method (here myMethod in your example.), axis will automatically generate SOAPFault element in the resulting response. The exception is actually wrapped into AxisFault exception and sent to the client.
See here a i.

Spring, #WebService / #WebMethod, (using Jax-WS), receiving a serialized object?

I've been gradually piecing together how I can receive a serialized object within Spring and have gotten a web service working, by following a tutorial, that uses Jax-WS. I have verified that I can access this basic service through a browser by pulling up the XML page using a url like http://localhost:8080/WebServicesExample/hello?wsdl
The code I currently have is like below, however I want to make a service so that a serialized object can be passed in, for example a HashMap and then have spring de-serialize it, etc. I have been doing a lot of reading on this but am still a bit lost, I would appreciate if anyone can offer advice how to get from where I am at currently to what I am trying to do. Thanks
import javax.jws.WebMethod;
import javax.jws.WebService;
import com.mkyong.bo.HelloWorldBo;
#WebService
public class HelloWorldWS{
//DI via Spring
HelloWorldBo helloWorldBo;
#WebMethod(exclude=true)
public void setHelloWorldBo(HelloWorldBo helloWorldBo) {
this.helloWorldBo = helloWorldBo;
}
#WebMethod(operationName="getHelloWorld")
public String getHelloWorld() {
return helloWorldBo.getHelloWorld();
}
}
I am not completely sure which WS stack you have used for exposing this service, assuming that you just want to create a JAX-WS based sample, let me point you to a working sample that I had created earlier available at : git://github.com/bijukunjummen/memberservice-codefirst.git .
This sample uses Apache CXF as the JAX-WS implementation, and uses JAXB2 for binding (converting the incoming xml to Java objects and back)
In your example, Apache CXF would allow you to expose a WS interface using an entry into spring configuration files of the type:
<jaxws:endpoint address="/helloworldservice" id="helloworld" implementor="#helloworldBean" >
</jaxws:endpoint>

JavaEE6+REST: How do I get all REST resources at runtime?

Is there a possibility to get a list of all registered REST resources at runtime?
With REST resources I mean:
either classes which have annotations such as #Path(...) and are considered by the server at runtime (so traversing all classes using reflection would not do),
or URIs of all paths (REST class can have multiple paths).
NOTE 1: I am using automatic configuration (that new feature of JavaEE 6) and Netbeans just generates an empty ApplicationConfig class.
NOTE 2: Using Netbeans 6.9, JavaEE 6, Glassfish 3. Is more information on my ecosystem needed?
Are you using Jersey? If so, then a WADL is generated automatically at /application.wadl. The WADL contains a lot of information about registered resource paths.
See also: WADL Support
public synchronized Response doSomething(#Context Application c, #FormParam("someParam") String someParam)
throws Exception {
// gives a list of classes which are used by this Jersey instance
// and have REST-related annotations
c.getSingletons(); // returns Set<Object>
return something;
}

Categories