8.1 示范web程序

8.1 示例web程序

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.