2016-03-22 53 views
7

Chciałbym opublikować webservice programowo do tomcat.
Z np. JAX-WS lub Apache CXF
Podobny do Endpoint.publish(...).
Jak programowo opublikować webservice do tomcat

//how to tell this tomcat? 
Endpoint.publish("http://0.0.0.0:8080/SimpleService", serviceImpl); 
//or better something like this: 
Endpoint.publish("/SimpleService", serviceImpl); 

Bez konieczności korzystania web.xml i/lub sun-jaxws.xml (dla każdej usługi)

Pytanie:
Czy istnieje dowolny znany sposób tego dokonać (z JAX-WS lub Apache CXF lub. ..)?

(wiem, że istnieją podobne pytania już wysłane. Ale żaden z nich nie odpowiada na moje pytanie.)

+0

Nie jestem pewien Twoich wymagań. Chcesz wdrożyć aplikację na tomcat (więc potrzebujesz web.xml), który programowo opublikuje nowy punkt końcowy, aby odbierać żądania. Czy to jest poprawne? – pedrofb

+0

Aplikacja webowa menedżera Tomcat może zostać wykorzystana do wdrożenia nowej aplikacji internetowej (przez wywołanie odpowiedniego adresu URL) (https://tomcat.apache.org/tomcat-6.0-doc/manager-howto.html#Deploy_A_New_Application_from_a_Local_Path) – Maxx

Odpowiedz

1

To anwer do mojego pytania.
Udało mi się to zrobić [programowo opublikować serwis internetowy do tomcat] za pomocą Apache CXF.

Oto uproszczony przykład praca:

I podklasy do CXFNonSpringServlet i zarejestrował go w web.xml:

<servlet> 
<servlet-name>MyCXFServlet</servlet-name> 
<display-name>CXF Servlet</display-name> 
<servlet-class>de.test.MyCXFServlet</servlet-class> 
<load-on-startup>2</load-on-startup> 
<async-supported>true</async-supported> 
</servlet> 

<servlet-mapping> 
<servlet-name>MyCXFServlet</servlet-name> 
<url-pattern>/soap/*</url-pattern> 
</servlet-mapping> 

To jest mój podklasy CXFNonSpringServlet:

import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 
import java.util.HashSet; 
import java.util.Set; 
import javax.jws.WebMethod; 
import javax.servlet.ServletConfig; 
import org.apache.cxf.endpoint.Server; 
import org.apache.cxf.frontend.ServerFactoryBean; 
import org.apache.cxf.service.factory.ReflectionServiceFactoryBean; 
import org.apache.cxf.transport.servlet.CXFNonSpringServlet; 

public class MyCXFServlet extends CXFNonSpringServlet 
{ 
    @Override 
    protected void loadBus(ServletConfig sc) 
    { 
     super.loadBus(sc); 
     publishServices(); 
    } 

    private void publishServices() 
    { 
     Set<Class> serviceInterfaces = new HashSet<>(); 
     serviceInterfaces.add(de.test.IUserService.class); 
     serviceInterfaces.add(de.test.ILoginService.class); 

     for (Class aSVCInterface : serviceInterfaces) 
     { 
      final String serviceName = aSVCInterface.getSimpleName(); 

      try 
      { 
       ReflectionServiceFactoryBean reflectionFactory = new ReflectionServiceFactoryBean(){ 
        @Override 
        protected boolean isValidMethod(Method method) 
        { 
         boolean ret = super.isValidMethod(method); 
         WebMethod wm = method.getAnnotation(WebMethod.class); 
         if (wm != null && wm.exclude()) 
          ret = false; 
         return ret; 
        } 

        @Override 
        protected String getServiceName() //Override for custom service name 
        { 
         return serviceName; 
        } 

       }; 
       reflectionFactory.setServiceClass(aSVCInterface); 

       Object proxiedServiceObject = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{aSVCInterface}, new de.test.MyWebServiceInvocationHandler(aSVCInterface)); 

       ServerFactoryBean factory = new ServerFactoryBean(reflectionFactory); 
       factory.setBus(getBus()); 
       factory.setServiceClass(aSVCInterface); 
       factory.setServiceBean(proxiedServiceObject); 
       factory.setAddress("/" + serviceName); 
       Server svr = factory.create();  
       svr.getEndpoint().getInInterceptors().add(new de.test.MyServiceInterceptor()); 
      } 
      catch (Exception exception) 
      { 
       exception.printStackTrace(); 
      } 
     } 
    } 
} 

Powyższy Servlet będzie opublikuj 2 proste interfejsy jako SOAP-WebService.
Realizacja jest dynamicznie (proxy)

To jest mój MyServiceInterceptor:

import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Proxy; 
import org.apache.cxf.binding.soap.SoapMessage; 
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor; 
import org.apache.cxf.endpoint.Endpoint; 
import org.apache.cxf.interceptor.Fault; 
import org.apache.cxf.message.Exchange; 
import org.apache.cxf.phase.Phase; 
import org.apache.cxf.service.Service; 
import org.apache.cxf.service.invoker.BeanInvoker; 
import org.apache.cxf.service.invoker.Invoker; 

public class MyServiceInterceptor extends AbstractSoapInterceptor 
{ 
    public MyServiceInterceptor() 
    { 
     super(Phase.PRE_INVOKE); 
    } 

    @Override 
    public void handleMessage(SoapMessage p_message) throws Fault 
    { 
     final Exchange exchange = p_message.getExchange(); 
     final Endpoint endpoint = exchange.get(Endpoint.class); 
     final Service service = endpoint.getService(); 
     final Invoker invoker = service.getInvoker(); 

     if (invoker instanceof BeanInvoker) 
     { 
      BeanInvoker bi = (BeanInvoker)invoker; 
      Object serviceObj = bi.getServiceObject(null); 
      if (Proxy.isProxyClass(serviceObj.getClass())) 
      { 
       InvocationHandler ih = Proxy.getInvocationHandler(serviceObj); 
       if (ih instanceof MyWebServiceInvocationHandler) 
       { 
        MyWebServiceInvocationHandler h = (MyWebServiceInvocationHandler)ih; 
        h.setSoapMessage(p_message); 
       } 
      } 
     } 
    } 
} 

MyServiceInterceptor-Class jest używany głównie do wstrzykiwania aktualny SOAPMessage do MyWebServiceInvocationHandler.

Mój MyWebServiceInvocationHandler (Myślę, że kod nie jest potrzebny) jest odpowiedzialny za wywołanie prawdziwej metody serwisowej. Po prostu implementuje InvocationHandler i ma pole do wiadomości Soap (zobacz MyServiceInterceptor). Jest to potrzebne, aby uzyskać szczegóły SOAPMessage (takie jak nagłówek).

Mam nadzieję, że to pomoże.
Pozdrawiam!