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

发布于 2025-01-07 13:29:18 字数 2737 浏览 3 评论 0原文

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

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

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

  1. Spring 故意不注入 WebServiceContext 对象
  2. WebServiceContext 是 SOAPMessageContext 的薄包装器

但是,如果我尝试自动装配 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

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

如果我尝试注入 SOAPMessage 对象,则会收到 org.springframework.beans.factory.NoSuchBeanDefinitionException: Nomatching bean of type [javax.xml.soap.SOAPMessage] found for dependency错误消息。

有人可以指出我正确的方向吗?

谢谢,

埃里克

I've got a JAX-WS WebService that is using Spring 3 IOC. I have coded a Spring Aspect to handle any exceptions and ensure that they are properly handled in the WebService class prior to completing a call. Within my Aspect, I would like to get access to the user's locale (defined in my SOAP Header), however I am not sure how to do this.

I know I can get the Locale in a handler, but that doesn't help me within my aspect. I tried injecting the WebServiceContext, but that is always null.

A little digging around pointed me to https://issues.apache.org/jira/browse/CXF-2674 which seems to indicate that:

  1. Spring intentionally does not inject a WebServiceContext object
  2. the WebServiceContext is a thin wrapper for the SOAPMessageContext

However, if I try to autowire the SOAPMessageContext instead, that fails as well with the following error message:

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

I figure that there must be a way I can access this information from within an aspect, but cannot seem to figure out how.

If I try to inject a SOAPMessage object instead, I get a org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.xml.soap.SOAPMessage] found for dependency error message.

Can someone point me in the right direction please?

Thanks,

Eric

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小清晰的声音 2025-01-14 13:29:18

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

Handler:

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

Defn of SOAPHeaderData:

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

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

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

谢谢,

埃里克

My solution uses a handler and a request-scoped object. Hopefully someone else might find this useful in the future

Handler:

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

Defn of SOAPHeaderData:

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

where SOAPHeaderDataImpl is a basic POJO (with an interface so as to not need CGLIB).

Hope this helps! If anything is unclear, let me know.

Thanks,

Eric

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文