Dynamic client with JAX-WS - web-services

With CXF 2.7.7, I can generate dynamic clients to call a web service:
JaxWsDynamicClientFactory dynamicClientFactory = JaxWsDynamicClientFactory.newInstance();
Client client = dynamicClientFactory.createClient(wsdlURL);
http.getAuthorization().setUserName("username");
http.getAuthorization().setPassword("password");
Object arg = Thread.currentThread().getContextClassLoader().loadClass("com.foo.Arg").newInstance();
Object[] response = client.invoke("someMethodName", arg);
In particular, I can reflectively instantiate and populate the generated classes.
Can a similar effect be achieved using the JAX-WS APIs?
Or alternatively, can I get hold of a javax.xml.ws.BindingProvider for a Client generated using JaxWsDynamicClientFactory?

What do you need the BindingProvider for? If it's just for the RequestContext, the Client object already has methods to obtain that. (although any key/value you set on that would need to be using the CXF keys, not the JAX-WS keys) The getConduit call is there as well if you need to configure conduit specific properties.

Related

Dropwizard - how would a client module look like?

I was wondering how the Dropwizard client module should be implemented.
Source of confusion:
Dropwizard recommends you to separate your project as such:
In general, we recommend you separate your projects into three Maven
modules: project-api, project-client, and project-service.
On the Client section, it shows that you can instantiate the httpClient provided by dropWizard within a run method.
#Override
public void run(ExampleConfiguration config,
Environment environment) {
final Client client = new JerseyClientBuilder().using(config.getJerseyClientConfiguration())
.using(environment)
.build();
environment.addResource(new ExternalServiceResource(client));
}
I thought that the client module would wrap the httpClient, and any other service can use the client module, without caring which httpClient it is using.
So
how would a client module look like
When would you instantiate an httpClient directly within a service's run method (as done in the snippet of code above)
Thanks!
How would a client module look like
This is heavily dependant on your project scope and structure. For example, in one of my projects which is heavily database dependant, the Client module (or Service class in DropWizard's terminology) contains my DAO instantiations as well as hibernate initializations and a bunch of other init stuff (SQS, etc). I also use the HTTP Client and the Service class is where I initialize it. Reason being is that the Service class is the entry point and this is where you end up instantiating your Resource classes, etc. So having the dependancies instantiated here allow me to pass them into my resources as constructor params. If you were using something like Guice, then the way to go would be different since you have access to injection, etc.
When would you instantiate an httpClient directly within a service's run method (as done in the snippet of code above)
The HttpClient shown in the doc and your question is used when your project requires a Http Client. For example, lets say your DW project or one of the resources you are writing requires you to make a HTTP call to a twitter API. This is where the Http Client comes into play. You can actually use any Http Client library you want, however using the ones provided by DW (Apache Http Client, Jersey Http Client) allows you to create a 'Managed' Http Client there by allowing DW to start up, shut down and clean up the HTTP Client when the service is shutdown. So things like thread pools, connection pools, etc are all cleaned up by DW when you use its managed HTTP Client. In addition, the reason why you create this HTTP Client inside the run method is because you are then able to get a reference to the Configuration object's instance which will allow you to control the HTTP Client's settings via DW's configuration system.
Hope this answers your questions

XML Binding via Web Service (or JAXB)

I have to maintain a Java EE 5 web app.
A part of this app is the exchange of messages through web services (with WSDL contract).
The wsdl is used to generate the Java classes through the Eclipse wsdl2Java (I think it uses Axis)
Now I have to implement a modification where the server that we call via Web Service must be able to respond in an async way.
In fact the server will not respond immediately with the SOAP message response but, after a while, call a web service exposed by the client (our web app)
passing the SOAP Message response of the first call as a field (parameter) of this second Web service invocation.
The client then will save the SOAP response (or XML) in a file.
Is there a way to populate the already generated Java classes using this XML or SOAP message file? I mean a way to simulate the direct response of the server (feeding the Axis binding Stub)
I have also tried to use JAXB (to bind XML to JAVA) but since the SOAP message response is complex, when I call JAXBContext I receive an error:
CodPrestazione does not have a no-arg default constructor
since this class is an enum class generated by the wsdl2Java.
Is there a way to bypass this error without annotating or modifying the java class (this class is generated so I will be forced to modify this class at every re-generation)?
What is the best way to consume a saved SOAP message file(or XML)? Alternatively, how can I deserialize SOAP using Axis 1.3?

Automatically pass a cookie with each web-service call

I have a standalone web-service client. When invoking any of the web-methods an additional "cookie" string must be implicitly(not as a web-method parameter) passed to the WS. The WS on the other end must be able to obtain the string and use it. How can this be achieved?
I invoke the service in the following way:
Service srv = Service.create(new URL(WSDL), QNAME);
myClassPort = srv.getPort(MyClass.class);
What I need is to put some code before the first line, which would make the client send this "cookie" string every time I invoke some remote method via myClassPort. Thx.
By default JAX-WS web services and clients are stateless. When a client makes a request, the server responds and sets a cookie on the connection, if it participates in a session. But, the JAX-WS client ignores that cookie and the server treats subsequent requests as new interaction. When the session is enabled, JAX-WS client sends the same cookie with each subsequent request so that server can keep track of the client session.
So you should not be using either cookies or HTTP sessions with web services. Return a token ID as part of the response; then the client can send that along with the next request.
Anyway:
JAX-WS web service clients must be configured to maintain session information (such as cookies), using the javax.xml.ws.session.maintain property.
Other web service stacks may have similar mechanisms.
On the Server Side
JAX-WS uses some handy annotations defined by Common Annotations for the Java Platform (JSR 250), to inject the web service context and declaring lifecycle methods.
WebServiceContext holds the context information pertaining to a request being served.
You don't need to implement javax.xml.rpc.server.ServiceLifecycle. With JAX-WS Web Service all you need to do is mark a field or method with #Resource. The type element MUST be either java.lang.Object or javax.xml.ws.WebServiceContext.
#WebService
public class HelloWorld {
#Resource
private WebServiceContext wsContext;
public void sayHello(){
MessageContext mc = wsContext.getMessageContext();
HttpSession session = ((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
}
}
There are some misleading answers to this question, so I will attempt to highlight current best practices. Most of these suggestions are part of the OWASP security guidelines, which I strongly recommend anyone working on web development to review.
1) ALWAYS use temporary (session scoped) cookies.
2) All cookies should be protected and encrypted.
3) Do not pass tokens in request payloads
4) For any requests which return data that may be sent back to the server, include a nonce (single use token) in your responses.
5) later requests should (must) include the nonce and the cookie
Again, my recommendation is to review the OWASP guidelines and proceed accordingly.
You may want to look into using a service provider for authentication - this is much smarter than brewing your own solution as there are literally a million details that all must be correct. Auth0.com is one of these.

How to decide between Message Contract and Data Contract in WCF?

I am reading so many things to understand various things in WCF.
Very soon, actually, i want to move/convert existing WSE3 web services to WCF. In existing WSE web services, I have some (data) classes that model entities in our environment.
While transforming those classes, should I use Data Contract/Data Member attribute or the MessageContract attribute?
1. How to decide between Message Contract and Data Contract in WCF?
2. Does type of binding (like basicHttpBinding) has any role in this decision?
3. Does proxies created at client side (when we add web reference) change significantly depending on the Data or Message Contract?
(PS: I am trying to find a way so that existing WSE clients should be able to consume the WCF service without much alterations/modifications. Is it possible to use the current proxies generated from ASMX web services, to connect to the new WCF service just by setting URL of the proxy to WCF service?)
Here is a quick go at answering your questions:
1) Unless there is a specific reason like tweaking the structure of the soap XML, use DataContract instead of MessageContract.
2 & PS) Since you are currently using soap over HTTP, you'll most likely need the new services to be configured for basicHttpBinding. This will provide the interoperability that you need for the ASMX clients.
3) It shouldn't if the soap structure created by the WCF service matches your current soap.
I vaguely remember that WSE 3.0 supported some of the WS-* standards. If your current code depends on these then you may be able to also expose a wsHttpBinding for these operations but I don't think a default ASMX client works with a wsHttpBinding configured service.
It depends on control you need over resulting SOAP message. DataContract defines part of message body wrapped by element defined by operation. MessageContract defines a structure of whole message - you can use multiple body members, you don't have to use default wrapper element and you can also place some data into SOAP headers.
In your scenario the most important part is to define WCF to use same SOAP messages as your former WSE3 service. Here the important is how do you currently serialize data? If you use Xml serialization (and attributes) you can use it directly in WCF by switchinig from data contract serialization to xml serialization.
Btw. why did you use WSE3 instead of plain ASMX? Did you use message security? In such case you will need another binding. BasicHttpBinding is not able to do message security.
General answer is yes, you can create service wich your current client proxies will be able to consume. But in reality the effort depends on your current service and current code.

gsoap: how to make it configurable?

I've implemented client for my Web Service. Auto-generated files for each web method contain hardcoded bindings to web service end point:
soap_endpoint = "http://localhost/MyService.asmx";
It is fine for development purposes, but before pushing that to PROD I will need to replace those string with PROD web service address.
Is it possible to manage gSOAP in order it generated this string to be putted in some 'external' variable?
Or I should replace those end-point value each time before deployment?
Thanks.
The functions generated from the gSoap Compiler are looking like:
soap_call_ns1__foo(struct soap* soap, char *URL, char *action, char *symbol, resultType &Result);
The argument URL is the endpoint adress. If you pass NULL, the endpoint from the WSDL file is used. But your client can call this function with any other endpoint -- which for example is defined within your clients configuration file.
If your client is using the -- from the gSoap compiler generated -- proxy class, it is also possible to set the endpoint. The proxy class has a member called endpoint which you can set before calling the service methods.
In the gSoap compiler generated ***proxy.h header file you will find
"endpoint = "http://localhost/MyService" in the class constructor.
Replace "localhost" with the "IP-address" of your web-service before pushing it to PROD.