REST on JMS Transport而不是HTTP

时间:2017-04-05 09:09:03

标签: rest jms cxf spring-jms cxfrs

我尝试为REST创建多个通道,以便可以使用http protcol从浏览器调用我的端点,或者可以通过在队列中放置消息来异步调用其他应用程序。虽然我能够配置两种传输类型。我能够访问REST服务,但在发送JMS消息时失败。

以下是我用于复制问题的完整代码设置。

的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.kp.swasthik</groupId>
    <artifactId>kp-rest-jms-artemis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>kp-rest-jms-artemis</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.5.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <cxf.version>3.1.10</cxf.version>
        <!-- <artemis.version>2.0.0</artemis.version> -->
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxrs</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-jms</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>artemis-jms-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-artemis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

REST服务

@Service
@Path("/kp")
public class KPRest {

    @Autowired
    private JmsTemplate jmsTemplate;

    @POST
    @Path("/hello")
    @Consumes(MediaType.TEXT_PLAIN)
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(String hello){
        System.out.println(hello);
        return "Hello from CXF";
    }

    @GET
    @Path("/send-message")
    public String sendMessage(){
        jmsTemplate.send("cxf_queue", (session)->{
            TextMessage msg = session.createTextMessage();
            msg.setBooleanProperty("OnewayMessage", true);
            msg.setStringProperty("org.apache.cxf.message.Message.REQUEST_URI", "/kp/hello");
            msg.setText("JMS message");
            return msg;
        });
        return "Sent message";
    }

}

Cxf配置

import com.kp.swasthik.cxf.rest.KPRest;

@Configuration
public class CxfConfig {

    @Bean
    public Server jaxrsServerRest(Bus bus, KPRest rest){
        JAXRSServerFactoryBean server = new JAXRSServerFactoryBean();
        server.setAddress("/kp");
        server.setBus(bus);
        server.setServiceBean(rest);
        server.setFeatures(Arrays.asList(new LoggingFeature()));
        return server.create();
    }

    @Bean
    public Server jaxrsServerJMS(Bus bus, KPRest rest, JMSConfigFeature feature){
        JAXRSServerFactoryBean server = new JAXRSServerFactoryBean();
        server.setAddress("/");
        server.setTransportId("http://cxf.apache.org/transports/jms");
        server.setBus(bus);
        server.setServiceBean(rest);
        server.setFeatures(Arrays.asList(new LoggingFeature(), feature));
        return server.create();
    }

    @Bean
    public JMSConfigFeature getJMSFeature(JMSConfiguration jmsConfiguration) {
        JMSConfigFeature feature = new JMSConfigFeature();
        feature.setJmsConfig(jmsConfiguration);
        return feature;
    }

    @Bean
    public JMSConfiguration getjmsConfig(ConnectionFactory connectionFactory) {
        JMSConfiguration config = new JMSConfiguration();
        config.setConnectionFactory(connectionFactory);
        config.setTargetDestination("cxf_queue");
        return config;
    }
}

Spring Boot入门级

@SpringBootApplication
public class KpRestJmsArtimisApplication {

    public static void main(String[] args) {
        SpringApplication.run(KpRestJmsArtimisApplication.class, args);
    }
}

application.properties

spring.artemis.embedded.queues=cxf_queue
spring.artemis.embedded=true

我正在调用send-message rest api,它将消息放在cxf_queue中,这将由CXF端点读取。但是,由于.

中存在org.apache.cxf.message.Message.REQUEST_URI,我收到了错误消息

这是stacktrace。

javax.jms.JMSRuntimeException: AMQ129012: The property name 'org.apache.cxf.message.Message.REQUEST_URI' is not a valid java identifier.
    at org.apache.activemq.artemis.jms.client.ActiveMQMessage.checkProperty(ActiveMQMessage.java:919) ~[artemis-jms-client-1.3.0.jar:1.3.0]
    at org.apache.activemq.artemis.jms.client.ActiveMQMessage.setStringProperty(ActiveMQMessage.java:657) ~[artemis-jms-client-1.3.0.jar:1.3.0]
    at com.kp.swasthik.cxf.rest.KPRest.lambda$0(KPRest.java:37) ~[classes/:na]
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:593) ~[spring-jms-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.jms.core.JmsTemplate$4.doInJms(JmsTemplate.java:574) ~[spring-jms-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:484) ~[spring-jms-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:570) ~[spring-jms-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at com.kp.swasthik.cxf.rest.KPRest.sendMessage(KPRest.java:34) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_102]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_102]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_102]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_102]
    at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180) ~[cxf-core-3.1.10.jar:3.1.10]
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) ~[cxf-core-3.1.10.jar:3.1.10]
    at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:189) ~[cxf-rt-frontend-jaxrs-3.1.10.jar:3.1.10]
    at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:99) ~[cxf-rt-frontend-jaxrs-3.1.10.jar:3.1.10]
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) ~[cxf-core-3.1.10.jar:3.1.10]
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96) ~[cxf-core-3.1.10.jar:3.1.10]
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) ~[cxf-core-3.1.10.jar:3.1.10]
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) ~[cxf-core-3.1.10.jar:3.1.10]
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:262) ~[cxf-rt-transports-http-3.1.10.jar:3.1.10]
    at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234) ~[cxf-rt-transports-http-3.1.10.jar:3.1.10]
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208) ~[cxf-rt-transports-http-3.1.10.jar:3.1.10]
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160) ~[cxf-rt-transports-http-3.1.10.jar:3.1.10]
    at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:180) ~[cxf-rt-transports-http-3.1.10.jar:3.1.10]
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:299) ~[cxf-rt-transports-http-3.1.10.jar:3.1.10]
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:223) ~[cxf-rt-transports-http-3.1.10.jar:3.1.10]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:274) ~[cxf-rt-transports-http-3.1.10.jar:3.1.10]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_102]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_102]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_102]

不确定Cxf完全支持具有JMS传输类型的REST。虽然在文档中说它支持但我没有看到很多细节。并且还不确定是否有任何方式或属性来逃避.字符。

2 个答案:

答案 0 :(得分:1)

我不知道你要做什么的完整背景,但是这......

'org.apache.cxf.message.Message.REQUEST_URI' is not a valid java identifier.

......非常清楚。你不能这样做......

msg.setStringProperty("org.apache.cxf.message.Message.REQUEST_URI", "/kp/hello");

...因为JMS属性中不能包含. - 它们使用与java标识符相同的规则(例如变量)。

您可以将.替换为发送方_,并在接收方交换它们;如果您需要那种格式。

答案 1 :(得分:1)

CXF实施目前不遵循JMS规范。我会注意我们解决这个问题,同时保持与旧CXF客户端的兼容性。

请参阅https://issues.apache.org/jira/browse/CXF-7344