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
Related
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).
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…
Here's a problem I am facing.
I am writing a plugin. There is an interface called SystemObject, and a default getter.
public class MyPlugin extends Plugin {
#override
public SystemObject getSystemObject() {
return super.getSystemObject();
}
}
SystemObject interface has a method called getScreenSize() which I would like to proxy or intercept. When I create a proxy class, or simply implement this SystemObject interface myself, I get a class cast exception.
This is because the caller for getSystemObject (part of the plugin system) has this in their code (found via reverse-engineering):
private void foo() {
SystemObjectImpl impl = (SystemObjectImpl)plugin.getSystemObject();
}
My question is: is there any way I can proxy calls on the SystemObject interface?
I tried implementing the interface and using java reflection proxy invocation to no avail. Unfortunately, I'm not responsible for running the java process, so I can't use an agent.
Cheers!
You could use something like CGLIB to create a proxy class that extends SystemObjectImpl.
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();
}
}
In all of the Guice examples I have found, getting an instance involves calling Injector.getInstance() with the concrete class as a parameter. Is there a way to get an instance from Guice using only the interface?
public interface Interface {}
public class Concrete implements Interface {}
Interface instance = injector.getInstance(Interface.class);
Thanks
Actually that's exactly what Guice is made for.
In order to make getInstance() work with an interface you'll need to first bind an implementation of that interface in your module.
So you'll need a class that looks something like this:
public class MyGuiceModule extends AbstractModule {
#Override
protected void configure() {
bind(Interface.class).to(Concrete.class);
}
}
Then when you create your injector you just need to pass an instance of your module in:
Injector injector = Guice.createInjector(new MyGuiceModule());
Now your call to injector.getInstance(Interface.class) should return a new instance of Concrete using the default constructor.
Of course there are many many more ways you can do bindings but this is probably the most straight forward.
It works for interface as well:
bind( Interface.class ).to( Concrete.class );
Without using a Module, you can also specify the implementation class to be used by default, directly in the interface declaration:
#ImplementedBy(Concrete.class)
public interface Interface {}
This doesn't necessarily fit every situation but I found this comes in handy most of the times.
Additionnally, when using #ImplementedBy annotation, you can still override the implementation class by binding another concrete class in a Module. That can also be useful.