## 3.2 用例一: stock portfolio实例 – Use case one: the stock portfolio example

As mentioned earlier in the chapter, the first use case revolves around a stock portfolio

use case for demonstrating publish/subscribe messaging. This example is simple

and utilizes a Publisher class for sending stock price messages to a topic, as well as a

Consumer class for registering a Listener class to consume messages from topics in

an asynchronous manner. These three classes embody the functionality of generating

ever-changing stock prices that are published to topics on which the consumer is

subscribed.

In this example, stock prices are published to an arbitrary number of topics. The

number of topics is based on the number of arguments sent to the Publisher and the

Consumer on the command line. Each class will dynamically send and receive to/from

the topics (an example is provided next). Take a look at figures 3.2 and 3.3 to see at a

high level what the examples seek to achieve.

For the sake of this demonstration, two topics will be used. The Publisher class

uses a single JMS MessageProducer to send 1,000 fictitious stock price messages in

blocks of 10, randomly distributed across the topics named in the command-line argument.

After it sends 1,000 messages, it shuts down. The Consumer class creates one JMS

MessageConsumer per topic and registers a JMS MessageListener for each topic.

Because this example demonstrates publish/subscribe, the Consumers must be online

to consume messages being sent by the Publisher, because durable consumers aren’t

used in the basic stock portfolio example. The next step is to actually run the example

so that you can see them in action.

3.2.1 Running the stock portfolio example

3.2.1 运行stock portfolio实例

There are three basic steps to running this example:

1 Start up ActiveMQ

2 Run the Consumer class

3 Run the Publisher class

1 启动ActiveMQ

2 运行Consumer类

3 运行Publisher类

These steps appear to be simple, and they are. The only item of note is that the Consumer

should be started before the Publisher, in order to receive all messages that are

published. This is because this example demonstrates pub/sub messaging and topics

won’t hold messages unless the consumer makes a durable subscription, and we’re

not using durable subscriptions here. So let’s get started with the stock portfolio

example.

The first task is to open a terminal or command line and execute ActiveMQ. This

only requires a single command as demonstrated in the following listing.

./bin/activemq console (注:windows下,到ActiveMQ的bin目录中 执行activemq即可)

Listing 3.2 Start up ActiveMQ

[apache-activemq-5.4.1] $./bin/activemq console INFO: Using default configuration (you can configure options in one of these file: /etc/default/activemq /Users/bsnyder/.activemqrc) INFO: Invoke the following command to create a configuration file ./bin/activemq setup [/etc/default/activemq | /Users/bsnyder/.activemqrc] INFO: Using java ‘/System/Library/Frameworks/JavaVM.framework/Home/bin/java’ INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C) Java Runtime: Apple Inc. 1.6.0_20 /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home Heap sizes: current=258880k free=253105k max=258880k JVM args: -Xms256M -Xmx256M -Dorg.apache.activemq.UseDedicatedTaskRunner=true -Djava.util.logging.config.file=logging.properties -Dcom.sun.management.jmxremote -Dactivemq.classpath=/Users/bsnyder/amq/apache-activemq-5.4.1/conf; -Dactivemq.home=/Users/bsnyder/amq/apache-activemq-5.4.1 -Dactivemq.base=/Users/bsnyder/amq/apache-activemq-5.4.1 ACTIVEMQ_HOME: /Users/bsnyder/amq/apache-activemq-5.4.1 ACTIVEMQ_BASE: /Users/bsnyder/amq/apache-activemq-5.4.1 Loading message broker from: xbean:activemq.xml INFO | Started SelectChannelConnector@0.0.0.0:8161 The next task is to open a second terminal or command line to execute the Consumer class. The Consumer is executed using the maven-exec-plugin (http://mng.bz/bf7g) by passing it some system properties as arguments using the exec.args property. An example of running the Consumer is shown next. 下一步,打开第二个终端窗口或控制台窗口执行Consumer类.Consumer类使用Maven的maven-exec-plugin 插件,需要使用exec.args传递几个系统属性作为参数.下面是允许Consumer的命令例子: Listing 3.3 Run the stock portfolio consumer [amq-in-action-example-src]$ mvn exec:java  -Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Consumer  -Dexec.args=”CSCO ORCL”

[INFO] Scanning for projects…

[INFO] Searching repository for plugin with prefix: ‘exec’.

[INFO] org.apache.maven.plugins: checking for updates from central

[INFO] org.codehaus.mojo: checking for updates from central

[INFO] artifact org.codehaus.mojo:exec-maven-plugin: checking for updates from central

[INFO] snapshot org.codehaus.mojo:exec-maven-plugin:1.1.2-SNAPSHOT: checking for updates from public-snapshots

[INFO] snapshot org.codehaus.mojo:exec-maven-plugin:1.1.2-SNAPSHOT: checking for updates from central

http://localhost:8081/nexus/content/groups/public/org/codehaus/mojo/mojo-parent/22/mojo-parent-22.pom

http://localhost:8081/nexus/content/groups/public-snapshots/org/codehaus/mojo/exec-maven-plugin/1.1.2-SNAPSHOT/exec-maven-plugin-1.1.2-20091120.114446-3.jar

[INFO] ————————————————————————

[INFO] Building ActiveMQ in Action Examples

[INFO] ————————————————————————

[INFO] Preparing exec:java

[INFO] No goals needed for project – skipping

[WARNING] POM for ‘woodstox:wstx-asl:pom:3.2.7:compile’ is invalid.

Its dependencies (if any) will NOT be available to the current build.

http://localhost:8081/nexus/content/groups/public/org/apache/commons/

commons-exec/1.0.1/commons-exec-1.0.1.pom

http://localhost:8081/nexus/content/groups/public/org/apache/commons/

commons-exec/1.0.1/commons-exec-1.0.1.jar

[INFO] [exec:java {execution: default-cli}]

You can see in listing 3.3 that Maven downloads the necessary artifacts it needs to run

the examples. Once this has completed, the Publisher can start up and begin publishing

stock prices to the two topics named on the command line, CSCO and ORCL.

These two topic names were picked at random and can be replaced with any Strings

you desire. The important part is that the same arguments be used for both the

Consumer and the Publisher (the Publisher is shown next) via the system property

exec.args.

CSCO 和 ORCL.这两个主题名称是随便选取的,你可以用其他任意字符串代替.重要的一点是

(运行Publisher的命令将在下文给出).

BUILD ERRORS WHEN RUNNING THE CONSUMER

If you receive a BUILD ERROR while attempting to run the consumer class,

you’ll need to compile the source code before running it.

To compile all the source, run the following command:

$mvn clean install This command will compile and package the source so that it’s ready to be run. After this command completes, you can go back and run the command consumer using the command shown earlier. 如果在运行consumer时提示BUILD ERROR(编译错误),你需要重新编译源代码. 使用下面的命令重新编译源代码:$ mvn clean install

Note that the output just seems to stop as the Consumer hangs there. This behavior is

correct because it’s waiting for messages to arrive in the topics to be consumed. When

the Publisher begins sending messages, the Consumer will begin to consume them.

Why are all the artifacts being downloaded from the localhost in the output shown?

As long as Maven was set up correctly in section 3.1, then Maven will download all

in the first portion of the output. Note that all the artifacts are being downloaded

from the localhost instead of from a remote Maven repository. This is because the

example is being run with Maven, which is configured to use a Maven repository manager

named Nexus on the local computer. Nexus provides many benefits, one of

which is a proxy to remote Maven repositories with a local cache of all downloaded

artifacts. After Maven downloads artifacts the first time via Nexus, they’re held in a

local cache. During successive builds, Nexus provides the artifacts from the local

cache instead of checking a remote repository, and this speeds up the build time

features, see: http://nexus.sonatype.org/.

The next task is to open a third terminal or command line to execute the Publisher

class. Note that the same arguments are used in exec.args that were used for executing

the Consumer class earlier, because the maven-exec-plugin is used to execute the

Publisher class as well. An example of running Publisher is shown here.

[amq-in-action-example-src] \$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Publisher -Dexec.args=”CSCO ORCL”

[INFO] Scanning for projects…

[INFO] Searching repository for plugin with prefix: ‘exec’.

[INFO] ——————————————————————-

—–

[INFO] Building ActiveMQ in Action Examples

[INFO] ——————————————————————-

—–

[INFO] Preparing exec:java

[INFO] No goals needed for project – skipping

[WARNING] POM for ‘woodstox:wstx-asl:pom:3.2.7:compile’ is invalid.

Its dependencies (if any) will NOT be available to the current build.

[INFO] [exec:java {execution: default-cli}]

Sending: {offer=62.6861410176471, price=62.62351750014696, up=true,

stock=ORCL} on destination: topic://STOCKS.ORCL

Sending: {offer=55.508573596887715, price=55.45312047641131, up=true,

stock=CSCO} on destination: topic://STOCKS.CSCO

Sending: {offer=62.527946513790205, price=62.46548103275745, up=false,

stock=ORCL} on destination: topic://STOCKS.ORCL

Sending: {offer=55.78778713074073, price=55.73205507566507, up=true,

stock=CSCO} on destination: topic://STOCKS.CSCO

Sending: {offer=55.593918646251986, price=55.53838026598601, up=false,

stock=CSCO} on destination: topic://STOCKS.CSCO

Sending: {offer=55.83360390719586, price=55.777826081114746, up=true,

stock=CSCO} on destination: topic://STOCKS.CSCO

Sending: {offer=55.99233608275527, price=55.93639968307221, up=true,

stock=CSCO} on destination: topic://STOCKS.CSCO

Sending: {offer=62.006501598331475, price=61.94455704129019, up=false,

stock=ORCL} on destination: topic://STOCKS.ORCL

Sending: {offer=55.53698948617822, price=55.48150797820003, up=false,

stock=CSCO} on destination: topic://STOCKS.CSCO

Sending: {offer=61.43866500377897, price=61.377287716062916, up=false,

stock=ORCL} on destination: topic://STOCKS.ORCL

Published ’10’ of ’10’ price messages

Sending: {offer=55.466945358331216, price=55.41153382450671, up=false,

stock=CSCO} on destination: topic://STOCKS.CSCO

Sending: {offer=61.27694222131968, price=61.215726494824864, up=false,

stock=ORCL} on destination: topic://STOCKS.ORCL

Published ’10’ of ’30’ price messages

When executing the Publisher class, Maven already has all the necessary dependencies

from the earlier execution of the Consumer class, so nothing should be downloaded.

The lower portion of the output shows the stock price messages being sent to

the two topics in blocks of 10. The example output is truncated for space, so just know

that the Publisher will run until it sends a total of 1,000 messages.

After running the Publisher, if you switch back to the second terminal where the

Consumer was started, you should see that it’s now consuming messages from the topics:

[INFO] [exec:java {execution: default-cli}]

ORCL 62.62 62.69 up

CSCO 55.45 55.51 up

ORCL 62.47 62.53 down

CSCO 55.73 55.79 up

CSCO 55.94 55.99 up

CSCO 55.41 55.47 down

ORCL 61.22 61.28 down

ORCL 61.42 61.48 up

The preceding output comes from the Listener class that’s registered by the

Consumer on the two topics named ORCL and CSCO. This output shows the consumption

of the stock price messages from the same two topics to which the Publisher is

sending messages. Once the Publisher reaches 1,000 messages sent, it’ll shut down.

But the Consumer will continue to run and just hang there waiting for more messages

to arrive on those two topics. You can press CTRL-C in the second terminal to shut

down the Consumer at this point.

Now that you’ve seen how ActiveMQ works well in a pub/sub messaging scenario,

the following section will explore how it works in point-to-point messaging.

Publisher将自动关闭.而Consumer类将一直运行并挂起以等待更多的消息发布到那个那个主题.

微信赞赏  支付宝赞赏