简体   繁体   English

如何在同一端口托管SOAP服务和REST服务?

[英]How to host a SOAP service and REST service at the same port?

Does anyone know how to configure it so that a SOAP service and REST service can share the same port using Jersey (Grizzly) outside of an application server? 有谁知道如何配置它,以便SOAP服务和REST服务可以在应用程序服务器之外使用Jersey(Grizzly)共享同一个端口?

  • My soap service is at www.someurl.com:port/soap/crm 我的肥皂服务在www.someurl.com:port/soap/crm
  • My rest service is at www.someurl.com:port/crm 我的休息服务是www.someurl.com:port/crm

These services share the same port but not the same base url and therefor should be able to run side by side on that port. 这些服务共享相同的端口但不是相同的基本URL,因此应该能够在该端口上并行运行。 However, there is a port bind error .. 但是,有一个端口绑定错误..

All of this is in a custom service application and there is no web.xml or such. 所有这些都在自定义服务应用程序中,并且没有web.xml等。

The REST service is using Jersey and the Soap service is a class 'ReceptionService' published on an endpoint. REST服务使用Jersey,Soap服务是在端点上发布的类“ReceptionService”。

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);

When I try this, Grizzly spits out 'java.net.BindException: Address already in use: bind' 当我尝试这个时,Grizzly吐出'java.net.BindException:地址已经在使用:bind'

My soap service reception is setup like this: 我的肥皂服务接待设置如下:

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

My rest service classes are annotated as usual like ... 我的休息服务课像往常一样注释......

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

I am a bit of a newbie at this and any pointers would be appreciated. 我在这方面有点新手,任何指针都会受到赞赏。 And please, don't bother suggesting I run an application server. 请不要打扰我建议运行应用程序服务器。 That is not the problem here -- the problem is how do I get around the port-bind issue without moving to some other webservice framework? 这不是问题 - 问题是我如何解决端口绑定问题而不转移到其他一些Web服务框架?

NOTE RE BOUNTY: I CANNOT ITERATE THIS ENOUGH 注意RE BOUNTY:我不能完全忘记这一点

"The bounty winner will demonstrate how to use Jersey for REST and a Java SOAP service (annotated JAX-WS) together on the same endpoint. The answer will not require changes to the Rest and Soap annotated classes. However, and HTTP server code changes or configuration changes to make it work are acceptable. Switching to Jetty or some other application server are not acceptable The solution must be 100% embedded and run using Java SE and Java web service libraries." “赏金获胜者将演示如何在同一端点上一起使用Jersey for REST和Java SOAP服务(带注释的JAX-WS)。 答案不需要更改Rest和Soap带注释的类。但是,HTTP服务器代码更改或接受配置更改以使其正常工作。切换到Jetty或其他应用程序服务器是不可接受的 。解决方案必须100%嵌入并使用Java SE和Java Web服务库运行。“

Jetty's overlay feature allows you to deploy two different webapps with different paths on the same Jetty instance/port. Jetty的覆盖功能允许您在同一个Jetty实例/端口上部署两个具有不同路径的不同Web应用程序。

You would have one web.xml with your Jersey servlet (for REST) and the other web.xml with the SOAP servlet. 您将拥有一个带有Jersey servlet(用于REST)的web.xml和带有SOAP servlet的另一个web.xml。

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

What you are saying is nothing but two different interfaces for exposing services and yes you can host them on a single port just deploy it in the same container and you will be having both the interfaces up and running. 您所说的只是两个不同的接口,用于公开服务,是的,您可以将它们托管在一个端口上,只需将它部署在同一个容器中,您就可以同时启动和运行这两个接口。

Just make sure you don't have a context path conflict, which does not seem to happen in the urls mentioned in the question above. 只是确保您没有上下文路径冲突,这似乎不会出现在上面问题中提到的网址中。

eg Let the rest interface be deployed as: 例如,将其余接口部署为:

www.someurl.com:port2/crm , so soap should not be deployed in the same url, www.someurl.com:port1/soap/crm , which is alright. www.someurl.com:port2/crm,所以肥皂不应该部署在同一个网址上,www.someurl.com:port1 / soap / crm,这没关系。

You should also explain a bit how you are deploying the interfaces, as separate war files or in a single war file. 您还应该解释一下如何部署接口,作为单独的war文件或单个war文件。

It´s not possible to start more than one service on the same port. 无法在同一端口上启动多个服务。

When you want that your App is accessible over the same port, you have to use an Application Server. 如果希望通过同一端口访问应用程序,则必须使用Application Server。

You must take care that both Apps on the Server are accessible with different URL´s (web.xml). 您必须注意服务器上的两个应用程序都可以使用不同的URL(web.xml)访问。

All Applications on the same Application Server are now accessible over the same port. 现在可以通过同一端口访问同一Application Server上的所有应用程序。

If you are using a common container such as tomcat for your webservices, then you can get requests for both of the services arriving on the same port. 如果您使用诸如tomcat之类的公共容器作为Web服务,那么您可以获得对同一端口上的两个服务的请求。 You can deploy both the REST and SOAP based services as part of your application. 您可以将REST和基于SOAP的服务部署为应用程序的一部分。 The container will accept the incoming request and will forward them to the application depending on the application context. 容器将接受传入的请求,并根据应用程序上下文将它们转发到应用程序。 In your application web.xml, you can configure the where to send the request depending on the request URL mapping. 在您的应用程序web.xml中,您可以根据请求URL映射配置发送请求的位置。

This is most of the code I use to host both rest and soap services on a single port (2 different context paths), completely embedded in my app (using Grizzly obviously), and spring configured... 这是我用于在单个端口(2个不同的上下文路径)上托管rest和soap服务的大部分代码,完全嵌入在我的应用程序中(显然使用Grizzly),以及spring配置...

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();
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM