java - 如何从 JAX-WS 中的 Spring 方面访问 SOAPMessage?

标签 java web-services spring jax-ws

我有一个使用 Spring 3 IOC 的 JAX-WS WebService。我编写了一个 Spring Aspect 来处理任何异常,并确保在完成调用之前在 WebService 类中正确处理它们。在我的方面,我想访问用户的区域设置(在我的 SOAP header 中定义),但我不确定如何执行此操作。

我知道我可以在处理程序中获取区域设置,但这对我而言没有帮助。我尝试注入(inject) WebServiceContext,但它始终为 null。

稍微挖掘一下,我就找到了 https://issues.apache.org/jira/browse/CXF-2674这似乎表明:

  1. Spring 故意不注入(inject) WebServiceContext 对象
  2. WebServiceContext 是 SOAPMessageContext 的瘦包装器

但是,如果我尝试 Autowiring SOAPMessageContext,也会失败并显示以下错误消息:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.xml.ws.handler.soap.SOAPMessageContext com.cws.cs.lendingsimulationservice.error.ServiceErrorInterceptor.webServiceContext; nested exception is java.lang.IllegalArgumentException: Can not set javax.xml.ws.handler.soap.SOAPMessageContext field com.cws.cs.lendingsimulationservice.error.ServiceErrorInterceptor.webServiceContext to java.util.LinkedHashMap
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502) [spring-beans-3.0.5.RELEASE.jar:]
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84) [spring-beans-3.0.5.RELEASE.jar:]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282) [spring-beans-3.0.5.RELEASE.jar:]
        ... 21 more
Caused by: java.lang.IllegalArgumentException: Can not set javax.xml.ws.handler.soap.SOAPMessageContext field com.cws.cs.lendingsimulationservice.error.ServiceErrorInterceptor.webServiceContext to java.util.LinkedHashMap
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146) [:1.6.0_29]
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150) [:1.6.0_29]
        at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63) [:1.6.0_29]
        at java.lang.reflect.Field.set(Field.java:657) [:1.6.0_29]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:498) [spring-beans-3.0.5.RELEASE.jar:]
        ... 23 more

我认为必须有一种方法可以从某个方面访问此信息,但似乎无法弄清楚如何实现。

如果我尝试注入(inject) SOAPMessage 对象,则会收到 org.springframework.beans.factory.NoSuchBeanDefinitionException: Nomatching bean of type [javax.xml.soap.SOAPMessage]发现依赖项错误消息。

有人能给我指出正确的方向吗?

谢谢

埃里克

最佳答案

我的解决方案使用处理程序和请求范围的对象。希望其他人将来会发现这很有用

处理程序:

public class ServiceContextHandler implements SOAPHandler<SOAPMessageContext>{

    /**
     * Logger
     */
    private static final Logger logger = LoggerFactory.getLogger(ServiceContextHandler.class);

    /**
     * Request object
     */
    @Autowired
    private SOAPHeaderData soapHeaderData;

    /**
     * Ensure that the bean has its parameters injected appropriately
     */
    @PostConstruct
    public void init() {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    /**
     * Nothing to do on end of message
     */
    public void close(MessageContext context) {
    }


    /**
     * Nothing to do for a fault
     */
    public boolean handleFault(SOAPMessageContext context) {
        return true;
    }

    /**
     * Process the message
     */
    public boolean handleMessage(SOAPMessageContext context) {
        // no need to bother with outbound requests
        if( !((Boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue() )
            process(context);
        return true;
    }

    /**
     * Doesn't handle any specific QNames in the header
     */
    public Set<QName> getHeaders() {
        return null;
    }


    /**
     * Extract the header parameters
     * @param context
     */
    @SuppressWarnings("unchecked")
    private void process(SOAPMessageContext context) {
        // Creating the XML tree
        try {
            JAXBContext jc = JAXBContext.newInstance( ObjectFactory.class);
            Object[] headers = context.getHeaders(new ObjectFactory().createServiceContext(null).getName(), jc, true);

            // find the service context element
            for( Object header : headers ){
                if( (header instanceof JAXBElement<?>) && ((JAXBElement<?>)header).getValue() instanceof ServiceContextType){
                    // found the service context element
                    soapHeaderData.setServiceContext(((JAXBElement<ServiceContextType>)header).getValue());
                    break;
                }
            }

        } catch (JAXBException e) {
            logger.error(ExceptionUtils.getStackTrace(e));
        } catch (WebServiceException e) {
            logger.error(ExceptionUtils.getStackTrace(e));
        }
    }
}

SOAPHeaderData 的定义:

<!-- SOAPHeaderData -->
<bean id="soapHeaderData" class="com.cws.cs.lendingsimulationservice.header.SOAPHeaderDataImpl" scope="request">
    <aop:scoped-proxy proxy-target-class="false"/>
</bean>

其中 SOAPHeaderDataImpl 是一个基本的 POJO(具有接口(interface),以便不需要 CGLIB)。

希望这有帮助!如果有任何不清楚的地方,请告诉我。

谢谢

埃里克

关于java - 如何从 JAX-WS 中的 Spring 方面访问 SOAPMessage?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9365630/

相关文章:

java - 未找到当前线程的 session (Spring 3.1.X 和 Hibernate 4)

java - 即使solve() 方法返回 true,IloCplex.solve() 仍无法满足所有约束

java - spring boot oauth2 feign 允许匿名请求

java 。对 Web 服务的 Soap 请求

c# - OData 是公开非 CRUD API 的好方法吗?

java - Spring RESTful 服务作为 WAR 而不是 Tomcat 中的 JAR

java - neo4j找不到java

java - Maven:打包和模块依赖

javascript - 你能从 javascript 使用 ASMX 网络服务吗?

java - Spring Security 尽管有限制但仍允许访问