本文介绍了在JMS Transport上使用REST而不是HTTP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create multiple channels for REST such that my endpoints can be invoked from Browser using http protcol or other applications can asynchronously invoke by placing message on queue. Though I'm able to configure both transport types. I'm able to access the REST service and but fails when sending JMS message.

这是我用来重现此问题的完整代码设置.

Here is the complete code setup I'm using for reproducing the issue.

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配置

导入com.kp.swasthik.cxf.rest.KPRest;

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

I'm calling send-message rest api which places the message in cxf_queue which would be read by the CXF endpoint. However I get error due to the presence of . in the org.apache.cxf.message.Message.REQUEST_URI

这是堆栈跟踪.

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.尽管在文档中它说它支持,但是我没有看到太多细节.并且也不确定是否有任何方式或属性可以转义.字符.

Not sure Cxf Completely supports REST with JMS transport type. though in the documentation it say it supports but I don't see much details in that. And also not sure if there are any way or property to escape . character.

推荐答案

CXF实现当前未遵循JMS规范.我会在保持与旧CXF客户端兼容性的同时,在解决此问题的过程中小心翼翼.

The CXF implementation is currently not following the JMS spec. I will take care we fix this while maintaining compatibility with old CXF clients.

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

这篇关于在JMS Transport上使用REST而不是HTTP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-24 23:54