简体   繁体   中英

Spring JMS Listener Container not stopping fully

I have weird problem with a JMS Listener container. In case I stop the listener container, half of messages are still delivered to the app and processed by listener. Here is my deployment descriptor:

  <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/jms-config.xml,WEB-INF/root-context.xml</param-value>      
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Here is my Spring configuration:

<context:component-scan base-package="com.con.*" />


    <bean   class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />


    <!-- Web methods environment mappings -->

    <bean id="webMethodProperties"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="file:/opt/app/jboss/current/modules/com/con/commons/logconfiguration/main/webmethods.properties" />
    </bean> 


    <bean id="intialContext" class="javax.naming.InitialContext">
    <constructor-arg>

            <map>
                <entry key="java.naming.factory.initial" value="${java.naming.factory.initial}" />
                <entry key="java.naming.provider.url" value="${java.naming.provider.url}" />
                <entry key="com.webmethods.jms.naming.clientgroup" value="${com.webmethods.jms.naming.clientgroup}" />
            </map>

        </constructor-arg>
    </bean>
    <!-- JNDI Template for accessing Web Method resources -->
    <bean id="webMethodsJndiTemplate" class="org.springframework.jndi.JndiTemplate">
        <property name="environment">
            <map>
                <entry key="java.naming.factory.initial" value="${java.naming.factory.initial}" />
                <entry key="java.naming.provider.url" value="${java.naming.provider.url}" />
                <entry key="com.webmethods.jms.naming.clientgroup" value="${com.webmethods.jms.naming.clientgroup}" />
            </map>
        </property>
    </bean>
    <bean id="destinationResolver"
        class="org.springframework.jms.support.destination.JndiDestinationResolver">
        <property name="jndiTemplate" ref="webMethodsJndiTemplate" />
        <property name="cache" value="true" />
        <property name="fallbackToDynamicDestination" value="false" />
    </bean>

    <!-- Custom ConnectionFactory to customize ClientId -->
    <bean id="remoteJmsConnectionFactory"
        class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="connectionFactoryHelper"/>
        <property name="targetMethod" value="createJmsConnectionFactory"/>
    </bean>

    <!-- JMS MDB Container which recieves messages from Vantage S -->

    <jms:listener-container container-type="default"
        connection-factory="remoteJmsConnectionFactory" destination-type="durableTopic"
        destination-resolver="destinationResolver" acknowledge="auto">
        <jms:listener destination="beconEventingJMSTopic" ref="beconListener" id="jmslistener"
            selector="${scrmessageselector}" subscription="${screventingsubscriber}"
            method="onMessage" />
    </jms:listener-container>

    <bean id="beconListener" class="com.con.jms.OMIListener"/>

</beans>

Trying to start listener here

@Controller
public class StartJmsController {

    @Resource(name="jmslistener")
    private DefaultMessageListenerContainer beconListener;

    @RequestMapping("/startscrjms")
    public String hello(
            @RequestParam(value = "name", required = false, defaultValue = "World") String name,
            Model model) {

        beconListener.start();
        model.addAttribute("message", "JMS Listener started.");
        return "jmsmessage";
    }

}

Stop Listener here.

@Controller

public class StopJmsController {

    @Resource(name="jmslistener")
    private DefaultMessageListenerContainer beconListener;

    @RequestMapping("/stopscrjms" ) 
    public String printWelcome(ModelMap model,  HttpSession session) {

        beconListener.stop(new Runnable() {
            public void run() {
                System.out.println("JMS Listener stopped.");
            }
        });

        model.addAttribute("message", "JMS Listener stopped.");
        return "jmsmessage";

    }

}

root-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd">

  <!-- Empty -->

</beans>

pom.xml

   <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>WebMethodTopicSubscriber</groupId>
        <artifactId>OMISCRPayLoad</artifactId>
        <version>1.0</version>
        <packaging>war</packaging>
        <dependencies>
            <dependency>
                <groupId>com.wm.g11n</groupId>
                <artifactId>wm-g11nutils</artifactId>
                <version>8.2.2.4</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.webmethods.jms</groupId>
                <artifactId>wm-brokerclient</artifactId>
                <version>8.2.3</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.webmethods.jms</groupId>
                <artifactId>wm-jmsnaming</artifactId>
                <version>8.2.2</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.webmethods.jms</groupId>
                <artifactId>wm-jmsclient</artifactId>
                <version>8.2.2.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>antlr</groupId>
                <artifactId>antlr</artifactId>
                <version>2.7.7</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>aopalliance</groupId>
                <artifactId>aopalliance</artifactId>
                <version>1.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>commons-collections</groupId>
                <artifactId>commons-collections</artifactId>
                <version>3.2.1</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>commons-dbcp</groupId>
                <artifactId>commons-dbcp</artifactId>
                <version>1.4</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.1.1</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>commons-pool</groupId>
                <artifactId>commons-pool</artifactId>
                <version>1.6</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>dom4j</groupId>
                <artifactId>dom4j</artifactId>
                <version>1.6.1</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.logicblaze.fuse.liferay.dependencies</groupId>
                <artifactId>jms</artifactId>
                <version>fuse-4.1.2</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.2.1</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-expression</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jms</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-tx</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>4.0.3.RELEASE</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.con.commons</groupId>
                <artifactId>Configuration</artifactId>
                <version>1.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
              <groupId>org.apache.logging.log4j</groupId>
              <artifactId>log4j-api</artifactId>
              <version>2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.1</version>
        </dependency>   
            <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
             <scope>provided</scope>
        </dependency>
        </dependencies>

    <build>
         <sourceDirectory>src/main/java</sourceDirectory>
        <resources>
          <resource>
            <directory>src/main/java</directory>
            <filtering>true</filtering>
            <includes>
              <include>**/*.xml</include>          
            </includes>
          </resource>     
        </resources>

            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.3</version>
                    <configuration>
                        <warSourceDirectory>WebContent</warSourceDirectory>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>


          </plugins>
        </build>
    </project>

Read in the blog that probably this is the error " is that you are loading the container into both the web context (DispatcherServlet's context) and the root context (ContextLoaderListener's context). Which means you have 2 containers and you are only stopping the one in the servlet context"

Issue is similar Spring JMS Listener Container stop only half of listeners

But fix is not clear in the answer.

How can I fix this. ?

In your web.xml change the Dispatcher Servlet definition to below.

    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
                <param-value>WEB-INF/jms-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

And remove the following part.

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/jms-config.xml,WEB-INF/root-context.xml</param-value>      
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Updated as per user comments

The recommended pattern is to have separate context for non web stuff and the web stuff. But in your case there doesn't seem to be anything in the root context, you can skip it if your app works that way.

In future if you require root scope - say you add ORM support in your app - you could always keep the ContextLoaderListener entry in there with the contextConfigLocation context param with the value as only your root context config file name.

As a side note, even if you decide to add the ORM support in your app you could very well do that in the web context and the app should work fine, just that it is not recommended.

Update try this.

    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
                <param-value>WEB-INF/jms-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>


<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/root-context.xml</param-value>      
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM