Spring Boot将JAX-WS Web服务注册为Bean [英] Spring Boot register JAX-WS webservice as bean

查看:427
本文介绍了Spring Boot将JAX-WS Web服务注册为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆