2013-07-15 13 views
5

Czy ktoś wie, jak to skonfigurować, aby usługa SOAP i usługa REST mogły współużytkować ten sam port za pomocą usługi Jersey (Grizzly) poza serwerem aplikacji?Jak hostować usługę SOAP i usługę REST w tym samym porcie?

  • Moje usługi mydło jest w www.someurl.com:port/soap/crm
  • Moje usługi reszta jest w www.someurl.com:port/crm

Usługi te mają te same port, ale nie ten sam adres bazowy i dlatego powinien być w stanie działać obok siebie na tym porcie. Istnieje jednak błąd powiązania portu.

Wszystko to w niestandardowej aplikacji usługowej i nie ma pliku web.xml lub innego.

Usługa REST korzysta z usługi Jersey, a usługa Soap jest klasą "Usługa odbioru" opublikowaną w punkcie końcowym.

URI soapUri = URI.create("192.168.0.0:1234\soap\Crm") 
URI restUri = URI.create("192.168.0.0:1234\crm") 

// START SOAP SERVICE 
Object reception = getObjectResource(ReceptionService.class); 
Endpoint e = Endpoint.publish(soapUri, reception); 

// START REST SERVICE  
ResourceConfig rc = new ResourceConfig().packages("company.rest"); 
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(restUri, rc); 

Kiedy próbuję to, Grizzly wypluwa 'java.net.BindException: Address already in use bind'

Mój odbiór serwis mydło jest ustawiony tak:

@WebService(targetNamespace = "company.crm") 
    @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL,  parameterStyle = SOAPBinding.ParameterStyle.WRAPPED) 
    public class Reception implements ReceptionService { 
    ... methods 
    } 

My klasy usług reszta są opatrzone jak zwykle jak ...

@Path("hello/{username}") 
public class Hello { ... } 

Jestem trochę newbie w tym a i jakiekolwiek wskazówki byłyby doceniane. I proszę, nie przejmuj się sugerowaniem uruchamiania serwera aplikacji. To nie jest problem - problem polega na tym, jak obejść problem związany z portem bez przechodzenia do innej struktury usług sieciowych?

UWAGA RE BOUNTY. NIE MOGĘ iteracyjne to wystarczy

„Zwycięzca nagród pokaże, jak korzystać z Jersey do odpoczynku i usługi SOAP Java (adnotacją JAX-WS) razem na tym samym punkcie końcowym odpowiedź będzie nie wymaga zmian w klasach adnotowanych Odpoczynku i Mydła, jednak zmiany kodu serwera HTTP lub zmiany konfiguracji w celu jego działania są dopuszczalne. Przełączenie na Jetty lub inny serwer aplikacji jest nie do przyjęcia Rozwiązanie musi być w 100% osadzone i uruchomione przy użyciu Java SE i biblioteki serwisów Java. "

+0

Przydałoby się trochę więcej informacji, np. jakiego typu serwera internetowego/serwera aplikacji używasz? Jak wygląda "web.xml"? –

+0

znalazłeś rozwiązanie? Mam do czynienia z tym samym problemem –

+0

Nie. Nadal trzymam je w osobnych portach. Musiałbym dużo przerobić mój kod i nie mam czasu ani cierpliwości. Mając nadzieję, że będzie to konfigurowalne w przyszłości. –

Odpowiedz

1

Jeśli używasz wspólnego kontenera, takiego jak tomcat, do swoich usług sieciowych, możesz otrzymywać żądania dotyczące obu usług przybywających do tego samego portu. Możesz wdrożyć usługi oparte na REST i SOAP jako część aplikacji. Kontener zaakceptuje przychodzące żądanie i przekaże je do aplikacji w zależności od kontekstu aplikacji. W aplikacji web.xml możesz skonfigurować miejsce wysyłania żądania w zależności od mapowania adresu URL żądania.

+0

Dzięki. Używam oprogramowania Jersey (spoza programu Glassfish) w aplikacji serwera klienta. Postawię więcej informacji powyżej i być może ktoś ma rozwiązanie. –

2

To, co mówisz, to nic innego jak dwa różne interfejsy do eksponowania usług i tak, możesz je hostować na jednym porcie, a następnie wdrożyć je w tym samym kontenerze, a będziesz mieć oba interfejsy w stanie gotowości.

Tylko upewnij się, że nie masz konfliktu ścieżki kontekstowej, co wydaje się nie występować w adresach URL wymienionych w powyższym pytaniu.

np. Niech interfejs reszty zostanie wdrożony jako:

www.someurl.com: port2/crm, więc nie powinno się instalować mydła w tym samym adresie URL, www.someurl.com:port1/soap/crm, co jest w porządku.

Powinieneś również nieco wyjaśnić, w jaki sposób wdrażasz interfejsy, jako oddzielne pliki wojny lub w jednym pliku wojny.

+0

Dzięki. Ale muszę im udostępnić ten sam port URL. Bez plików wojennych, bez serwera aplikacji, tylko kodowane jak wyżej. Działa dobrze, na oddzielnych portach, ale powoduje wyjątek wiązania podczas współużytkowania tego samego portu (chociaż punkt końcowy jest rzeczywiście inny). –

+0

Problem polega na tym, Endpoint.publish uruchomi się, a serwer HTTP i część Grizzly również uruchomi HTTP Serwer z tego powodu zderza się port. –

+0

Więc jak mogę sprawić, by Grizzly dostarczył usługę mydła? TO ZNACZY. Opublikuj usługę odbioru dokładnie obok siebie? Musi być jakiś sposób, ponieważ zarówno serwer Microsoft Server, jak i serwer Apache CMX zezwalają na to samo zachowanie. –

1

Nie można uruchomić więcej niż jednej usługi na tym samym porcie.

Jeśli chcesz, aby Twoja aplikacja była dostępna przez ten sam port, musisz użyć serwera Aplikacji .

Musisz zadbać, aby obie aplikacje na serwerze były dostępne z różnymi adresami URL (web.xml).

Wszystkie aplikacje na tym samym serwerze aplikacji są teraz dostępne przez ten sam port.

+0

Jeśli można to zrobić za pomocą serwera aplikacji, można to zrobić programowo bez niego. Jak więc Glassfish hostuje na tym samym porcie, używając jersey'a (grizzly http) jako serwera reszty i usługi mydła ... to jest pytanie za milion dolarów :) –

4

Nakładka Jetty pozwala na rozmieszczenie dwóch różnych aplikacji webowych o różnych ścieżkach na tej samej instancji/porcie Jetty.

Będziesz mieć jeden plik web.xml z serwletem Jersey (dla usługi REST) ​​i innym plikiem web.xml z serwletem SOAP.

http://www.eclipse.org/jetty/documentation/current/overlay-deployer.html

+0

OK. To może zadziałać, jeśli przeniesię to wszystko na Jetty. A ponieważ teraz korzystam z Jetty dla Restful Side of Things, ponieważ podoba mi się sposób, w jaki łatwo konfiguruje się z Guice, to może Soap też może pójść tą drogą. –

+0

Ale to musi być rozwiązanie, które nie obejmuje plików web.xml.Jeśli możesz pokazać, jak to zrobić z Jetty i bez plików xml, wtedy rozważę właściwą odpowiedź. –

0

to większość kodu używam do organizacji zarówno usługi odpoczynek i mydła na jednym porcie (2 różne ścieżki kontekstu), całkowicie osadzony w mojej aplikacji (za pomocą Grizzly oczywiście), a wiosną skonfigurowany. ..

package com.mycompany.structure.web.grizzly; 

import java.io.IOException; 
import java.lang.reflect.Constructor; 
import java.net.BindException; 
import java.util.EnumSet; 
import java.util.LinkedList; 
import javax.servlet.DispatcherType; 
import javax.servlet.Servlet; 
import com.mycompany.structure.web.jersey.jackson.JsonResourceConfig; 
import com.mycompany.structure.web.jersey.spring.ExposedApplicationContext; 
import org.glassfish.grizzly.http.server.HttpHandler; 
import org.glassfish.grizzly.http.server.HttpServer; 
import org.glassfish.grizzly.http.server.NetworkListener; 
import org.glassfish.grizzly.jaxws.JaxwsHandler; 
import org.glassfish.grizzly.servlet.WebappContext; 
import org.glassfish.jersey.servlet.ServletContainer; 
import org.smallmind.nutsnbolts.lang.web.PerApplicationContextFilter; 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.DisposableBean; 
import org.springframework.beans.factory.config.BeanPostProcessor; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.ApplicationContextAware; 
import org.springframework.context.ApplicationEvent; 
import org.springframework.context.ApplicationListener; 
import org.springframework.context.event.ContextRefreshedEvent; 

public class GrizzlyInitializingBean implements DisposableBean, ApplicationContextAware, ApplicationListener, BeanPostProcessor { 

    private static final Class[] NO_ARG_SIGNATURE = new Class[0]; 
    private HttpServer httpServer; 
    private LinkedList<WebService> serviceList = new LinkedList<>(); 
    private ServletInstaller[] servletInstallers; 
    private String host; 
    private String contextPath; 
    private String restPath; 
    private String soapPath; 
    private int port; 
    private boolean debug = false; 

    public void setHost (String host) { 

    this.host = host; 
    } 

    public void setPort (int port) { 

    this.port = port; 
    } 

    public void setContextPath (String contextPath) { 

    this.contextPath = contextPath; 
    } 

    public void setRestPath (String restPath) { 

    this.restPath = restPath; 
    } 

    public void setSoapPath (String soapPath) { 

    this.soapPath = soapPath; 
    } 

    public void setServletInstallers (ServletInstaller[] servletInstallers) { 

    this.servletInstallers = servletInstallers; 
    } 

    public void setDebug (boolean debug) { 

    this.debug = debug; 
    } 

    @Override 
    public synchronized void onApplicationEvent (ApplicationEvent event) { 

    if (event instanceof ContextRefreshedEvent) { 

     if (debug) { 
     System.setProperty("com.sun.xml.ws.transport.http.HttpAdapter.dump", "true"); 
     } 
     httpServer = new HttpServer(); 
     httpServer.addListener(new NetworkListener("grizzly2", host, port)); 

     WebappContext webappContext = new WebappContext("Grizzly Application Context"); 
     webappContext.addServlet("JAX-RS Application", new ServletContainer(new JsonResourceConfig(ExposedApplicationContext.getApplicationContext()))).addMapping(restPath + "/*"); 
     webappContext.addFilter("per-application-data", new PerApplicationContextFilter()).addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), restPath + "/*"); 
     webappContext.addListener("org.springframework.web.context.request.RequestContextListener"); 

     for (ServletInstaller servletInstaller : servletInstallers) { 
     try { 

      Constructor<? extends Servlet> servletConstructor; 
      Servlet servlet; 
      String urlPattern; 

      servletConstructor = servletInstaller.getServletClass().getConstructor(NO_ARG_SIGNATURE); 
      servlet = servletConstructor.newInstance(); 

      webappContext.addServlet(servletInstaller.getDisplayName(), servlet).addMapping((urlPattern = servletInstaller.getUrlPattern()) == null ? "/" : urlPattern); 
     } 
     catch (Exception exception) { 
      throw new GrizzlyInitializationException(exception); 
     } 
     } 

     webappContext.deploy(httpServer); 

     for (WebService webService : serviceList) { 

     HttpHandler httpHandler = new JaxwsHandler(webService.getService(), false); 

     httpServer.getServerConfiguration().addHttpHandler(httpHandler, soapPath + webService.getPath()); 
     } 

     try { 
     httpServer.start(); 
     } 
     catch (IOException ioException) { 
     if (!(ioException instanceof BindException)) { 
      throw new GrizzlyInitializationException(ioException); 
     } 
     } 
    } 
    } 

    @Override 
    public void setApplicationContext (ApplicationContext applicationContext) { 

    ExposedApplicationContext.register(applicationContext); 
    } 

    @Override 
    public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { 

    return bean; 
    } 

    @Override 
    public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { 

    ServicePath servicePath; 

    if ((servicePath = bean.getClass().getAnnotation(ServicePath.class)) != null) { 
     serviceList.add(new WebService(servicePath.value(), bean)); 
    } 

    return bean; 
    } 

    @Override 
    public synchronized void destroy() { 

    if (httpServer != null) { 
     httpServer.shutdown(); 
    } 
    } 
} 
+0

Awesome. Przyjrzę się temu. –

Powiązane problemy