Spring 和 CXF 同时为一个端点公开 Rest 和 Soap
Expose Rest and Soap for one endpoint simultaneously by Spring and CXF
我有一个非常简单的服务,必须以两种方式公开:REST 和 SOAP
我写了以下代码:
@WebService(name = "Base")
@Path("/Base")
@Produces("application/json")
public class BaseService
{
@POST
@Path("/Hello")
public String sayHello()
{
return "Hello";
}
}
那是我的端点,我将其配置如下:
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
@Configuration
public class CxfConfiguration {
@Bean( destroyMethod = "shutdown" )
public SpringBus cxf() {
return new SpringBus();
}
@Bean @DependsOn( "cxf" )
public Server getServer()
{
JaxWsServerFactoryBean wsFactory = new JaxWsServerFactoryBean();
wsFactory.setServiceBean(getBaseService());
return wsFactory.create();
}
@Bean(name = "RestWS") @DependsOn( "cxf" )
public Server getServerRest()
{
JAXRSServerFactoryBean restFactory = new JAXRSServerFactoryBean();
ArrayList<Object> objectArrayList = new ArrayList<>();
restFactory.setServiceBean(getBaseService());
restFactory.setProvider(new JacksonJsonProvider());
return restFactory.create();
}
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("facade.xml");
@Bean
public BaseService getBaseService()
{
return (BaseService)applicationContext.getBean("base_service");
}
}
最后 facade.xml
是:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="base_service" class="BaseService"/>
</beans>
当我 运行 我的应用程序时,我得到 NullPointerException
:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'RestWS' defined in CxfConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.cxf.endpoint.Server]: Factory method 'getServerRest' threw exception; nested exception is org.apache.cxf.service.factory.ServiceConstructionException
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:583)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1249)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1098)
最重要的是,我想同时使用这两种形式的服务,但我遇到了上述异常。当我评论 getServer
或 getServerRest
方法之一时,一切都会好的。
当您想在 SOAP 和 REST 标准中表示服务时,您必须为 REST 和 SOAP 的端点。
对于您的问题,您必须通过以下代码更改CxfConfiguration
class:
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
@Configuration
public class CxfConfiguration
{
@Autowired
private ApplicationContext applicationContext;
@Bean( destroyMethod = "shutdown" )
public SpringBus cxf() {
return new SpringBus();
}
@Bean(name = "RestWS")
public Server getServerRest()
{
JAXRSServerFactoryBean restFactory = new JAXRSServerFactoryBean();
ArrayList<Object> objectArrayList = new ArrayList<>();
restFactory.setServiceBean(getBaseService());
restFactory.setProvider(new JacksonJsonProvider());
return restFactory.create();
}
@Bean
public Server getServer()
{
Bus bus = (Bus) applicationContext.getBean(Bus.DEFAULT_BUS_ID);
Object implementor = getBaseService();
EndpointImpl endpoint = new EndpointImpl(bus, implementor);
endpoint.publish("/Base");
return endpoint ;
}
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("facade.xml");
@Bean
public BaseService getBaseService()
{
return (BaseService)applicationContext.getBean("base_service");
}
}
这可以解决您的问题,但我相信您最好为每个 REST 和 SOAP 服务设置不同的路径或地址。
我有一个非常简单的服务,必须以两种方式公开:REST 和 SOAP 我写了以下代码:
@WebService(name = "Base")
@Path("/Base")
@Produces("application/json")
public class BaseService
{
@POST
@Path("/Hello")
public String sayHello()
{
return "Hello";
}
}
那是我的端点,我将其配置如下:
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
@Configuration
public class CxfConfiguration {
@Bean( destroyMethod = "shutdown" )
public SpringBus cxf() {
return new SpringBus();
}
@Bean @DependsOn( "cxf" )
public Server getServer()
{
JaxWsServerFactoryBean wsFactory = new JaxWsServerFactoryBean();
wsFactory.setServiceBean(getBaseService());
return wsFactory.create();
}
@Bean(name = "RestWS") @DependsOn( "cxf" )
public Server getServerRest()
{
JAXRSServerFactoryBean restFactory = new JAXRSServerFactoryBean();
ArrayList<Object> objectArrayList = new ArrayList<>();
restFactory.setServiceBean(getBaseService());
restFactory.setProvider(new JacksonJsonProvider());
return restFactory.create();
}
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("facade.xml");
@Bean
public BaseService getBaseService()
{
return (BaseService)applicationContext.getBean("base_service");
}
}
最后 facade.xml
是:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="base_service" class="BaseService"/>
</beans>
当我 运行 我的应用程序时,我得到 NullPointerException
:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'RestWS' defined in CxfConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.cxf.endpoint.Server]: Factory method 'getServerRest' threw exception; nested exception is org.apache.cxf.service.factory.ServiceConstructionException
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:583)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1249)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1098)
最重要的是,我想同时使用这两种形式的服务,但我遇到了上述异常。当我评论 getServer
或 getServerRest
方法之一时,一切都会好的。
当您想在 SOAP 和 REST 标准中表示服务时,您必须为 REST 和 SOAP 的端点。
对于您的问题,您必须通过以下代码更改CxfConfiguration
class:
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
@Configuration
public class CxfConfiguration
{
@Autowired
private ApplicationContext applicationContext;
@Bean( destroyMethod = "shutdown" )
public SpringBus cxf() {
return new SpringBus();
}
@Bean(name = "RestWS")
public Server getServerRest()
{
JAXRSServerFactoryBean restFactory = new JAXRSServerFactoryBean();
ArrayList<Object> objectArrayList = new ArrayList<>();
restFactory.setServiceBean(getBaseService());
restFactory.setProvider(new JacksonJsonProvider());
return restFactory.create();
}
@Bean
public Server getServer()
{
Bus bus = (Bus) applicationContext.getBean(Bus.DEFAULT_BUS_ID);
Object implementor = getBaseService();
EndpointImpl endpoint = new EndpointImpl(bus, implementor);
endpoint.publish("/Base");
return endpoint ;
}
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("facade.xml");
@Bean
public BaseService getBaseService()
{
return (BaseService)applicationContext.getBean("base_service");
}
}
这可以解决您的问题,但我相信您最好为每个 REST 和 SOAP 服务设置不同的路径或地址。