Spring Boot将JAX-WS Web服务注册为Bean [英] Spring Boot register JAX-WS webservice as bean
问题描述
在基于spring boot ws的应用程序中,我遵循合同优先方法创建了jax-ws Web服务. Web服务已启动,但是我无法在我的Web服务中自动连接其他bean.
In my spring boot ws based application I have created a jax-ws webservice following a contract first approach. The Web service is up but I cannot autowire my other beans inside my webservice.
我如何在春季将我的Web服务定义为bean?
How can I define, my webservice in spring as bean?
以下是我的网络服务隐含类
Following is my webservice impl class
@WebService(endpointInterface = "com.foo.bar.MyServicePortType")
@Service
public class MySoapService implements MyServicePortType {
@Autowired
private MyBean obj;
public Res method(final Req request) {
System.out.println("\n\n\nCALLING.......\n\n" + obj.toString()); //obj is null here
return new Res();
}
}
MyServicePortType由maven从wsdl文件生成
MyServicePortType is geneated by maven from wsdl file
当我通过SoapUi调用此服务时,由于MyBean对象未自动装配,它会给出NullPointerException.
When I call this service (via SoapUi) it gives NullPointerException as the MyBean object is not autowired.
由于我的应用程序是基于Spring Boot构建的,因此没有xml文件.目前,我有具有端点配置的sun-jaxws.xml
文件.如何在Spring Boot应用程序中进行以下配置
Since my application is built on Spring boot, there is no xml file. Currently I have sun-jaxws.xml
file with endpoint configuration. How can I do following configuration in spring boot application
<wss:binding url="/hello">
<wss:service>
<ws:service bean="#helloWs"/>
</wss:service>
</wss:binding>
以下是我的SpringBootServletInitializer类
Following is my SpringBootServletInitializer class
@Configuration
public class WebXml extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(WSApplication.class);
}
@Bean
public ServletRegistrationBean jaxws() {
final ServletRegistrationBean jaxws = new ServletRegistrationBean(new WSServlet(), "/jaxws");
return jaxws;
}
@Override
public void onStartup(final ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addListener(new WSServletContextListener());
}
}
谢谢
推荐答案
扩展SpringBeanAutowiringSupport
是从当前Spring根Web应用程序上下文中获取为JAX-WS端点类注入的bean的推荐方法.但这不适用于 spring boot ,因为在
Extending SpringBeanAutowiringSupport
is the recommended way to get beans injected for JAX-WS endpoint class, from current spring root web application context. However this does not work with spring boot as it's a bit different on servlet context initialization.
SpringBootServletInitializer.startup()
使用自定义的ContextLoaderListener
,并且不会将创建的应用程序上下文传递给ContextLoader
.稍后,当初始化JAX-WS终结点类的对象时,SpringBeanAutowiringSupport
依赖ContextLoader
来检索当前应用程序上下文,并始终获取null
.
SpringBootServletInitializer.startup()
uses a custom ContextLoaderListener
and does not pass the created application context to ContextLoader
. Later when the object of JAX-WS endpoint class being initialized, SpringBeanAutowiringSupport
depends on ContextLoader
to retrieve the current application context, and always get null
.
public abstract class SpringBootServletInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext rootAppContext = createRootApplicationContext(
servletContext);
if (rootAppContext != null) {
servletContext.addListener(new ContextLoaderListener(rootAppContext) {
@Override
public void contextInitialized(ServletContextEvent event) {
// no-op because the application context is already initialized
}
});
}
......
}
}
解决方法
您可以注册一个实现org.springframework.boot.context.embedded.ServletContextInitializer
的bean,以在startup()
期间检索应用程序上下文.
Workaround
You could register a bean that implements org.springframework.boot.context.embedded.ServletContextInitializer
to retrieve the application context during startup()
.
@Configuration
public class WebApplicationContextLocator implements ServletContextInitializer {
private static WebApplicationContext webApplicationContext;
public static WebApplicationContext getCurrentWebApplicationContext() {
return webApplicationContext;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
}
}
然后,您可以在JAX-WS终结点类中实现自动装配.
Then you could implement self-autowiring in your JAX-WS endpoint class.
@WebService
public class ServiceImpl implements ServicePortType {
@Autowired
private FooBean bean;
public ServiceImpl() {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
WebApplicationContext currentContext = WebApplicationContextLocator.getCurrentWebApplicationContext();
bpp.setBeanFactory(currentContext.getAutowireCapableBeanFactory());
bpp.processInjection(this);
}
// alternative constructor to facilitate unit testing.
protected ServiceImpl(ApplicationContext context) {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(new DefaultListableBeanFactory(context));
bpp.processInjection(this);
}
}
单元测试
在单元测试中,您可以注入当前的spring应用程序上下文,并使用它调用替代构造函数.
Unit Testing
In unit tests you could get current spring application context injected, and call alternative constructor with it.
@Autowired
private ApplicationContext context;
private ServicePortType service;
@Before
public void setup() {
this.service = new ServiceImpl(this.context);
}
这篇关于Spring Boot将JAX-WS Web服务注册为Bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!