【问题标题】:'No adapter for endpoint' exception - apache-camel with spring-boot & spring-ws“没有端点适配器”异常 - 带有 spring-boot 和 spring-ws 的 apache-camel
【发布时间】:2015-06-25 10:56:46
【问题描述】:

JVM 1.8.0_45
apache-camel 2.15.2
spring-ws 2.2.1
弹簧启动 1.2.4

我正在尝试在 spring-boot 应用程序中使用 apache-camel (2.15.2) 来处理传入的 Web 服务调用。

我按照http://spring.io/guides/gs/producing-web-service/ 此处的指导方针创建了一个初始工作弹簧启动项目(没有骆驼)

然后我尝试将 Camel: Spring Web Services 组件集成为消费者,以按照此处“公开 Web 服务”部分中的指南处理传入的 Web 服务请求http://camel.apache.org/spring-web-services.html

WebServiceConfig.java

import org.apache.camel.component.spring.ws.bean.CamelEndpointMapping;

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {

    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/ws/*");
    }

    // default wsdl stuff here...

    // exposing the endpoint mapping bean here rather than in spring-ws-servlet.xml (seems to work)
    @Bean  public CamelEndpointMapping  endpointMapping() {
        return new CamelEndpointMapping();
    }
}

ClaimRouter.java

import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.dataformat.JaxbDataFormat;
import org.springframework.stereotype.Component;

@Component
public class ClaimRouter extends RouteBuilder {

    @Override
    public void configure() throws Exception {

        JaxbDataFormat jaxb = new JaxbDataFormat(false);
        jaxb.setContextPath("uk.co.example.claim.ws.v2"); 

        // comment @PayloadRoot annotation in ClaimEndpointV2.java to enable requests to be mapped to this camel route
        from("spring-ws:rootqname:{http://example.co.uk/claim/ws/v2}getClaimRequest?endpointMapping=#endpointMapping")
        .to("log:uk.co.example.claim.ws.v2?level=INFO")
        .unmarshal(jaxb)
        .process(new ClaimProcessor())
        .marshal(jaxb);
    }
}

根据日志(如下),传入请求已成功映射到我的 Camel 消费者,但随后失败并显示“端点没有适配器”

[2015-06-24 13:22:03.981] boot - 6892 DEBUG [http-nio-8090-exec-6] --- WsdlDefinitionHandlerAdapter: Transforming [/ws] to [http://localhost:8090/ws]
[2015-06-24 13:22:03.983] boot - 6892 DEBUG [http-nio-8090-exec-6] --- MessageDispatcherServlet: Successfully completed request
[2015-06-24 13:22:13.544] boot - 6892 DEBUG [http-nio-8090-exec-7] --- WebServiceMessageReceiverHandlerAdapter: Accepting incoming [org.springframework.ws.transport.http.HttpServletConnection@70863933] at [http://localhost:8090/ws]
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- received: Received request [SaajSoapMessage {http://example.co.uk/claim/ws/v2}getClaimRequest]
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- PayloadRootAnnotationMethodEndpointMapping: Looking up endpoint for [{http://example.co.uk/claim/ws/v2}getClaimRequest]
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint mapping [org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping@5fdbde50] has no mapping for request
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapActionAnnotationMethodEndpointMapping: Looking up endpoint for []
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint mapping [org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationMethodEndpointMapping@50bf4dcb] has no mapping for request
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint mapping [org.springframework.ws.soap.addressing.server.AnnotationActionEndpointMapping@8b5028a] has no mapping for request
[2015-06-24 13:22:13.548] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint mapping [org.apache.camel.component.spring.ws.bean.CamelEndpointMapping@7a9ff5b1] maps request to endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]
[2015-06-24 13:22:13.548] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Testing endpoint adapter [org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter@5a1e093a]
[2015-06-24 13:22:13.549] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapFaultAnnotationExceptionResolver: Resolving exception from endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: java.lang.IllegalStateException: No adapter for endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?
[2015-06-24 13:22:13.549] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SimpleSoapExceptionResolver: Resolving exception from endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: java.lang.IllegalStateException: No adapter for endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?
[2015-06-24 13:22:13.549] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint invocation resulted in exception - responding with Fault
java.lang.IllegalStateException: No adapter for endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?
        at org.springframework.ws.server.MessageDispatcher.getEndpointAdapter(MessageDispatcher.java:302)
        at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:235)
        at org.springframework.ws.server.MessageDispatcher.reessageDispatcher.java:176)
        at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:89)
        at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:61)
        at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:293)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catali.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)
[2015-06-24 13:22:13.554] boot - 6892 DEBUG [http-nio-8090-exec-7] --- sent: Sent response [SaajSoapMessage {http://schemas.xmlsoap.org/soap/envelope/}Fault] for request [SaajSoapMessage {http://example.co.uk/claim/ws/v2}getClaimRequest]
[2015-06-24 13:22:13.556] boot - 6892 DEBUG [http-nio-8090-exec-7] --- MessageDispatcherServlet: Successfully completed request

我的gradle依赖如下:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-ws") {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
    compile("org.springframework.boot:spring-boot-starter") {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
    compile("org.springframework.boot:spring-boot-starter-log4j")
    compile("org.springframework:spring-web")
    compile("com.fasterxml.jackson.core:jackson-databind")
    compile("org.apache.camel:camel-core:2.15.2")
    compile("org.apache.camel:camel-spring-boot:2.15.2")
    compile("org.apache.camel:camel-spring-ws:2.15.2")
    compile("org.apache.camel:camel-jaxb:2.15.2")
    testCompile("org.springframework.boot:spring-boot-starter-test")
    compile 'org.slf4j:slf4j-log4j12:1.7.12'
    compile("wsdl4j:wsdl4j:1.6.1")
    jaxb("com.sun.xml.bind:jaxb-xjc:2.2.4-1")
    compile sourceSets.generated.output
}

我研究了大量的No adapter for endpoint问题,其中大部分似乎是由端点的返回类型引起的。但是,我只是在创建一个骆驼路线,所以大概 camel-spring-ws 集成应该提供实际的端点。

我是否缺少配置/注释的关键部分,还是存在更根本的问题(可能是某些版本不兼容)?非常感谢任何帮助或见解。

【问题讨论】:

    标签: spring web-services apache-camel spring-boot spring-ws


    【解决方案1】:

    使用spring boot时,它只注册DefaultMethodEndpointAdapter,配置注解驱动的Spring WS编程模型。这样就可以使用各种注解,如@Endpoint、@Payload 自动检测。

    在我们的例子中,spring-ws 端点必须将 ws 请求交给骆驼端点,DefaultMethodEndpointAdapter 不会为我们做这项工作。

    下面是spring框架中做端点适配器注册的部分代码,

    private void initEndpointAdapters(ApplicationContext applicationContext) throws BeansException {
    
        if (endpointAdapters == null) {
            Map<String, EndpointAdapter> matchingBeans = BeanFactoryUtils
                    .beansOfTypeIncludingAncestors(applicationContext, EndpointAdapter.class, true, false);
    
    
            if (!matchingBeans.isEmpty()) {
                endpointAdapters = new ArrayList<EndpointAdapter>(matchingBeans.values());
                Collections.sort(endpointAdapters, new OrderComparator());          
            }
    
            else {
                endpointAdapters =
                        defaultStrategiesHelper.getDefaultStrategies(EndpointAdapter.class, applicationContext);
                if (logger.isDebugEnabled()) {
                    logger.debug("No EndpointAdapters found, using defaults");
                }
            }
        }
    } 
    

    当我们使用 spring-boot 时,DefaultMethodEndpointAdapter 被注册,因此第一个“if 块”运行,因此它不会注册其他适配器,如 MessageEndpointAdapter、PayloadEndpointAdapter 等。

    在这种情况下,我们需要的是,除了 DefaultMethodEndpointAdapter 之外,还必须注册 MessageEndpointAdapter 以将 spring-ws 卸载到骆驼端点。

    所以在WebServiceConfig类中,添加以下代码,

    @Bean
        public EndpointAdapter messageEndpointAdapter() {
            return new MessageEndpointAdapter();
        }
    

    然后切换魔法发生了。

    MessageEndpointAdapter 是 spring-ws 和 camel 所必需的 交接。

    【讨论】:

    • spring boot注解就是这种情况,如果你使用xml配置,就不会发生这种情况,因为在后一种情况下会激活else块。
    • 很好的解释。对我来说就像一个魅力。有同样的问题。
    • 如果你使用了基于 Java 的配置,这个 Bean 就是救命稻草。
    猜你喜欢
    • 1970-01-01
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    相关资源
    最近更新 更多