Skip to main content

A Handler closer to java.lang.reflect.InvocationHandler?

11 replies [Last post]
andreou
Offline
Joined: 2005-12-21
Points: 0

The programming interface of LogicalHandler is pretty useless to me (too low-level). I need something more closer to java.lang.reflect.InvocationHandler, that is:

Object invoke(Object proxy, Method method, Object[] args)

Obviously, there is some handler in the implementation of JAX-WS that does this converting. It would be very handy if I could add handlers below that point.

I understand that this is not supported in the current specification, but I think it should be, without using Spring or so.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
tarasp
Offline
Joined: 2006-12-22
Points: 0

In JAX-WS RI 2.1 the following "hack" should work.
First define an annotation and annotate your service with it:

@Target(ElementType.TYPE)
@InstanceResolverAnnotation(MyInstanceResolver.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyService {
}

Then create a custom resolver that will create an instance for each request.

public class MyInstanceResolver extends AbstractMultiInstanceResolver {

public MyInstanceResolver(Class clazz) {
super(clazz);
}

public Object doInvoke(Packet p, Method m, Object... args)
throws InvocationTargetException, IllegalAccessException {
T instance = create();
prepare(instance);
try {
return m.invoke(instance, args);
}
finally {
dispose(instance);
}
}

public T resolve(Packet request) {
throw new UnsupportedOperationException();
}

public Invoker createInvoker() {
return new MyInstanceResolver.MyInvoker(super.createInvoker());
}

private class MyInvoker extends Invoker {

private final Invoker delegate;

public MyInvoker(Invoker delegate) {
this.delegate = delegate;
}

public void start(WSWebServiceContext wsc, WSEndpoint endpoint) {
delegate.start(wsc, endpoint);
}

public void start(WebServiceContext wsc) {
delegate.start(wsc);
}

public void dispose() {
delegate.dispose();
}

public Object invoke(Packet p, Method m, Object... args)
throws InvocationTargetException, IllegalAccessException {
return doInvoke(p, m, args);
}

public T invokeProvider(Packet p, T arg)
throws IllegalAccessException, InvocationTargetException {
return super.invokeProvider(p, arg);
}

public void invokeAsyncProvider(Packet p, T arg, AsyncProviderCallback cbak,
WebServiceContext ctxt)
throws IllegalAccessException, InvocationTargetException {
super.invokeAsyncProvider(p, arg, cbak, ctxt);
}

}

}

kohsuke
Offline
Joined: 2003-06-09
Points: 0

Yes, exactly!

tarasp, would you be interested in generalizing this a bit and host it to http://jax-ws-commons.dev.java.net/ ? I think this would be quite useful.

tarasp
Offline
Joined: 2006-12-22
Points: 0

It's so simple, why not add it to JAX-WS RI? :)

The following code must be in com.sun.xml.ws.server because AbstractInstanceResolver is package-private.

public class MethodInvoker {
public Object invoke(Method method, Object instance, Object[] args)
throws IllegalAccessException, InvocationTargetException {
return method.invoke(instance, args);
}
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@InstanceResolverAnnotation(InterceptedInstanceResolver.class)
public @interface Intercepted {
Class methodInvoker() default MethodInvoker.class;
}

public class InterceptedInstanceResolver extends AbstractInstanceResolver {

private final T singleton;
private final MethodInvoker methodInvoker;

public InterceptedInstanceResolver(Class clazz) {
singleton = createNewInstance(clazz);
methodInvoker = createNewInstance(clazz.getAnnotation(Intercepted.class).methodInvoker());
}

public T resolve(Packet request) {
return singleton;
}

public void start(WSWebServiceContext wsc, WSEndpoint endpoint) {
getResourceInjector(endpoint).inject(wsc, singleton);
invokeMethod(findAnnotatedMethod(singleton.getClass(), PostConstruct.class), singleton);
}

public void dispose() {
invokeMethod(findAnnotatedMethod(singleton.getClass(), PreDestroy.class), singleton);
}

public Invoker createInvoker() {
return new Invoker() {
public void start(WSWebServiceContext wsc, WSEndpoint endpoint) {
InterceptedInstanceResolver.this.start(wsc, endpoint);
}

public void dispose() {
InterceptedInstanceResolver.this.dispose();
}

public Object invoke(Packet p, Method m, Object... args)
throws InvocationTargetException, IllegalAccessException {
return methodInvoker.invoke(m, resolve(p), args);
}
};
}

}

kohsuke
Offline
Joined: 2003-06-09
Points: 0

There are various reasons why this is better in jax-ws-commons. Things in the JAX-WS RI has higher compatibility commitment requirements, some legal due diligence etc, etc.

So I still think it would be great if you can host this on jax-ws-commons. I'd be very happy to give you a developer access. I can do it for you if you are busy, but I prefer the original developer of the code to own the code, so that he can respond to questions/RFEs from other folks.

tarasp
Offline
Joined: 2006-12-22
Points: 0

Unfortunately I don't have enough time, sorry.

BTW, I think AbstractInstanceResolver would be more useful if it was public. For instance, the proposed InterceptedInstanceResolver could be defined in any package.
And if you put the proposed MethodInvoker into RI than existing Stateful and HttpSessionScope annotations could be rewritten to use it as well, since they cannot be used in conjunction with the proposed Intercepted annotation.

Thanks,
Taras

kohsuke
Offline
Joined: 2003-06-09
Points: 0

OK. I understand. Let me know when you change your mind or get more time.

Yeah, maybe we should make that class public.

rebeccas
Offline
Joined: 2005-09-06
Points: 0

That would be "request" not require".

rebeccas
Offline
Joined: 2005-09-06
Points: 0

Please file an enhancement require in issue tracker.

How about coding the enhancement you want as well.
Provide the src as an attachment in the enhancement
require.

andreou
Offline
Joined: 2005-12-21
Points: 0

https://jax-ws.dev.java.net/issues/show_bug.cgi?id=205

I don't have much time, so this could be more clean, but anyway, I filed one (vote anyone? :-)). I don't have the time to search the code of JAX-WS to find this functionality either, and implement the proposal there. But I'm sure that it would be quite easy for the maintainer of the framework.

dumpshock111
Offline
Joined: 2006-11-17
Points: 0

+1 on this one.

I already asked for something similar just yesterday!

andreou
Offline
Joined: 2005-12-21
Points: 0

Two are a crowd! Someone will surely look into it now :-)