JAXB cannot handle an interface - what am I missing? - java

I'm getting familiar with web services in Java using Jax-ws (or JAXB, not sure, anyway...).
I've created small project with a single webservice. The WS has the only endpoint called transfer and returns objects inheriting ITransferResult interface.
Web service contract
//Service Endpoint Interface
#WebService
#SOAPBinding(style = Style.RPC)
public interface IBankWebSrv {
#WebMethod
ITransferResult transfer(String accountNumber, double amount);
}
Web service implementation
//Service Implementation
#WebService(endpointInterface = "Contracts.IBankWebSrv")
public class BankWebSrv implements IBankWebSrv {
#Override
public ITransferResult transfer(String accountNumber, double amount) {
ITransferResult result = new TransferResult();
// TODO logic here
result.setSuccessful(true);
return result;
}
}
TransferResult contract
#XmlJavaTypeAdapter(TransferResult.class)
public interface ITransferResult {
boolean isSuccessful();
void setSuccessful(boolean successful);
}
TransferResult implementation
public class TransferResult extends XmlAdapter<TransferResult, ITransferResult>
implements ITransferResult {
#XmlElement
boolean successful;
public boolean isSuccessful() {
return this.successful;
}
public void setSuccessful(boolean successful) {
this.successful = successful;
}
#Override
public TransferResult marshal(ITransferResult v) throws Exception {
return (TransferResult) v;
}
#Override
public ITransferResult unmarshal(TransferResult v) throws Exception {
return (ITransferResult) v;
}
}
When I publish my web service, I get the following error:
Exception in thread "main" javax.xml.ws.WebServiceException: Unable to
create JAXBContext...
Caused by: java.security.PrivilegedActionException:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1
counts of IllegalAnnotationExceptions ITransferResult is an interface,
and JAXB can't handle interfaces. this problem is related to the
following location: at ITransferResult
I've looked over SO for the answer and applied to the most repetitive tips, but none of them have worked for me yet.
What am I missing?

You may need to change the style to be DOCUMENT instead of RPC in your declaration at #SOAPBinding(style = Style.RPC)
Although this is an old question, I thought I'd answer it as it's common exception people encounter.
The difference between the two styles in high level is as follows
Document: The return type and method arguments are clearly explained in a separate XSD with each type in detail - helpful in case of custom data types (Example in your case ITransferResult or java.util.List).
RPC: the types are defined in the WSDL itself in simple manner.

It looks like it's not processing the annotations on the TransferResult class as a bindable element. That means you probably need to add #XmlSeeAlso(TransferResult.class) to the interface (ITransferResult). You also need to put #XmlRootElement on the serialization-implementation (TransferResult) so that an actual XML document can be produced, and not just a type that you use in some other document. This is because when the JAX-WS implementation is creating the JAXB context that it uses internally, it only uses the argument and result types that you define on the service interface as arguments to JAXB.newInstance(…); anything not literally listed there (or findable via simple following the types) will be omitted, and it's entirely possible that the type adapters used are not processed for annotations (after all, they don't need to be instances of the interface they're adapting, nor does the type being adapted need to be an interface).
(Yes, a SOAP response is an enclosing document, but the recommended way of using it is to put a single element inside the SOAP Body, and that means you need to know the name of the element. Which means an #XmlRootElement annotation.)
Warning: I'm not 100% sure that this will work. If it doesn't, you'll have to switch to using concrete types (probably straight POJOs) as results. It might not be a particularly palatable thing, but it's at least easy to do…

Related

Collections usable in a class denoted as a Fault Bean for a #WebFault

All examples I've found of classes denoted as #WebFault for a SOAP web service contain an array of Fault Beans, and the class denoted as the fault bean contain an int, a String, and sometimes a List .
My webservice makes use of a build-step using java2ws to create the wsdl.
Question 1) can a SOAP webservice have more than one #WebFault? One would think so.
Question 2) can the fault bean class take a Set? and can the elements in the set be classes ie Set ?
The goal here is to propagate JSR-303 bean validation failures from the server back to the web service client where a form is waiting to be updated with 0,1, or >1 error messages.
TIA,
Still-learning Steve
Question 3) can the #WebFault class take a Set<> instead of an array?
1) Yes, a single operation can have multiple faults, just like in Java a method can throw more than one checked exception
2) Not sure exactly what you're asking.
Let me just show one quick example of what you can do..maybe it points you in a helpful direction:
// MyIntf.java
#WebService
public interface MyIntf {
#WebMethod
void myMethod() throws MyFault;
//...
}
// MyFault.java
#WebFault(faultBean="mypkg.MyFaultBean")
public class MyFault extends Exception {
private MyFaultBean bean;
public MyFault(MyFaultBean bean, String message) {
super(message);
this.bean = bean;
}
public MyFault(MyFaultBean bean, String message, Throwable cause) {
super(message, cause);
this.bean = bean;
}
public MyFaultBean getFaultInfo() {
return bean;
}
}
// MyFaultBean.java
public class MyFaultBean {
private Set mySet;
public Set getMySet() {
return mySet;
}
public void setMySet(Set mySet) {
this.mySet = mySet;
}
//...
}
So you're trying to use JAXB and JAX-WS to map between Java exceptions and WSDL faults (putting it that way might help your searches).
One thing to consider is whether to approach this top-down (WSDL/XSD primary, Java secondary) or bottom-up (Java primary).
If you don't already have a fixed Java interface that you're trying to use (sounds like you may not, but maybe you do), you might be better off starting from WSDL/XSD, then using wsdl2java to generate the Java interface, then maybe customizing it a bit using JAXB customizations.
A couple more links on the subject here and here, (the latter mentions "SCA" but this uses JAX-WS and JAXB so is relevant).

How can I override a method of an anonymous generic class?

I am working on GWT project with JDK7. It has two entryPoints (two clients) that are located in separate packages of the project. Clients share some code that is located in /common package, which is universal and accessible to both by having the following line in their respective xml-build files:
<source path='ui/common' />
Both clients have their own specific implementations of the Callback class which serves their running environments and performs various actions in case of failure or success. I have the following abstract class that implements AsyncCallback interface and then gets extended by its respective client.
public abstract class AbstractCallback<T> implements AsyncCallback<T> {
public void handleSuccess( T result ) {}
...
}
Here are the client's classes:
public class Client1Callback<T> extends AbstractCallback<T> {...}
and
public class Client2Callback<T> extends AbstractCallback<T> {...}
In the common package, that also contains these callback classes, I am working on implementing the service layer that serves both clients. Clients use the same back-end services, just handle the results differently. Based on the type of the client I want to build a corresponding instance of AbstractCallback child without duplicating anonymous class creation for each call. I am going to have many declarations that will look like the following:
AsyncCallback<MyVO> nextCallback = isClient1 ?
new Client1Callback<MyVO>("ABC") {
public void handleSuccess(MyVO result) {
doThatSameAction(result);
}
}
:
new Client2Callback<MyVO>("DEF") {
public void handleSuccess(MyVO result) {
doThatSameAction(result);
}
};
That will result in a very verbose code.
The intent (in pseudo-code) is to have the below instead:
AsyncCallback<MyVO> nextCallback = new CallbackTypeResolver.ACallback<MyVO>(clientType, "ABC"){
public void handleSuccess(MyVO result) {
doThatSameAction(result);
}
};
I was playing with the factory pattern to get the right child instance, but quickly realized that I am not able to override handleSuccess() method after the instance is created.
I think the solution may come from one of the two sources:
Different GWT way of dealing with custom Callback implementations, lets call it alternative existent solution.
Java generics/types juggling magic
I can miss something obvious, and would appreciate any advice.
I've read some articles here and on Oracle about types erasure for generics, so I understand that my question may have no direct answer.
Refactor out the handleSuccess behavior into its own class.
The handleSuccess behavior is a separate concern from what else is going on in the AsyncCallback classes; therefore, separate it out into a more useful form. See Why should I prefer composition over inheritance?
Essentially, by doing this refactoring, you are transforming an overridden method into injected behavior that you have more control over. Specifically, you would have instead:
public interface SuccessHandler<T> {
public void handleSuccess(T result);
}
Your callback would look something like this:
public abstract class AbstractCallback<T> implements AsyncCallback<T> {
private final SuccessHandler<T> handler; // Inject this in the constructor
// etc.
// not abstract anymore
public void handleSuccess( T result ) {
handler.handleSuccess(result);
}
}
Then your pseudocode callback creation statement would be something like:
AsyncCallback<MyVO> nextCallback = new CallbackTypeResolver.ACallback<MyVO>(
clientType,
"ABC",
new SuccessHandler<MyVO>() {
public void handleSuccess(MyVO result) {
doThatSameMethod(result);
}
});
The implementations of SuccessHandler don't have to be anonymous, they can be top level classes or even inner classes based on your needs. There's a lot more power you can do once you're using this injection based framework, including creating these handlers with automatically injected dependencies using Gin and Guice Providers. (Gin is a project that integrates Guice, a dependency injection framework, with GWT).

JSON deserialize only with at least 2 parameters

I'm implementing a RESTful service application for TomEE Plus 1.7.1 with Jettison as default json provider. I have several facade classes for my entitiy classes to provide CRUD functionalities for each of them. Service facades have been generated by netbeans.
This is the POST method:
#POST
public void create(Course entity) {
super.create(entity);
}
While using this method (to create a new instance in the database) I got following error:
No message body reader has been found for request class Object, ContentType : application/json.
After several hours of trying, I got it to work: I only had to add another parameter to the method, like that:
#POST
public void create(#Context Context uriInfo, Course entity) {
super.create(entity);
}
I don't understand why I had to add this Context parameter. I don't need the context variable, so actually I would like to remove it...
Does anybody know the reason?
Okay, I think I found the solution:
All my rest services have been implemented as facade classes. The abstract facade (super class of all services) has several methods like:
public void create(T entity) { getEntityManager().persist(entity); }
public void edit(T entity) {getEntityManager().merge(entity);}
These methods are used by the facade classes:
public void create(Course entity) {
super.create(entity);
}
public void edit(#PathParam("id") Integer id, Course entity) {
super.edit(entity);
}
(for better viewing I've removed the annotations here)
The difference between these two methods is, that the edit method has a second parameter "id" and so does not override the edit() method of the super class. But the create() method does only have a single parameter which causes override of the super class method "create()". I don't know why, but cxf is now creating two endpoints:
POST http://localhost:8080/webprog/api/course/ -> void create(Course)
POST http://localhost:8080/webprog/api/course/ -> void create(Object)
This is also the reason why I got it working with a secon parameter: The create() method is not getting overriden anymore.
So what i did now, is simply renaming the method in de super class, to not override them in the facade classes.
by the way: all services classes have been created by netbeans generator... maybe there is a bug in it
Here are some of the pointers
Make sure you have jettison jar in your classpath, CXF automatically registers jettison as json provider.
#Context Context is not mandatory, so if you want to access some context parameters you can add.
For Method create add Media Type #Consumes(MediaType.APPLICATION_JSON)
Finally Check why you are getting No message body reader has been found for request class Object Ideally you should have got No message body reader has been found for request class Course(There might be some issues with your class definations)

What is the right way to organize Jersey resources using inheritance and generics?

I'm developing an app with Jersey where I have many resources. Although main functionality of these resources varies, they share lots of common methods (like list, read, update and etc). The app runs on Google App Engine and uses Guice for dependency injection.
My first approach was to have a generic AbstactResource which contains all common logic, and it's respectively extended by all other resources which add their required custom methods.
public class AbstractResource<T> {
#GET
public ListPage<T> list(#QueryParam("limit") Integer limit,
#QueryParam("start") Integer start) {
// ... implementation
}
#GET
#Path("/{id}")
public T get(#PathParam("id") Long id) {
// ... implementation
}
And sample resource looks like:
public class TenantResource extends AbstractResource<Tenant> {
// custom resource related methods here
}
Everything works fine in this case. The problems appear when I add one more level of abstraction. Let's say if I want to store history and changelogs only for some of my resources. I've created one more abstract class extending AbstractResource called AudiatableResource which adds the required functionality.
public abstract class AuditableResource<T extends AuditableModel>
extends AbstractResource {
// here I override update and create methods to save changelogs
}
As you see the type parameter in this case has changed (now it extends AuditableModel).
New concrete resources will look like:
public class PropertyResource extends AuditableResource<Tenant> {
// custom resource related methods here
}
In this case everything still works, but this time I'm getting lots of warning messages on start-up:
WARNING: Return type T of method public T com.pkg.AbstractResource.get(java.lang.Long) is not resolvable to a concrete type
WARNING: Return type T of method public T com.pkg.AbstractResource.getNew() is not resolvable to a concrete type
WARNING: Return type com.pkg.data.ListPage<T> of method public com.pkg.ListPage<T> com.pkg.AbstractResource.list(java.lang.Integer,java.lang.Integer) is not resolvable to a concrete type
I really wonder if this approach is correct using Jersey and if I can just ignore this messages. It would be interesting to know how resources are organized in cases when there are large number of them.
One way to go is to separate the definition of the resources from the implementation.
Have very simple resource classes, defining the different services you want to offer. This way, the API you expose through rest is easily located and audited. The different methods are probably delegates to an implementation class
Implement the business logic of your resources in the implementations, where you might want to use inheritance to factor common behavior.
The reason you get those messages at runtime is that jersey uses runtime information about types in the resource. Generic type information being erased at compile time, it cannot get the actual return type of the generic class methods. If you provide a REST "facade" to your implementation, you can make this explicit.
public class Facade {
private final PropertyResource propertyResource;
public Facade() {
propertyResource = new PropertyResource();
}
#GET
#Path("somepath")
public Tenant something() {
return propertyResource.something();
}
}

Java Webservice with generic methods

I was wondering if it is possible to make a generic webservice method in java like this:
#WebMethod
public <T extends Foo> void testGeneric(T data){
However when I try to consume this with a Java client I get an error stating:
[ERROR] Schema descriptor {http://####/}testGeneric in message part "parameters" is not defined and could not be bound to Java.
I know it is possible to make a method that takes a parameter such as List and this generates correctly using JAX-WS.
I don't mind if there is a solution that means I am tied to using only a particular technology.
Thanks,
Dan.
I doubt it. But you can define a generic super interface and let your actual service interface extend it with parameters:
public interface BaseService<T>{
T doWhackStuff();
}
public interface WhackyService extends BaseService<Whack>{
}
public interface EvenMoreWhackyService extends BaseService<Whackier>{
}
This approach usually only makes sense if you build your interfaces from multiple components:
public interface BaseService<T>{
T doWhackStuff();
}
public interface ExtendedService<T>{
T doMoreWhackStuff();
}
public interface DoubleWhackyService extends BaseService<Whack>, ExtendedService<Whack>{
}
I have not tested this approach in JAX-WS, but I know it works in Spring / GraniteDS / Flex

Categories

Resources