Proxies und Annotationen

TheMagican

Grünschnabel
Nabend allerseits,

ich bin gerade dabei mehrere WebServices (SOAP) zu schreiben. Da das ganze möglichst flexibel sein soll hab ich die WebServices als einzelne Projekte angelegt, die zur Laufzeit erst eingebunden werden.

Ich möchte jetzt für jeden WebService, für jeden Methodenaufruf etwas mit-loggen und bin dabei auf java.lang.reflect.Proxy gestoßen. Die Klasse wäre super geeignet für mich, da ich ja eine zentrale Anlaufstelle für alle Methodenaufrufe hätte. Das Problem mit dem Proxy ergib sich jetzt daraus, dass ich ja die zur Laufzeit erstellte Proxy-Klasse verwenden muss um den Endpoint zu publizieren. Leider braucht der Endpoint aber die Annotationen der WebService-Klasse um den Namensraum und den Service-Namen festzulegen. Der erstellte Proxy übernimmt aber leider diese Annotationen nicht.

Weiß jemand, wie man der Proxy-Klasse beibringt, die Annotationen des Objekts, das "hinter" dem Proxy liegt, zu übernehmen? Eine Lösung, wie man zur Laufzeit Annotationen hinzufügt / ändert, wäre auch ok...


Danke im Voraus!
Andi
 
Hallo,

welches Webservice Framework verwendest du denn? Je nachdem stellt das Framework bereits entsprechende interception Möglichkeiten bereit.

Ansonsten müsstest du einfach mal ein kleines Beispiel machen.

Gruß Tom
 
Ich verwende Apache CXF. Hauptsächlich gehts mir um die @WebService(...) Annotation, die ja an jeder Klasse dran sein muss / sollte, die man über einen Endpoint publizieren möchte.
Ich hoffe das hilft? :)

Grüße
Andi
 
Hallo,

warum wrappest du nicht den Service Proxy wieder in einem Proxy?

Schau mal hier:
http://www.tutorials.de/forum/java/268800-einfache-webservices-unter-java-6-mustang.html

Java:
package de.tutorials;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Endpoint;
import javax.xml.ws.Service;

/**
 * @author Tom
 */
public class SimpleWebServiceExample {
    public static void main(String[] args) throws Exception {
        Endpoint endpoint = null;
        try {
            endpoint = Endpoint.publish("http://localhost:44444/Calculator", new Calculator());
            System.out.println("Service Published!");
            Service service = Service.create(new URL("http://localhost:44444/Calculator?wsdl"), new QName("http://tutorials.de/", "Calculator"));
            ICalculator simpleService = service.getPort(ICalculator.class);

            ICalculator simpleServiceProxy = (ICalculator) Proxy.newProxyInstance(
                                                                                    Thread.currentThread().getContextClassLoader()
                                                                                   ,new Class[] { ICalculator.class }
                                                                                   ,createTracingInvocationHandler(simpleService));

            System.out.println(simpleServiceProxy.computeSumOf(11, 12));
        } finally {
            endpoint.stop();
        }
    }

    private static InvocationHandler createTracingInvocationHandler(
            final Object target) {
        return new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                System.out
                        .println("About to call: " + method + " on " + target);
                return method.invoke(target, args);
            }
        };
    }
}

Ausgabe:
Code:
Service Published!
About to call: public abstract int de.tutorials.Calculator.computeSumOf(int,int) on JAX-WS RI 2.1.1: Stub for http://localhost:44444/Calculator
23

Bei den meisten Webservice Frameworks kann man Interceptoren bzw. Handler hinterlegen die es erlauben in das intere Call-Processing eingreifen zu können.

So auch CXF:
http://cwiki.apache.org/CXF20DOC/interceptors.html

Ansonsten könntest du auch per AspectJ einen execution Pointcut definieren und in einem damit verbundenen Advice dort dann die trace-operationen durchführen.

Gruß Tom
 
Hi,

danke für die guten Vorschläge. Bei dem Code-Beispiel ist es nur leider so, dass der WS-Client einen Proxy benutzt, ich bräuchte den aber auf Serverseite; soll heißen: egal welcher Client anfragt wird immer auf Serverseite ein Log-Eintrag gemacht.

Die Interceptions waren ein sehr guter Tipp (wieder ein Begriff mehr gelernt ;) ). Ich hab mir die verlinkte Seite dazu angesehen und mal testweise eingebaut. Leider bekomme ich bei den Interceptions aber nur ein Message-Objekt und das enthält leider nicht die Parameter, mit der eine Methode aufgerufen worden ist. Ansonsten ist das ne echt coole Sache und wäre perfekt geeignet gewesen.

Hat jemand vielleicht noch ne andere Idee, wie ich ich mein Problem lösen könnte?


Grüße
Andi
 
Zurück