8.2 ActiveMQ 与Apache Tomcat集成

8.2 Integrating with Apache Tomcat

Apache Tomcat is arguably the most widely used Java web container available today.Tomcat is used for both development and production throughout the world becauseit’s extremely robust, highly configurable, and commercially supported by a numberof companies. Because of its widespread use, Tomcat provides facilities for integratingthird-party resources such as JDBC data sources, JMS connection factories, and so on,and making them JNDI accessible. In this section, we’ll show you how to integrateActiveMQ with Apache Tomcat. You’ll need to download Apache Tomcat 6.0.26(http://mng.bz/75qc) and expand it on your computer.

8.2 与Apache Tomcat集成

Apache Tomcat毫无疑问是当今世界上使用做广泛的Java web容器.  Tomcat同时广泛用于 世界范围内的开发和生产环境的原因是其极其健壮,高可配置并受到很多公司的商业支持.因为应用广泛,Tomcat提供了多种工具用于集成诸如JDBC数据源,JMS连接工厂等第三方资源,并且可以通过JNDI访问这些第三方资源.本节中,我们将展示如何集成ActiveMQ到Apache Tomcat中.你需要下载Apache Tomcat 6.0.26(http://mng.bz/75qc)并解压到你的电脑中.

Tomcat offers two styles of configuration for JNDI resources: local JNDI context andglobal JNDI context. Configuring a local JNDI resource means that the resource is onlyavailable to a particular web application deployed to Tomcat. Configuring a resourcein the global JNDI context means that the resource is available to any web applicationdeployed to Tomcat. The configuration for each type of JNDI style is different, so let’sreview both.

Tomcat提供配置两种方式的JNDI:本地JNDI和全局JNDI.配置本地JNDI表示该JNDI资源只能被部署到Tomcat的特定的web程序使用,配置全局JNDI表示该JNDI资源可以被所有部署在Tomcat中的资源使用. 不同类型的JNDI的配置是不同的,下面让我们分别来看看这两种配置.

NOTE The sample applications for the local JNDI configuration and theglobal JNDI configuration can’t be deployed at the same time. This will causeclassloader issues and will prevent ActiveMQ from being deployed correctly.Make sure to only deploy one of the sample applications at a time.

8.2.1 Using local JNDI to integrate ActiveMQ with Tomcat

The local JNDI configuration restricts the availability of resources to the applicationwhere they’re defined. With this style of configuration for Tomcat, the JNDI resourcesare defined in a file named META-INF/context.xml. The following listing shows thecontext.xml file.
Listing 8.5 The Tomcat context.xml file

8.2.1 使用本地JNDI将ActiveMQ集成到Tomcat中

<Context reloadable="true">
<Resource
auth="Container"
name="jms/ConnectionFactory"
type="org.apache.activemq.ActiveMQConnectionFactory"
description="JMS Connection Factory"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
brokerURL="vm://localhost
brokerConfig=xbean:activemq.xml"
brokerName="MyActiveMQBroker"
/>

<Resource
auth="Container"
name="jms/FooQueue"
type="org.apache.activemq.command.ActiveMQQueue"
description="JMS queue"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
physicalName="FOO.QUEUE"
/>
</Context>

Listing 8.5 is specific to Tomcat. The first element is named jms/Connection-Factory—it defines an ActiveMQ connection factory and takes advantage of featuresin ActiveMQ to start an instance of the broker via the connection factory. The secondelement named jms/FooQueue defines a JMS queue in ActiveMQ. This configurationfile lives with the web application and is automatically picked up by Tomcat to configurethe resources. Tomcat makes them available via a standard JNDI lookup to thesample web application.

NOTE The $TOMCAT_HOME variable is being used to generically reference theTomcat installation directory. This isn’t something that you must set in yourenvironment. 注意:$TOMCAT_HOME变量表示Tomcat的安装目录,并不是必须要在你的环境中设置这个环境变量.(译注,window中需要设置这个环境变量)

To test the local JNDI resources, use the following steps:
Step 1 Copy the jms-webapp-local/target/jms-webapp.war file to the $TOMCAT_HOME/ webapps directory. Step 2 Start up Tomcat: 按照下面的步骤来测试本地JNDI资源: 步骤1 拷贝jms-webapp-local/target/jms-webapp.war到$TOMCAT_HOME/ webapps目录下

$cd$TOMCAT_HOME
$./bin/catalina.sh run Using CATALINA_BASE: /opt/apache-tomcat-6.0.26 Using CATALINA_HOME: /opt/apache-tomcat-6.0.26 Using CATALINA_TMPDIR: /opt/apache-tomcat-6.0.26/temp Using JRE_HOME:System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home Using CLASSPATH: /opt/apache-tomcat-6.0.26/bin/bootstrap.jar ... INFO - BrokerService - ActiveMQ 5.4.1 JMS Message Broker (FooBroker) is starting ... Apr 8, 2010 9:03:03 PM org.apache.catalina.startup.Catalina start INFO: Server startup in 3542 ms You can see in the output that ActiveMQ is actually using the activemq.xml configurationfile because the brokerName FooBroker is being used. Passing the run argument tothe catalina.sh script will cause Tomcat to start up so that its output will appear in theterminal. The ability to see the output is helpful as noted earlier, and will also help youto verify the message receipt in a few steps. 你将看到,在输出信息中ActiveMQ实际上使用了activemq.xml配置文件,因为使用了FooBroker作为代理的名称.将”run”作为参数传递给catalina.sh脚本会启动Tomcat并且会在终端窗口中显示输出信息. 如前文提到的,能够看到输出信息很有用,这样可以帮助你检查在前面步骤中的输出信息. As noted at the beginning of the chapter, this configuration takes advantage ofa unique feature in ActiveMQ. This feature allows an ActiveMQ broker to bestarted simply by creating a connection factory and passing it a broker URI. Theconnection factory attempts to connect to a broker at the URI, and if onedoesn’t exist, it’ll start one up. As you can see, this is a handy feature inActiveMQ. 本章开头部分已经提到,这种配置方式充分利用了ActiveMQ的一个独特的功能,这个功能允许通过创建一个连接工厂并传递一个代理的URI给这个工厂来启动一个代理.因为连接工厂会尝试连接通过URI制定的代理,假如这个代理不存在连接工厂会尝试启动一个代理.就像你已经看到这,ActiveMQ的这个功能非常方便. Step 3 Visit http://localhost:8080/jms-webapp and use the web page to send amessage. See figure 8.4 for an example of what you should see. Step 4 To verify the message send, check the terminal to see that theconsumer received the message. See the following output: Note the output from the terminal—specifically, the final line that’s a log messagefrom the JmsMessageDelegate bean. This line indicates that the message has beenconsumed, and you see the message payload is being output. 步骤3 访问http://localhost:8080/jms-webapp,通过这个web页发送一个示例消息,如图8.4所示. 步骤4 查看终端窗口以便检查消息的发送情况.和消息消费者接收消息.请看下面的额输出信息: 注意这里的来自控制台终端窗体的输出信息,最后一行应该是一个来自JmsMessageDelegate输出的长消息.这行输出表示消息已经被接收和处理过过了,因而你能看到payload消息被打印出来. The local configuration of the ActiveMQ resources is a great approach because theseresources are contained with the web application. Nothing in Tomcat itself needs tobe changed or configured, which is different from the way that resources are configuredfor global JNDI. 配置本地ActiveMQ资源是一个非常好的方式因为这些资源都包含在应用程序中了.Tomcat本身不需要任何修改或者配置,这与配置全局JNDI资源不同. 8.2.2 Using global JNDI to integrate ActiveMQ with Tomcat The global JNDI configuration in Tomcat is also easy to use. It just requires a bit ofadditional configuration and copying some JARs into the Tomcat lib directory. Theadvantage of global JNDI is that the resources are available to any web applicationsthat are deployed to Tomcat. In this style of configuration, the JNDI resources aredefined in configuration files that live with the Tomcat application server namedconf/server.xml and conf/context.xml. The following listing shows the relevant portionof the server.xml file. Listing 8.6 The Tomcat server.xml file 8.2.2 使用全局JNDI将ActiveMQ集成到Tomcat中 Tomcat 中配置全局JNDI也很容易,因为全局配置仅仅需要一些额外的配置并拷贝一些Jar包到 Tomcat的lib目录中.使用全局JNDI的好处是这些资源可以被所有部署在Tomcat中的程序使用.这种方式配置时,JNDI资源是在Tomcat的conf/server.xml和conf/context.xml文件中定义的.下面的代码清单是server.xml 文件中相关的配置部分. 代码清单8.6 Tomcat的server.xml文件 <GlobalNamingResources> ... <Resource auth="Container" name="jms/ConnectionFactory" type="org.apache.activemq.ActiveMQConnectionFactory" description="JMS Connection Factory" factory="org.apache.activemq.jndi.JNDIReferenceFactory" brokerURL="vm://localhost?brokerConfig=xbean:conf/activemq.xml" brokerName="MyActiveMQBroker" /> <Resource auth="Container" name="jms/FooQueue" type="org.apache.activemq.command.ActiveMQQueue" description="A sample queue" factory="org.apache.activemq.jndi.JNDIReferenceFactory" physicalName="FOO.QUEUE" /> ... </GlobalNamingResources> The <Resource> elements in the server.xml file shown in listing 8.6 register theJNDIReferenceFactory object with Tomcat for creating the noted object types—theActiveMQConnectionFactory and the ActiveMQQueue. Again, ActiveMQ is unique inthe fact that a full broker instance can be created by creating anActiveMQConnectionFactory. 代码清单8.6中 Tomcat使用server.xml 文件的 <Resource>元素注册了JNDIReferenceFactory对象用来创建ActiveMQConnectionFactory和ActiveMQQueue.同样,ActiveMQ的独特之处是可以通过创建一个ActiveMQConnectionFactory来创建一个完整的代理实例. The brokerURL attribute is used to pass the broker URI, which allows any of thesupported transports (TCP, VM, and so forth) to be used. It also supports theoptional brokerConfig parameter used to point to a configuration file for theActiveMQ instance that’s being started. The next file to be changed is the context.xml file; the relevant additions are shown next. Listing 8.7 The Tomcat context.xml file brokerURL属性用来传递代理的RUI,该URI允许使用任何支持的传输连接协议(TCP, VM, 等),并且也支持使用可选的代理配置参数,该参数指向一个ActiveMQ实例启动时使用的配置文件. 另一个需要被修改的文件是context.xml文件,下面是该文件中与配置有关的部分: 代码清单8.7 Tomcat 的 context.xml配置文件 <Context> ... <ResourceLink global="jms/ConnectionFactory" name="jms/ConnectionFactory" /> <ResourceLink global="jms/FooQueue" name="jms/FooQueue" /> ... </Context> The <ResourceLink> elements define a link to the resources that are defined in theglobal JNDI context and expose these resources to all web applications deployed inthis instance of Tomcat. To test the global JNDI resource configurations, use the following steps: Step 1 Copy the following JARs into the$TOMCAT_HOME/lib directory:

$mvn clean install ... [INFO] Scanning for projects... [INFO] -------------------------------------------------------------------- [INFO] Building jms-webapp-global [INFO] task-segment: [clean, install] [INFO] -------------------------------------------------------------------- ... [INFO] -------------------------------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO] -------------------------------------------------------------------- ... After running this command, a WAR file will exist in the target directory. Step 3 Copy the jms-webapp-global/activemq.xml file to$TOMCAT_HOME/conf/activemq.xml. This makes the ActiveMQ configuration file available on theclasspath.

Step 5 Start up Tomcat using the following command:

Using CATALINA_BASE: /opt/apache-tomcat-6.0.26
Using CATALINA_HOME: /opt/apache-tomcat-6.0.26
Using CATALINA_TMPDIR: /opt/apache-tomcat-6.0.26/temp
Using JRE_HOME:/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
Using CLASSPATH:/opt/apache-tomcat-6.0.26/bin/bootstrap.jar
...
INFO - BrokerService - ActiveMQ 5.4.1 JMS MessageBroker (FooBroker) is starting
...
Apr 9, 2010 8:54:59 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 3365 ms

Again, you can see that ActiveMQ is using the activemq.xml configuration file based on the output stating that the FooBroker is starting.

Step 6 Visit http://localhost:8080/jms-webapp and send a message.

Step 7 To confirm a successful message send, check the terminal for the following output:

...
INFO: Server startup in 3365 ms
INFO - SingleConnectionFactory - Established shared
JMS Connection:ActiveMQConnection {id=ID:mongoose.local-49429-1270868098091-2:1,clientId=null,started=false}
INFO - JmsMessageDelegate - Consumed message with payload:This is a test message

In the output shown, note that the last line of output from the JmsMessageDelegatebean shows the message payload that was consumed by the JmsMessageDelegatebean.

For some projects, configuring ActiveMQ to use the Tomcat global JNDI context isappropriate because there may be multiple projects that need access to thoseresources. In some situations, it makes sense to control ActiveMQ from within theTomcat process. The disadvantage is that Tomcat and ActiveMQ are now contendingfor the same resources inside of the same JVM. For some projects, this isn’t a problem,and is therefore an acceptable trade-off.

But Tomcat isn’t the only viable open source web container. Jetty is a formidable alternative.

微信赞赏  支付宝赞赏