8.1 The sample web application
8.1 示例web程序
?
To demonstrate the sample integrations in this chapter, a simple web application
is used to prove that each ?integration is successful. There are four ?copies of
this web application that are each customized for various environments. Each web
application is ?small and ?utilizes only ?the ActiveMQ ?broker, a JMS connection
factory, and a JMS queue. Figure 8.1 provides a look at the directory ?structure
for the sample web application.
?
本章中为了演示如何将ActiveMQ集成到应用程序服务器,我们使用了一个简单的web程序来
检查集成是否成功了.这个web应用程序有4份拷贝,每一份拷贝都针对不同的部署环境进行了
不同的配置.每个web程序的规模都很小,仅包括ActiveMQ 代理,一个JMS连接工厂和一个JMS
队列.图8.1展示了这些示例web程序目录结构概览.
?
As you can see, the structure of this is fairly standard for a Maven-based ?Java
web application. Though the screenshot in figure 8.1 shows the project structure
for ?the jms-webapp-local ?application, the ?directory structure ?for the ?other
instances of the ?application is only ?slightly different. Each ?web application
uses the Spring Framework’s web framework features, which reduces the complexity
of building a web application. To understand how the web application works, it’s
best ?to ?examine ?some ?of ?the ?major ?items ?found ?in ?a ?standard ?Java web
application. The relevant portions of the web application that are pertinent ?to
the ?exercises in ?this chapter ?are the ?web.xml file, ?the Spring ?application
context, and the ?JmsMessage- SenderService class. ?The following listing ?shows
the relevant portion of the web.xml file.
?
你可以看到,上面的目录结构是标准的基于Maven的Java web程序目录结构.图8.1的是
jms-webapp-local程序的工程目录结构截图,但是其他的程序工程目录与这个差别很小.
每个web程序都使用了Spring框架中的web框架工程,以便降低创建一个web程序的复杂度.
为了弄清web程序是如何运行的,最好是了解这些标准Java web程序中的主要组件.
本章实例程序中与web程序集成JMS相关的主要组件是web.xml文件,Spring 的应用程序
上下文以及JmsMessage-SenderService类.下面的代码清单是web.xml中与集成JMS相关
的部分:
?
Listing 8.1 The web.xml file
代码清单8.1 web.xml文件
?
...
<resource-ref>
? <description>JMS Connection</description>
? <res-ref-name>jms/ConnectionFactory</res-ref-name>
? <res-type>org.apache.activemq.ActiveMQConnectionFactory</res-type>
? <res-auth>Container</res-auth>
</resource-ref>
?
<resource-ref>
? <res-ref-name>jms/FooQueue</res-ref-name>
? <res-type>javax.jms.Queue</res-type>
? <res-auth>Container</res-auth>
</resource-ref>
...
?
The <resource-ref> elements in the web.xml reference the JNDI resources that are
registered with the application server. This configuration makes those resources available
to the web application. This configuration will only change for the Geronimo
integration, which uses the standard <message-destination-ref> element instead of
a <resource-ref> for the JMS queue.
?
web.xml文件中的<resource-ref>元素是文本程序服务器中已注册的JNDI资源的引用.这里的配置是的
web程序中可以使用这些JNDI资源.这里的配置只在与Geronimo集成时才需要修改,即:使用
<message-destination-ref>替代配置JMS消息队列的<resource-ref>元素.
?
The other relevant configuration file from the web application is the Spring application
context, shown next.
另一个web程序中的配置文件是Spring的程序上下文的配置,如下面代码清单所示:
?
Listing 8.2 The Spring application context file
代码清单8.2 Spring应用程序上下文配置文件:
...
<jee: jndi-lookup?
? ? ? id="connectionFactory"?
? ? ? jndi-name="java:comp/env/jms/ConnectionFactory"
? ? ? cache="true"
? ? ? resource-ref="true"
? ? ? lookup-on-startup="true"
? ? ? expected-type="org.apache.activemq.ActiveMQConnectionFactory"
? ? ? proxy-interface="javax.jms.ConnectionFactory" />
?
<jee: jndi-lookup id="fooQueue"
? ? ? jndi-name="java:comp/env/jms/FooQueue"
? ? ? cache="true"
? ? ? resource-ref="true"
? ? ? lookup-on-startup="true"
? ? ? expected-type="org.apache.activemq.command.ActiveMQQueue"
? ? ? proxy-interface="javax.jms.Queue" />
?
<bean id="jmsMessageBean"
? ? ? class="org.apache.activemq.book.ch8.jms.domain.JmsMessage" />
? ? ??
<bean id="messageSenderService"
? ? ? class="org.apache.activemq.book.ch8.jms.service.JmsMessageSenderService"
? ? ? p:connectionFactory-ref="connectionFactory"
? ? ? p:queue-ref="fooQueue" />
...
?
The Spring application context shown in listing 8.2 is an XML configuration file for
the Spring Framework: see http://www.springframework.org. (Please also note that
Spring’s p-namespace http://mng.bz/dLT9 is being used in the configuration.) The
<jee:jndi-lookup> elements utilize Spring to perform a JNDI lookup of the noted
resources. These resources are then injected into the messageSenderService Java
bean (the values are inserted via setter methods) after it’s instantiated by Spring. The
messageSenderService is then used by the web application to send a JMS message.
?
代码清单8.2所示的是Spring程序上下文配置文件,该文件是用于Spring 框架的XML配置文件
参阅:http://www.springframework.org. (注意,在配置中使用了Sping的p命名空间,参阅:
http://mng.bz/dLT9).<jee:jndi-lookup>元素使用Spring 来进行JNDI查找已暴露的资源.
Spring在完成初始化之后将找到的资源注入到messageSenderService的bean中(通过
setter方法注入).然后,这个web应用程序就可以利用messageSenderService发送JMS消息.
?
?
Listing 8.3 shows the source code for the JmsMessageSenderService bean.
代码清单8.3 是 JmsMessageSenderService bean的源代码.
?
Listing 8.3 The JmsMessageSenderService class
代码清单8.3 ?JmsMessageSenderService 类的源代码.
?
public class JmsMessageSenderService?
{
private JmsTemplate jmsTemplate;
?
public void sendMessage(final JmsMessage bean) throws JMSException?
{
if (bean.isPersistent())
{
jmsTemplate.setDeliveryPersistent(bean.isPersistent());
}
?
if (0 != bean.getTimeToLive())?
{
jmsTemplate.setTimeToLive(bean.getTimeToLive());
}
?
jmsTemplate.send
(new MessageCreator()?
{
public Message createMessage(Session session) throws JMSException?
{
TextMessage message = session.createTextMessage(bean.getMessagePayload());
if (bean.getReplyTo() != null && !bean.getReplyTo().equals(""))?
{
ActiveMQQueue replyToQueue = new ActiveMQQueue(bean.getReplyTo());
message.setJMSReplyTo(replyToQueue);
}
return message;
}
});
}
?
public void setJmsTemplate(JmsTemplate jmsTemplate)?
{
this.jmsTemplate = jmsTemplate;
}
}
?
The JmsMessageSenderService bean is kept simple so that it only focuses on the task
of sending the JMS message. This class uses the Spring JmsTemplate and an anonymous
MessageCreator to easily send the JMS message.
?
JmsMessageSenderService bean被设计成尽量保持简单,以便能将精力集中在发送JMS消息上.
这个类(JmsMessageSenderService)使用Spring的JmsTemplate模版和一个匿名的
MessageCreator实现类轻松实现JMS消息的发送.
?
There’s only one web page in this web application and it’s deliberately uncomplicated.
This is because the web application is only necessary to test the integration and
nothing more. To add further detail to it would only complicate matters and detract
from the real purpose of the chapter.
?
这个示例web程序只有一恶搞页面,并且特意的把这个页面做的简单一些.这是因为使用这个web程序
仅仅是用来测试集成ActiveMQ的.要添加进一步的细节,只会使问题复杂化,这也不是本章的主旨.
?
?
To better understand the flow of a JMS message through these classes, take a look
at figure 8.2.
为了更好的理解使用这些类发送JMS消息的流程,请看图8.2.
?
Here’s a brief explanation of the illustrated steps:
下面简要解释一下使用Spring发送和接受JMS消息的步骤:
?
Step 1 The JmsMessageSenderService implements
an anonymous Spring Message-
Creator to create the message.
第一步,JmsMessageSenderService使用一个匿名类实现了一个MessageCreator,用来创建消息.
?
Step 2 The JmsMessageSenderService uses the
Spring JmsTemplate to send the message
to ActiveMQ.
第二步,JmsMessageSenderService类使用JmsTemplate给ActiveMQ发送消息.
?
Step 3 The Spring DefaultMessageListener-
Container consumes the message and
hands it off to the JmsMessageDelegate.
第三步,Spring的DefaultMessageListenerContainer接收并处理消息,并把消息传递给
JmsMessageDelegate.
?
Step 4 The JmsMessageDelegate bean processes
the message (it outputs the message payload).
第4步,JmsMessageDelegate bean处理消息(它输出payload消息).
?
The ?JmsMessageSenderService is ?completely isolated ?from the ?Spring
DefaultMessageListener- Container and the JmsMessageDelegate bean. Any ?messages
sent to ActiveMQ by the JmsMessage- SenderService have no bearing on whether the
DefaultMessageListenerContainer ?is actually ?online and ?ready to ?consume.?
?
JmsMessageSenderService与Spring中的DefaultMessageListenerContainer and和
JmsMessageDelegate 是完全隔离的.任何通过 JmsMessageSenderService发送给
ActiveMQ的消息都无需了解DefaultMessageListenerContainer是否在线并已做好
处理消息的准备.
?
In fact, ? ?the ? ?Jms-MessageSenderService ? ?and ? ?the ? ?Spring ? ? Default
MessageListenerContainer could easily be split out of this application so as ?to
reside ?in ? completely ?different ? processes ?and ? it ?wouldn’t ? change ?the
functionality of this application. This is a perfect albeit small example of the
asynchronous messaging provided ?by ActiveMQ. figure ?8.2 are all ?hidden behind
the scenes of the single page in ?the sample web application shown in 8.3.?
?
事实上,在这个程序之外,Jms MessageSenderService 和 Spring默认的MessageListenerContainer
可以很容易的被分隔开,从而驻留到不同的处理过程中,并且分割后并不会影响这个程序的功能.
这个示例程序是一个非常小的使用ActiveMQ发送异步消息的程序.图8.2中展示的是所有web
程序中由图8.3所示的单个页面的后台处理过程.
?
?When sending a message using ?the page shown in ?figure 8.3, a small ?message appears
briefly on the page and then fades away quickly to indicate that the message was
sent. This is just a sanity check to show some activity in the web ?application.
These are ?the only ?visible features ?in the ?web application. ?Everything else
happens behind the scenes.
?
当使用如图8.3所示的页面发送消息时,页面会生成一个短小的消息然后迅速的消失,表示
该消息已经被发送出去了.这仅仅是为了显示web程序做了一些操作而做的检查.
这些是web程序中仅有的可见部分,其他工作都是在幕后完成的.
?
These are only the portions of the web application that are apropos to the integration
of ActiveMQ with application servers. To get a better look at the details of this
sample web application, and to actually deploy it yourself to test your own integrations
as you work through the examples, download the example source code for the book.
?
这里介绍的仅仅是在应用程序服务器中集成示例web程序和ActiveMQ的部分内容.如果想要更好
的了解示例web程序的细节,并且自己动手部署这些程序以便测试web程序和ActiveMQ集成的话,
请下载本书示例程序源码.
?
The four versions of the sample web application for this chapter are
四个版本示例web应用程序分别是:
?
? jms-webapp-geronimo ―Used to demonstrate ActiveMQ integration with Geronimo
jms-webapp-geronimo -- 用于说明Geronimo和ActiveMQ集成
? jms-webapp-global―Used to demonstrate ActiveMQ integration with Tomcat and Jetty using global JNDI
jms-webapp-global -- 用于说明ActiveMQ与Tomcat和Jetty的集成并使用了全局JNDI
? jms-webapp-jboss―Used to demonstrate ActiveMQ configuration and deployment with JBoss
jms-webapp-jboss -- 用于说明ActiveMQ和JBoss的集成配置和部署
? jms-webapp-local―Used to demonstrate ActiveMQ integration with Tomcat and Jetty using local JNDI
?jms-webapp-local -- 用于说明ActiveMQ和Jetty的集成并使用了本地JNDI
?
NOTE The local JNDI configuration example and the global JNDI configuration
example can’t be deployed at the same time. This will cause classloader
issues and will prevent ActiveMQ from being deployed correctly. Make sure to
only deploy one style of configuration at a time.
?
注意,使用了本地JNDI配置和全局JNDI配置的例子不能同时部署,否则会导致类加载问题,使得
ActiveMQ不能正常部署.切记一次只能部署一种风格的JNDI.
?
Before proceeding with this chapter, you need to build all four of these examples.
This can be achieved using the Maven command shown next.
在继续阅读本章的内容之前,你需要构建所有的4个示例程序.
可以使用下面的Maven命令构建:
?
Listing 8.4 Build the examples
代码清单8.4 构建示例程序
?
[amq-in-action-example-src] $ cd chapter8/
[chapter8] $ mvn clean install
[INFO] Scanning for projects...
[INFO] Reactor build order:
[INFO] jms-webapp-geronimo
[INFO] jms-webapp-global
[INFO] jms-webapp-jboss
[INFO] jms-webapp-local
[INFO] ActiveMQ In Action Examples Chapter 8
...
[INFO]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] ------------------------------------------------------------------------
[INFO] jms-webapp-geronimo ...................................SUCCESS [4.787s]
[INFO] jms-webapp-global .....................................SUCCESS [1.265s]
[INFO] jms-webapp-jboss ......................................SUCCESS [8.278s]
[INFO] jms-webapp-local ......................................SUCCESS [2.359s]
[INFO] ActiveMQ In Action Examples Chapter 8 .................SUCCESS [1.911s]
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 18 seconds
[INFO] Finished at: Mon Apr 26 13:24:31 MDT 2010
[INFO] Final Memory: 19M/35M
[INFO] ------------------------------------------------------------------------
?
Note that the output in listing 8.4 has been elided slightly. As long as you see the BUILD
SUCCESSFUL message, the examples were built correctly and a WAR file for each one
should now exist in each project’s target directory. This WAR file can then be deployed
to the appropriate application server and used to test the ActiveMQ integration.
?
注意,代码清单8.4中的输出信息是经过简化的以便显示的更简洁.只要你看到BUILD SUCCESSFUL后
就表示所有示例程序都构建成功了.同时每个工程的target目录下面会生成一个WAR文件.
这个WAR文件可以被部署到与应用程序对应的服务器程序中用来测试和ActiveMQ的集成.
?
NOTE Although this chapter describes in detail the changes necessary for
each application server, all of these changes have already been made in each
of the projects. Just make sure to download the source code for the book to
get these example projects.
注意: 尽管本章描述了针对每一个应用程序服务器而对应用程序进行修改的各种细节,
然而所有示例程序源代码都修改好了.所以,你只要下载本书示例程序的源代码就可以了.
?
Now that you have an overview of the sample applications, you’re ready to walk
through the integrations. The first application server with which to integrate
ActiveMQ is Apache Tomcat.
现在你已经大概了解了这些示例程序,你应该准备好亲自在应用程序服务器中将web应用程序
和ActiveMQ集成了.第一个用来集成的应用程序服务器是Apache tomcat.
?
?
?
?