I have this simple JAX-WS WebService:
#WebService
public class AnimalFeedingService {
#WebMethod
public void feed(#WebParam(name = "animal") Animal animal) {
// Whatever
}
}
#XmlSeeAlso({ Dog.class, Cat.class })
public abstract class Animal {
private double weight;
private String name;
// Also getters and setters
}
public class Dog extends Animal {}
public class Cat extends Animal {}
I create a client and call feed with an instance of Dog.
Animal myDog = new Dog();
myDog .setName("Rambo");
myDog .setWeight(15);
feedingServicePort.feed(myDog);
The animal in the body of the SOAP call looks like this:
<animal>
<name>Rambo</name>
<weight>15</weight>
</animal>
and I get an UnmarshallException because Animal is abstract.
Is there a way to have Rambo unmarshalled as an instance of class Dog? What are my alternatives?
As you might have guessed, XML parser is not able to determine the exact subtype of animal you used when requesting because anything it sees is generic <animal> and a set of tags that are common to all types, hence the error. What JAX-WS implementation do you use? It is the responsibility of the client to properly wrap polymorphic types when sending request. In Apache CXF (I checked your code against newest 2.3.2 version) the SOAP request body looks like this:
<animal xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:dog">
<name>Rambo</name>
<weight>15.0</weight>
</animal>
The xsi:type="ns2:dog" is crucial here. It seems like your JAX-WS client is sending incorrect request that confuses the server. Try sending this request with some other client, like SoapUI, to see whether your server reacts properly.
As I said, it works just fine with Spring/Apache CXF and exactly the same code you've provided, I only extracted Java interface to make CXF happy:
public interface AnimalFeedingService {
#WebMethod
void feed(#WebParam(name = "animal") Animal animal);
}
#WebService
#Service
public class AnimalFeedingServiceImpl implements AnimalFeedingService {
#Override
#WebMethod
public void feed(#WebParam(name = "animal") Animal animal) {
// Whatever
}
}
...and the server/client glue code:
<jaxws:endpoint implementor="#animalFeedingService" address="/animal"/>
<jaxws:client id="animalFeedingServiceClient"
serviceClass="com.blogspot.nurkiewicz.test.jaxws.AnimalFeedingService"
address="http://localhost:8080/test/animal">
</jaxws:client>
Related
I am trying to unittest an API REST function.
builder = webTarget.request();
returns builder of the type
javax.ws.rs.client.Invocation.Builder
But if I take that builder and call builder.method("POST", entity) on it, the method called looks thus:
public Response method(final String name, final Entity<?> entity) throws ProcessingException {
requestContext.setMethod(name);
storeEntity(entity);
return new JerseyInvocation(this).invoke();
}
And the last line uses as "this" different builder:
org.glassfish.jersey.client.JerseyInvocation.Builder
And the run fails on that line.
I am looking at it and feel me crazy: How could it be, that the function is called as a member of one class, but when "this" is used in that method, absolutely different class is used?
Both Invocation and Invocation.Builder are interfaces. The WebTarget.request() contract is to return Invocation.Builder. These are all interfaces we are talking about here; WebTarget, Invocation, Invocation.Builder. This is contract design by the JAX-RS specification. It is up the JAX-RS implementation to implement these interfaces. Jersey implementation are JerseyWebTarget, JerseyInvocation, and JerseyInvociation.Builder, respectively.
It's the same if I created something like this
public interface Model {}
public interface Service {
Model getModel();
}
public ModelImpl implements Model {}
public class ServiceImpl implements Service {
#Override
public Model getModel() {
return new ModelImpl();
}
}
There's nothing special goin on here. The Service contract says that the getModel() method returns a Model, which is an interface, the actual return value will be of type ModelImpl, the implementation. Polymorphism in the works.
I recently ran across this scenario in code that I didn't write and while there may be some design benefit to this approach, I can't seem to squeeze this rationale out of my own brain. So before I go and look foolish, I'm hoping for some feedback here.
Service interface something like this:
public interface Service {...}
Then, a base class that adds a generic reference to the Service interface where T extends the Service, but then the overall base class also implements the interface. Something like this:
public class ServiceBase<T extends Service> implements Service {...}
Why would you do this? I'm noticing that in practice the extension of ServiceBase always uses the same class name as T as the one that is being declared; so there's not really any magic polymorphic benefit here. Something like this:
public class MyService extends ServiceBase<MyService> {...}
and, the MyService class is never a container for the generic (e.g., I don't believe this is signaling some kind of self-containing list, where MyService could contain a list of MyServices).
Any ideas/thoughts on why someone would do this?
Why would you do this? I'm noticing that in practice the extension of
ServiceBase always uses the same class name as T as the one that is
being declared; so there's not really any magic polymorphic benefit
here.
Generics don't exist to create magic polymorphim. It is mainly a way to add constraints on types at compile time in order to reduce clumsy cast and error type at runtime.
In your case, suppose that ServiceBase class is abstract and has a process() method which needs to create at each call a new instance of the concrete class we declare in the parameterized type.
We call this abstract method createService().
Without using generics, we could declare the method like that public abstract ServiceBase createService().
ServiceBase without generics
public abstract class ServiceBase implements Service {
public abstract ServiceBase createService();
#Override
public void process() {
createService().process();
}
}
With this declaration, the concrete class may return any instance of ServiceBase.
For example, the following child class will compile because we are not forced to change the returned type of createService() to the current declared type.
MyService without generics
public class MyService extends ServiceBase {
#Override
public ServiceBase createService() {
return new AnotherService();
}
}
But if I use generics in base class :
ServiceBase with generics
public abstract class ServiceBase<T extends Service> implements Service {
public abstract T createService();
#Override
public void process() {
createService().process();
}
}
The concrete class has no choice, it is forced to change the returned type of createService() with the parameterized type declared.
MyService with generics
public class MyService extends ServiceBase<MyService> {
#Override
public MyService createService() {
return new MyService();
}
}
I made up an example using your class and interface declarations (except that I made ServiceBase abstract) which should illustrate the use of the generic types:
public interface Service {
int configure(String cmd);
}
public abstract class ServiceBase<T extends Service> implements Service {
private ServiceManager manager;
public ServiceBase(ServiceManager manager){
this.manager = manager;
}
public final void synchronize(T otherService){
manager.configureEnvironment(otherService.configure("syncDest"), configure("syncSrc"));
synchronizeTo(otherService);
}
protected abstract void synchronizeTo(T otherService);
}
public class ProducerService extends ServiceBase<ConsumerService> {
public ProducerService(ServiceManager manager) {
super(manager);
}
#Override
protected void synchronizeTo(ConsumerService otherService) {
/* specific code for synchronization with consumer service*/
}
#Override
public int configure(String cmd) { ... }
}
public class ConsumerService extends ServiceBase<ProducerService> {
public ConsumerService(ServiceManager manager) {
super(manager);
}
#Override
protected void synchronizeTo(ProducerService otherService) {
/* specific code for synchronization with producer service */
}
#Override
public int configure(String cmd) { ... }
}
Imagine we have services managed by a ServiceManager which can configure the environment of the services so that they are ready for synchronization with each other. How a configure command is interpreted is up to the specific service. Therefore a configure() declaration resides in our interface.
The ServiceBase handles the basic synchronization stuff that has to happen generally when two services want to synchronize. The individual implementations of ServiceBase shouldn't have to deal with this.
However ServiceBase doesn't know how a specific implementation of itself synchronizes to a specific other implementation of service. Therefore it has to delegate this part of synchronization to its subclass.
Now generics come into the play. ServiceBase also doesn't know to which type of service it is able to synchronize to. He has also to delegate this decision to its subclass. He can do this using the construct T extends Service
Given this structure now imagine two concrete subclasses of ServiceBase: ProducerService and ConsumerService; The consumer service can only synchronize to the producer service and the other way around. Therefore the two classes specify in their declaration ServiceBase<ConsumerService> respectively ServiceBase<ProducerService>.
Conclusion
Just like abstract methods can be used by superclasses to delegate the implementation of functionality to their subclasses, generic type parameters can be used by superclasses to delegate the "implementation" of type placeholders to their subclasses.
You haven't posted any of the definitions of these classes where the type parameter is used (which would most likely convey the rationale behind this design, or maybe the lack of it...), but in all cases, a type parameter is a way of parameterizing a class, just like a method can be parameterized.
The ServiceBase class implements a Service. This tells us that it implements the contract (methods) of a Service (to be more precise, subclasses of it can act as the implementation).
At the same time, ServiceBase takes a type argument that is a subtype of Service. This tells us that a service implementation probably has a "relationship" with another implementation type (possibly the same type as the current one). This relationship could be anything needed by the specific design requirement, e.g. the type of Service that this implementation can delegate to, the type of Service that can call this service, etc.
The way I read the following declaration
public class ServiceBase<T extends Service> implements Service {...}
is roughly: ServiceBase is a base implementation of a service, which can have a statically typed relationship with some other type of service.
These two aspects are completely independent.
I have created a JaX Webservice through RAD(eclipse), and I am able to use the #WebParam annotation with my function parameter, however I also want to use #webresult etc but Don't know where should i specify them, on google I got interfaces but here i only have class and delegate class.
my class is
public class GetFPDDataClass {
public String GetFPDDataInput(String PolicyNumber)
{
return PolicyNumber;
}
}
and this is my delegate class
#WebService (targetNamespace="fpd", serviceName="GetFPDDataClassService", portName="GetFPDDataClassPort")
public class GetFPDDataClassDelegate{
fpd.GetFPDDataClass _getFPDDataClass = null;
public String GetFPDDataInput (#WebParam(name="PolicyNumber") String PolicyNumber) {
return _getFPDDataClass.GetFPDDataInput(PolicyNumber);
}
public GetFPDDataClassDelegate() {
_getFPDDataClass = new fpd.GetFPDDataClass(); }
}
Both #WebResult and #WebMethod are set on the method level.
#WebResult is used to customize name of the XML element that represents the return value.
#WebMethod is used to mark business methods that are exposed to web service clients. By default all public methods in your class are exposed, if you don't implement web service interface.
Example:
#WebMethod
#WebResult(name="hellomessage")
public String getHello() {
....
}
UPDATE:
If I dont have #WebResult I see the following xml:
<ns2:getHelloResponse>
<return>hello fff</return>
</ns2:getHelloResponse>
with #WebResult:
<ns2:getHelloResponse>
<hellomessage>hello fff</hellomessage>
</ns2:getHelloResponse>
I would just know if inheritance is supported in Google Cloud Endpoints methods. Here is the scenario:
I have an interface :
public interface A {
public String getSomething();
}
and a class that implements that interface :
public class B implements A {
public String getSomething(){
return "hello";
}
}
In my class annotated with #Api I wold have a method like this :
#ApiMethod()
public void submitStatistic(A statistic)
Then when I generate the client library the B class is not generated but only the interface A is transformed in a class that is available to client side. Is there something to force in some way the transformation of class B ? and also to maintain the inheritance between this classes ?
Thank you for reading.
Yes you can:
https://developers.google.com/appengine/docs/java/datastore/jdo/dataclasses#Inheritance
and
http://www.datanucleus.org/products/accessplatform/jdo/orm/inheritance.html
Looks like you may need to include a couple extra lines to get it to work over normal Java.
#XmlSeeAlso({ Dog.class, Cat.class })
public abstract class Animal {}
#XmlRootElement(name="dog")
public class Dog extends Animal {}
#XmlRootElement(name="cat")
public class Cat extends Animal {}
#WebService(name = "WebServiceDemo", serviceName = "WebServiceDemo")
#SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL,
parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class WebServiceDemo {
#WebMethod
public String service(#WebParam(name = "animal") Animal animal) {
System.out.println("animal service calling.....");
return animal;
}
}
Now when i am calling this service method from client with Animal calss as a parameter that time i am getting error-
Caused by: javax.xml.bind.UnmarshalException: Unable to create an instance of Animal
- with linked exception:
[java.lang.InstantiationException]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:616)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:244)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:583)
at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.startElement(StructureLoader.java:181)
at com.sun.xml.bind.v2.runtime.unmarshaller.XsiTypeLoader.startElement(XsiTypeLoader.java:73)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:455)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:433)
at com.sun.xml.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:71)
at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137)
at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:240)
at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:277)
at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:246)
at com.sun.xml.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:123)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:314)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:293)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:244)
at org.jboss.ws.core.jaxws.JAXBDeserializer.deserialize(JAXBDeserializer.java:71)
Abstract classes cannot be instantiated, that is the basic rule for them in Java. From the javadocs:
An abstract class is a class that is declared abstract—it may or may
not include abstract methods. Abstract classes cannot be instantiated,
but they can be subclassed.
Jaxb internally will try to unmarshall your xml to the java object. But if it is not able to create an object of Animal, how will it work. Hence it throws the exception. You need to provide a non-abstract class to JaxB to work.