I am migrating a SOAP web service to JDK1.5.
I have took advantage of native java enums in the new code.
For some reasons, I'm stuck with Axis 1.2 and it does not natively support JDK5 "enums".
I have found a tutorial on how to implement custom a serialization / deserialization for java enums:
http://www.developpez.net/forums/d236564/java/developpement-web-java/web-services/utiliser-type-enum-jdk5-axis/ (in French).
I have been able to successfully register those custom serialization handlers on the server side via the use of "typeMapping" elements in the ".wsdd" file.
However, I can't figure out how to register the same classes on the client side, as I do not have a ".wssd" file here.
Any help would be appreciated.
Thanks,
Raphael
I have finally found how to manually register a custom type mapping.
I do it when creating an instance of a Service :
service = new Service();
// Get default type mapping
TypeMapping tmap = DefaultTypeMappingImpl.getSingletonDelegate();
// Register our custom serializer / deserializer
tmap.register(
MyCustomClass.class,
MyCustomClassQName,
new MyCustomSerizalizerFactory(),
new MyCustomDeserizalizerFactory());
// Add it back to the service
service.getTypeMappingRegistry().register(
"http://schemas.xmlsoap.org/soap/encoding/", // Default encoding
tmap);
I don't know whether it is the right way to do it, but it works !
Related
I have two instances of clients with different configs that I am creating (timeout, threadpool, etc...), and would like to leverage Dropwizard's metric on both of the clients.
final JerseyClientBuilder jerseyClientBuilder = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration());
final Client config1Client = jerseyClientBuilder.build("config1Client");
environment.jersey().register(config1Client);
final Client config2Client = jerseyClientBuilder.build("config2Client");
environment.jersey().register(config2Client);
However, I am getting
org.glassfish.jersey.internal.Errors: The following warnings have been detected:
HINT: Cannot create new registration for component type class org.glassfish.jersey.client.JerseyClient:
Existing previous registration found for the type.
And only one client's metric shows up.
How do I track both clients' metrics or is it not common to have 2 clients in a single dropwizard app?
Never mind, turned out I was an idiot (for trying to save some resource on the ClientBuilder).
2 Things that I did wrong with my original code:
1. You don't need to register Jersey clients, just the resource is enough... somehow I missed the resource part in my code and just straight up trying to register the client
2. You need to explicitly build each JerseyClientBuilder and then build your individually configured clients, then dropwizard will fetch by each JerseyClientBuilder's metrics
In the end, I just had to change my code to the following:
final Client config1Client = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration()).build("config1Client");
final Client config2Client = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration()).build("config2Client");
Doh.
environment.jersey().register() has a javadoc listing of Adds the given object as a Jersey singleton component meaning that the objects registered become part of the jersey dependency injection framework. Specifically this method is used to add resource classes to the jersey context, but any object with an annotation or type that Jersey looks for can be added this way. Additionally, since they are singletons you can only have one of them per any concrete type (which is why you are getting a "previous registration" error from Jersey).
I imagine that you want to have two Jersey clients to connect to two different external services via REST/HTTP. Since your service needs to talk to these others to do its work, you'll want to have the clients accessible wherever the "work" or business logic is being performed.
For example, this guide creates a resource class that requires a client to an external http service to do currency conversions. I'm not saying this is a great example (just a top google result for dropwizard external client example). In fact, I think this not a good to structure your application. I'd create several internal objects that hide from the resource class how the currency information is fetched, like a business object (BO) or data access object (DAO), etc.
For your case, you might want something like this (think of these as constructor calls). JC = jersey client, R = resource object, BO = business logic object
JC1()
JC2()
B1(JC1)
B2(JC2)
R1(B1)
R2(B2)
R3(B1, B2)
environment.jersey().register(R1)
environment.jersey().register(R2)
environment.jersey().register(R3)
The official Dropwizard docs are somewhat helpful. They at least explain how to create a jersey client; they don't explain how to structure your application.
If you're using the Jersey client builder from dropwizard, each of the clients that you create should be automatically registered to record metrics. Make sure you're using the client builder from the dropwizard-client artifact and package io.dropwizard.client. (Looks like you are because you have the using(config) method.)
Having a SOAP based web service with XML payload, how can I grab the XML payload of the service response in JAX-WS >2.0 client?
I can see how this question will be marked as duplicate, but bear with me.
It seems that the options are:
Use Dispatch API. However this would require me to go low(er) level and create the request payload manually, which I want to avoid.
Use handler infrastructure of the JAX-WS to grab the payload and possibly pass it via MessageContext property back to the client, but this will still unmarshall the XML into JAXB Object tree, which I want to avoid.
So, how can I:
Call a web service using SEI - no messing with creating XML request from scratch
Grab the 'RAW' XML response without the JAXB unmarshalling happening
Sounds simple enough, right?
Among the non-goals the JAX-WS 2 specification says that
'Pluggable data binding JAX-WS 2.0 will defer data binding to JAXB[10]; it is not a goal to provide a
plug-in API to allow other types of data binding technologies to be used in place of JAXB. However,
JAX-WS 2.0 will maintain the capability to selectively disable data binding to provide an XML based
fragment suitable for use as input to alternative data binding technologies.'
So, you should be able to have access to the raw payload.
The following example is also in the specification :
4.3.5.5 Asynchronous, Callback, Payload-Oriented
class MyHandler implements AsyncHandler<Source> {
...
public void handleResponse(Response<Source> res) {
Source resMsg = res.get();
// do something with the results
}
}
Source reqMsg = ...;
Service service = ...;
Dispatch<Source> disp = service.createDispatch(portName,
Source.class, PAYLOAD);
MyHandler handler = new MyHandler();
disp.invokeAsync(reqMsg, handler);
Since the specification also states that a Binding has its own HandlerChain (see chapter 9) you should be able to remove the JAXB handler from the chain, so that JAXB marshalling/unmarshalling doesn't get involved.
I am currently working on a web project which is using Play Framework 2.1.0. Play supports a decent API for parsing form data and mapping that to the Model beans directly. Which looks something like,
Form<Employee> form = Form.form(Employee.class).bindFromRequest();
if (form.hasErrors()) {
return badRequest(template.render(form));
}
This API also does validations on the fly and is capable of handling binding failures, when say a String could not be converted to an Integer. The Form API keeps the collection of errors mapped to the name of the property. Underlying the Form API, Play is using DataBinder of Spring's validation framework which is actually doing all the magic.
I was wondering if there is similar binding API to convert from JSON to the bean directly, with support for handling binding failures?
Play 2.0 uses Jackson internally which fails when there are binding failures and simply throws an exception. I looked at the code and does not look easy to supress these errors.
Is there some framework that can satisfy my requirement out of the box?
Essentially, I need the framework to convert from JSON to Java Bean, which can handle binding failures gracefully.
It would be wonderful if it allows me to collect them somewhere so I can generate appropriate validation errors. I will run custom validations on the parsed object using javax.validation APIs to perform more specific validations once the JSON is parsed into the Bean.
I achieved this by adding custom deserializers in Jackson
SimpleDeserializers deserializers = new SimpleDeserializers();
deserializers.addDeserializer(Integer.class, new MyIntegerDeserializer(null));
deserializers.addDeserializer(Long.class, new MyLongDeserializer(null));
ObjectMapper mapper = new ObjectMapper().setDeserializerProvider(
new StdDeserializerProvider().withAdditionalDeserializers(deserializers));
MyModel value = mapper.treeToValue(node, MyModel.class);
MyIntegerDeserializer and MyLongDeserializer are custom deserializers for Integer and Long values respectively. These are in my case exact copy of the internal default corresponding deserializer classes with additional code to gracefully handle NumberFormatException
Is there any way to use soap-rpc web services such that the client is generated via a shared interface? Restful web services do it this way, but what about soap based? Do you always have to use a tool like Axis or CXF to generate your stubs and proxies, or is there something out there that will set it up dynamically?
Thanks.
EDIT #1:
To clarify, I'm looking to do something like this:
Common interface:
#WebService
public interface MyWebService {
#WebMethod
String helloWorld();
}
This common interface can already be used to create the server side component. My question is: can this type of common interface be used on the client side to generate dynamic proxies? Restful web services do it this way (Restlets & CXF) and it seems the .Net world has this type of functionality too.
I would see this tutorial of JAX-WS useful for your purposes:
In the example code the Web Services Client is configured by adding an annotation #WebServiceRef with a property pointing to the WSDL location to the client implementation class and no tools are needed to access the stuff from the Web Service that is referenced.
Was this the way you would like to have it, or did this even answer to right question?
Not exactly sure what you're looking for, but if you don't want to rely on JAX-WS/JAXB-generated artifacts (service interfaces and binding objects), you can make use of the Service and Dispatch APIs. For example:
QName serviceName = new QName(...);
Service service = Service.create(serviceName);
QName portName = new QName(...);
String endpointAddress = "...";
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
SOAPMessage request = ...;
SOAPMessage response = dispatch.invoke(request);
Check Apache CXF. Configuring a Spring Client (Option 1).
When you want to call a webservice, you must have knowledge of methods implemented on it. For that, We need to make stubs OR we can read it from WSDL.
I have created a WS client, using AXIS2 libraries, which is without stubs. The thing is, for each diff. WS we need to create response handles.
You can call any WS method using SOAP envelops and handle the response.
//common interface for response handlers...
//implement this for diff. web service/methods
public interface WSRespHandler{
public Object getMeResp(Object respData);
}
//pass particular handler to client when you call some WS
public class WebServiceClient {
public Object getResp(WSRespHandler respHandler) {
...
return repHandler.getMeResp(xmlData);
}
}
Please check the link below, which shows the example interface for WS client.
http://javalibs.blogspot.com/2010/05/axis2-web-service-client-without.html
For every diff. WS method we can have diff. implementation for WSRespHandler interface, which will help parsing the response.
Not knowing java so well, but being forced to learn some to accomplish a task that I was given, I needed to consume a .Net service that I have already written, I had to do a little research.
I found that 99% of the examples/samples/problems with invoking a method call against a .Net service, or any service for that matter involved using J2EE (ServiceManager) or build classes and a proxy that reflect the service being invoked. Unfortunately for me, none of this would work. I was working "in a box". I could not add new classes, could not WSDL references, did not have J2EE, but DID have access to the standard java libs.
I am used to doing this sort of thing in pretty much every other language but java, but now there was no choice, and java it was.
A lot of digging and figuring out all new terminology, methods, classes, etc, I knew I was getting close, but was having issues with some small items to complete the task.
Then I came across this post: http://www.ibm.com/developerworks/xml/library/x-jaxmsoap/
As long as you have some sort of idea of what you need to send the soap service in term of the soap envelope, the above link will give you the information you need to be able to invoke a service without the classes, wsdl class generators and J2EE, apache or other dependencies.
In an hour from the time I read the mentioned article, I had a class working and about 10 minutes later, converted the code to the "in the box" solution.
Hope this helps
Apache Tuscany might help you, although it may be heavier than you want
http://tuscany.apache.org/
Is it possible with Axis2 and Eclipse to generate a Web Service client and have it use java types that you already have in packages instead of creating it's own types. Reason being of course if I have type A already created and it creates it's own Type A I can't just assign variable of type A to variable of type B.
The wsdl is being generated from a Web Service deployed to an application server.
If it's not possible to generate it from that would it be possible to generate a client from the already existing java files.
If you really want to reuse existing classes, you can call the Axis2 API directly without generating a client using wsdl2java. Below is some relatively simple code to call a web service. You just need to fill in the web service endpoint, method QName, expected return Class(es), and arguments to the service. You could reuse your existing classes as the return values or arguments.
If your web service is pretty complicated then you may find that you have to go deeper into the API to get this approach to work.
serviceClient = new RPCServiceClient();
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference("http://myservice");
options.setTo(targetEPR);
QName methodName = new QName("ns","methodName");
Class<?>[] returnTypes = new Class[] { String.class };
Object[] args = new Object[] { "parameter" };
Object[] response = serviceClient.invokeBlocking(methodName, args,
returnTypes);
You are generating the web service client from wsdl, correct?
The only thing that the wsdl2java tool knows about is the information in the wsdl, so it won't know about any types that you have already created.
If you can get the type information into the wsdl you may get it to work, although I have never tried.
If you want an easy way to copy from Type A to Type B then you could try BeanUtils.copyProperties, as long as the setters and getters of Type A and Type B match.
pretty much most java webservices projects go through this. I don't know if the .NET/C# world have a more elegant solution.
It makes sense, as Mike mentioned, to use BeanUtils.copyProperties.
BR,
~A
If you use eclipse as your ide, that is waht you need: http://www.eclipse.org/webtools/. It does beyond other things exactly what you want.
You can directly use ServiceClient class to call web service, which provides call using XML only and returns XML response. For different methods of web service, you have to convert the XML response to some java POJO to use it. Only Response handling needs to be done at your end. that you can do like from XML to Map etc...
So you won't need any other stub classes to call any web service, only needs to handle response XML. You can convert XML to POJO using Castor or JAXB libs.
This is the way you don't need to modify your client every time for diff. web services. You can develop like providing a response handler to client externally. So that for every different web service you will have diff. response handler class which is implementation of you interface.
//common interface for response handlers...
//implement this for diff. web service/methods
public interface WSRespHandler{
public Object getMeResp(Object respData);
}
//pass particular handler to client when you call some WS
public class WebServiceClient {
public Object getResp(WSRespHandler respHandler) {
..
return repHandler.getMeResp(xmlData);
}
}
reference:
http://www.developer.com/java/web/article.php/3863416/Using-Axis2-and-Java-for-Asynchronous-Web-Service-Invocation-on-the-Client-Side.htm
http://www.devdaily.com/blog/post/java/java-web-service-client-read-array-list/
thanks.
www.techlads.com
In case this post is still of any use to someone I read the axis2 generating clients guide: http://axis.apache.org/axis2/java/core/docs/userguide-creatingclients.html.
It seems that the Axis2 Eclipse plugin is configured to call ADB code generation in integrated mode (see http://axis.apache.org/axis2/java/core/docs/adb/adb-howto.html), thus creating inner classes in the Web service stub. I don't know if changing the generation mode to expanded mode (generate data classes out of the stub class) is possible, but you can do it command line using Wsdl2Java:
%AXIS2_HOME%\bin\WSDL2Java -uri <wsdl file path> -p <package name> -u
The -u option tells the ADB code generator to create data classes as separate classes and not inner classes in the stub.