ACTIVEMQ6-9 - port to markdown

https://issues.apache.org/jira/browse/ACTIVEMQ6-9

remove the jboss jdocbook build and style and replace using plane markdown
This commit is contained in:
Andy Taylor 2014-12-04 15:25:29 +00:00
parent d42481db5c
commit 4245a6b4fe
169 changed files with 14940 additions and 19136 deletions

View File

@ -124,17 +124,5 @@
<exclude>**/**/*.dat</exclude>
</excludes>
</fileSet>
<!-- docs -->
<!--todo, this is crap, there must be better jdocbook assembly integration-->
<fileSet>
<directory>../../docs/user-manual/target/docbook/publish/en/html/</directory>
<outputDirectory>web/user-manual</outputDirectory>
<lineEnding>keep</lineEnding>
</fileSet>
<fileSet>
<directory>../../docs/rest-manual/target/docbook/publish/en</directory>
<outputDirectory>docs/rest-manual</outputDirectory>
<lineEnding>keep</lineEnding>
</fileSet>
</fileSets>
</assembly>

View File

@ -1,34 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_Design_Guide.ent">
%BOOK_ENTITIES;
]>
<authorgroup>
<author>
<firstname>Andy</firstname>
<surname>Taylor</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Core Developer</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
<email>ataylor@redhat.com</email>
</author>
</authorgroup>

View File

@ -1,48 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- This document was created with Syntext Serna Free. --><!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_Design_Guide.ent">
%BOOK_ENTITIES;
]>
<bookinfo id="ActiveMQ_QuickStart_Guide">
<title>ActiveMQ Design Guide</title>
<subtitle>Putting the buzz in messaging</subtitle>
<productname>ActiveMQ</productname>
<edition>2.1.0</edition>
<pubsnumber>1</pubsnumber>
<abstract>
<para>This Design guide is to help current and future developers how ActiveMQ's architectures are designed to
help the future development and maintenance of the project</para>
</abstract>
<corpauthor>
<inlinemediaobject>
<imageobject>
<imagedata fileref="images/hornetQ_logo_600px.png" format="PNG"/>
</imageobject>
<textobject>
<phrase>ActiveMQ Logo</phrase>
</textobject>
</inlinemediaobject>
</corpauthor>
<copyright>
<year>&YEAR;</year>
<holder>&HOLDER;</holder>
</copyright>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml"/>
</bookinfo>

View File

@ -1,5 +0,0 @@
<!ENTITY PRODUCT "ActiveMQ">
<!ENTITY BOOKID "ActiveMQ_Design_Guide">
<!ENTITY YEAR "2011">
<!ENTITY HOLDER "Red Hat Inc.">
<!ENTITY semi ";">

View File

@ -1,30 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_Design_Guide.ent">
%BOOK_ENTITIES;
]>
<book>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Book_Info.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="notice.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="about.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="clustering.xml"/>
</book>

View File

@ -0,0 +1,4 @@
About ActiveMQ
==============
What is ActiveMQ?

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_Design_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="about">
<title>About ActiveMQ</title>
<para>What is ActiveMQ?</para>
</chapter>

View File

@ -0,0 +1,23 @@
Getting Started
===============
This chapter discusses the architecture behind clustering
Discovery
=========
Discovery is done in 2 steps, initial discovery where the server locates
another node in the cluster and topology discovery where the node finds
out about all other nodes in the cluster
Initial Discovery
-----------------
blah blah blah, UDP, static connectors etc etc
Topology Discovery
------------------
blah blah blah, topology etc
![ActiveMQ topology-update.jpg](images/topology-update.jpg)

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_Design_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="introduction">
<title>Getting Started</title>
<para>This chapter discusses the architecture behind clustering</para>
<section>
<title>Discovery</title>
<para>Discovery is done in 2 steps, initial discovery where the server locates another node in the cluster and
topology discovery where the node finds out about all other nodes in the cluster</para>
<section>
<title>Initial Discovery</title>
<para>blah blah blah, UDP, static connectors etc etc</para>
</section>
<section>
<title>Topology Discovery</title>
<para>blah blah blah, topology etc</para>
<para>
<graphic fileref="images/topology-update.jpg" align="center" format="JPEG" scale="30"/>
</para>
</section>
</section>
</chapter>

View File

@ -0,0 +1,17 @@
Legal Notice
============
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. The
ASF licenses this file to You under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,41 +0,0 @@
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_Design_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="notice">
<title>Legal Notice</title>
<para>Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at</para>
<para></para>
<para>http://www.apache.org/licenses/LICENSE-2.0</para>
<para></para>
<para>Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.</para>
</chapter>

View File

@ -1,310 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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>org.jboss.project</groupId>
<artifactId>${docname}-${translation}</artifactId>
<version>1.0</version>
<packaging>jdocbook</packaging>
<name>${bookname}-(${translation})</name>
<properties>
<translation>en</translation>
<docname>ActiveMQ_Design_Guide</docname>
<bookname>ActiveMQ Design Guide</bookname>
</properties>
<repositories>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<!--pluginRepository>
<id>jboss-snapshot-repository-group</id>
<name>JBoss Snapshot Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/snapshot/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository-->
</pluginRepositories>
<profiles>
<!-- mvn compile -->
<profile>
<id>all</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<configuration>
<formats>
<format>
<formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
<finalName>${docname}.pdf</finalName>
</format>
<format>
<formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
<format>
<formatName>html_single</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
</formats>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- mvn compile -Phtml -->
<profile>
<id>html</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<configuration>
<formats>
<format>
<formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
</formats>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- mvn compile -Phtml-single -->
<profile>
<id>html-single</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
</profile>
<!-- mvn compile -Ppdf -->
<profile>
<id>pdf</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.1.0</version>
<extensions>true</extensions>
<configuration>
<formats>
<format>
<formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
<finalName>${docname}.pdf</finalName>
</format>
</formats>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<dependencies>
<dependency>
<groupId>org.jboss.pressgang</groupId>
<artifactId>pressgang-xslt</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jbossorg-jdocbook-style</artifactId>
<version>1.1.1</version>
<type>jdocbook-style</type>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>${project.basedir}</sourceDirectory>
<sourceDocumentName>${docname}.xml</sourceDocumentName>
<masterTranslation>en</masterTranslation>
<imageResource>
<directory>${project.basedir}/en</directory>
<includes>
<include>images/*.png</include>
<include>images/*.jpg</include>
</includes>
</imageResource>
<formats>
<format>
<formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
<finalName>${pdf.name}</finalName>
</format>
<format>
<formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
<format>
<formatName>html_single</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
</formats>
<options>
<xincludeSupported>true</xincludeSupported>
<xmlTransformerType>saxon</xmlTransformerType>
<docbookVersion>1.72.0</docbookVersion>
<localeSeparator>-</localeSeparator>
<transformerParameters>
<property>
<name>javax.xml.parsers.DocumentBuilderFactory</name>
<value>org.apache.xerces.jaxp.DocumentBuilderFactoryImpl</value>
</property>
<property>
<name>javax.xml.parsers.SAXParserFactory</name>
<value>org.apache.xerces.jaxp.SAXParserFactoryImpl</value>
</property>
</transformerParameters>
</options>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!--<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<dependencies>
<dependency>
<groupId>org.jboss.pressgang</groupId>
<artifactId>pressgang-xslt</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jbossorg-jdocbook-style</artifactId>
<version>1.1.1</version>
<type>jdocbook-style</type>
</dependency>
</dependencies>
<configuration>
<sourceDocumentName>${docname}.xml</sourceDocumentName>
<sourceDirectory>.</sourceDirectory>
<imageResource>
<directory>${translation}</directory>
<includes>
<include>images/*</include>
</includes>
</imageResource>
<options>
<xincludeSupported>true</xincludeSupported>
<xmlTransformerType>saxon</xmlTransformerType>
<transformerParameters>
<property>
<name>javax.xml.parsers.DocumentBuilderFactory</name>
<value>org.apache.xerces.jaxp.DocumentBuilderFactoryImpl</value>
</property>
<property>
<name>javax.xml.parsers.SAXParserFactory</name>
<value>org.apache.xerces.jaxp.SAXParserFactoryImpl</value>
</property>
</transformerParameters>
</options>
</configuration>
</plugin>
</plugins>
</build>-->
</project>

Binary file not shown.

View File

@ -1,35 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_EAP_Manual.ent">
%BOOK_ENTITIES;
]>
<authorgroup>
<author>
<firstname>Andy</firstname>
<surname>Taylor</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Core Developer</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
<email>ataylor@redhat.com</email>
</author>
</authorgroup>

View File

@ -1,49 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- This document was created with Syntext Serna Free. -->
<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_EAP_Manual.ent">
%BOOK_ENTITIES;
]>
<bookinfo id="ActiveMQ_EAP_Manual">
<title>ActiveMQ Eap Manual</title>
<subtitle>Putting the buzz in messaging</subtitle>
<productname>ActiveMQ</productname>
<edition>2.1.0</edition>
<pubsnumber>1</pubsnumber>
<abstract>
<para>This is a guide to using ActiveMQ within EAP</para>
</abstract>
<corpauthor>
<inlinemediaobject>
<imageobject>
<imagedata fileref="images/hornetQ_logo_600px.png" format="PNG"/>
</imageobject>
<textobject>
<phrase>ActiveMQ Logo</phrase>
</textobject>
</inlinemediaobject>
</corpauthor>
<copyright>
<year>&YEAR;</year>
<holder>&HOLDER;</holder>
</copyright>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml"/>
</bookinfo>

View File

@ -1,7 +0,0 @@
<!ENTITY PRODUCT "ActiveMQ">
<!ENTITY BOOKID "ActiveMQ_EAP_Manual">
<!ENTITY YEAR "2011">
<!ENTITY HOLDER "Red Hat Inc.">
<!ENTITY semi ";">

View File

@ -1,29 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- This document was created with Syntext Serna Free. -->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_EAP_Manual.ent">
%BOOK_ENTITIES;
]>
<book>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Book_Info.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="clusters.xml"/>
</book>

View File

@ -1,573 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<chapter id="clusters">
<title>ActiveMQ and EAP Cluster Configuration</title>
<section>
<title>Configuring Failover</title>
<para>
This chapter explains how to configure ActiveMQ within EAP with live backup-groups. Currently in this version
ActiveMQ only supports shared store for backup nodes so we assume that in the rest of this chapter.
</para>
<para>There are 2 main ways to configure ActiveMQ servers to have a backup server:</para>
<itemizedlist>
<listitem>
<para>Colocated. This is when an EAP instance has both a live and backup(s) running.</para>
</listitem>
<listitem>
<para>Dedicated. This is when an EAP instance has either a live or backup running but never both.</para>
</listitem>
</itemizedlist>
<section>
<title>Colocated Live and Backup in Symmetrical cluster</title>
<para>
The colocated symmetrical topology will be the most widely used topology, this is where an EAP instance has
a live node running plus 1 or more backup node. Each backup node will belong to a live node on another EAP
instance. In a simple cluster of 2
EAP instances this would mean that each EAP instance would have a live server and 1 backup server as in
diagram1.
</para>
<para>
<graphic fileref="images/simple-colocated.jpg" align="center" format="jpg" scale="30"/>
</para>
<para>
Here the continuous lines show before failover and the dotted lines show the state of the cluster after
failover has occurred. To start with the 2 live servers are connected forming a cluster with each live server
connected to its local applications (via JCA). Also remote clients are connected to the live servers. After
failover the backup connects to the still available live server (which happens to be in the same vm) and takes
over as the live server in the cluster. Any remote clients also failover.
</para>
<para>
One thing to mention is that in that depending on what consumers/producers and MDB's etc are available messages
will be distributed between the nodes to make sure that all clients are satisfied from a JMS perspective. That is
if a producer is sending messages to a queue on a backup server that has no consumers, the messages will be
distributed to a live node elsewhere.
</para>
<para>
The following diagram is slightly more complex but shows the same configuration with 3 servers. Note that the
cluster connections ave been removed to make the configuration clearer but in reality all live servers will
form a cluster.
</para>
<para>
<graphic fileref="images/simple-colocated2.jpg" align="center" format="jpg" scale="30"/>
</para>
<para>
With more than 2 servers it is up to the user as to how many backups per live server are configured, you can
have
as many backups as required but usually 1 would suffice. In 3 node topology you may have each EAP instance
configured
with 2 backups in a 4 node 3 backups and so on. The following diagram demonstrates this.
</para>
<para>
<graphic fileref="images/simple-colocated3.jpg" align="center" format="jpg" scale="30"/>
</para>
<section>
<title>Configuration</title>
<section>
<title>Live Server Configuration</title>
<para>
First let's start with the configuration of the live server, we will use the EAP 'all' configuration as
our starting point. Since this version only supports shared store for failover we need to configure
this in the
<literal>activemq-configuration.xml</literal>
file like so:
</para>
<programlisting>
&lt;shared-store>true&lt;/shared-store>
</programlisting>
<para>
Obviously this means that the location of the journal files etc will have to be configured to be some
where
where
this lives backup can access. You may change the lives configuration in
<literal>activemq-configuration.xml</literal>
to
something like:
</para>
<programlisting>
&lt;large-messages-directory>/media/shared/data/large-messages&lt;/large-messages-directory>
&lt;bindings-directory>/media/shared/data/bindings&lt;/bindings-directory>
&lt;journal-directory>/media/shared/data/journal&lt;/journal-directory>
&lt;paging-directory>/media/shared/data/paging&lt;/paging-directory>
</programlisting>
<para>
How these paths are configured will of course depend on your network settings or file system.
</para>
<para>
Now we need to configure how remote JMS clients will behave if the server is shutdown in a normal
fashion.
By
default
Clients will not failover if the live server is shutdown. Depending on there connection factory
settings
they will either fail or try to reconnect to the live server.
</para>
<para>If you want clients to failover on a normal server shutdown the you must configure the
<literal>failover-on-shutdown</literal>
flag to true in the
<literal>activemq-configuration.xml</literal>
file like so:
</para>
<programlisting>
&lt;failover-on-shutdown>false&lt;/failover-on-shutdown>
</programlisting>
<para>Don't worry if you have this set to false (which is the default) but still want failover to occur,
simply
kill
the
server process directly or call
<literal>forceFailover</literal>
via jmx or the admin console on the core server object.
</para>
<para>We also need to configure the connection factories used by the client to be HA. This is done by
adding
certain attributes to the connection factories in<literal>activemq-jms.xml</literal>. Let's look at an
example:
</para>
<programlisting>
&lt;connection-factory name="NettyConnectionFactory">
&lt;xa>true&lt;/xa>
&lt;connectors>
&lt;connector-ref connector-name="netty"/>
&lt;/connectors>
&lt;entries>
&lt;entry name="/ConnectionFactory"/>
&lt;entry name="/XAConnectionFactory"/>
&lt;/entries>
&lt;ha>true&lt;/ha>
&lt;!-- Pause 1 second between connect attempts -->
&lt;retry-interval>1000&lt;/retry-interval>
&lt;!-- Multiply subsequent reconnect pauses by this multiplier. This can be used to
implement an exponential back-off. For our purposes we just set to 1.0 so each reconnect
pause is the same length -->
&lt;retry-interval-multiplier>1.0&lt;/retry-interval-multiplier>
&lt;!-- Try reconnecting an unlimited number of times (-1 means "unlimited") -->
&lt;reconnect-attempts>-1&lt;/reconnect-attempts>
&lt;/connection-factory>
</programlisting>
<para>We have added the following attributes to the connection factory used by the client:</para>
<itemizedlist>
<listitem>
<para>
<literal>ha</literal>
- This tells the client it support HA and must always be true for failover
to occur
</para>
</listitem>
<listitem>
<para>
<literal>retry-interval</literal>
- this is how long the client will wait after each unsuccessful
reconnect to the server
</para>
</listitem>
<listitem>
<para>
<literal>retry-interval-multiplier</literal>
- is used to configure an exponential back off for
reconnect attempts
</para>
</listitem>
<listitem>
<para>
<literal>reconnect-attempts</literal>
- how many reconnect attempts should a client make before failing,
-1 means unlimited.
</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Backup Server Configuration</title>
<para>
Now let's look at how to create and configure a backup server on the same eap instance. This is running
on the same eap instance as the live server from the previous chapter but is configured as the backup
for a live server running on a different eap instance.
</para>
<para>
The first thing to mention is that the backup only needs a <literal>activemq-jboss-beans.xml</literal>
and a <literal>activemq-configuration.xml</literal> configuration file. This is because any JMS components
are created from the Journal when the backup server becomes live.
</para>
<para>
Firstly we need to define a new ActiveMQ Server that EAP will deploy. We do this by creating a new
<literal>activemq-jboss-beans.xml</literal>
configuration. We will place this under a new directory
<literal>activemq-backup1</literal>
which will need creating
in the
<literal>deploy</literal>
directory but in reality it doesn't matter where this is put. This will look like:
</para>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;deployment xmlns="urn:jboss:bean-deployer:2.0">
&lt;!-- The core configuration -->
&lt;bean name="BackupConfiguration" class="org.apache.activemq.core.config.impl.FileConfiguration">
&lt;property
name="configurationUrl">${jboss.server.home.url}/deploy/activemq-backup1/activemq-configuration.xml&lt;/property>
&lt;/bean>
&lt;!-- The core server -->
&lt;bean name="BackupActiveMQServer" class="org.apache.activemq.core.server.impl.ActiveMQServerImpl">
&lt;constructor>
&lt;parameter>
&lt;inject bean="BackupConfiguration"/>
&lt;/parameter>
&lt;parameter>
&lt;inject bean="MBeanServer"/>
&lt;/parameter>
&lt;parameter>
&lt;inject bean="ActiveMQSecurityManager"/>
&lt;/parameter>
&lt;/constructor>
&lt;start ignored="true"/>
&lt;stop ignored="true"/>
&lt;/bean>
&lt;!-- The JMS server -->
&lt;bean name="BackupJMSServerManager" class="org.apache.activemq.jms.server.impl.JMSServerManagerImpl">
&lt;constructor>
&lt;parameter>
&lt;inject bean="BackupActiveMQServer"/>
&lt;/parameter>
&lt;/constructor>
&lt;/bean>
&lt;/deployment>
</programlisting>
<para>
The first thing to notice is the BackupConfiguration bean. This is configured to pick up the
configuration
for
the
server which we will place in the same directory.
</para>
<para>
After that we just configure a new ActiveMQ Server and JMS server.
</para>
<note>
<para>
Notice that the names of the beans have been changed from that of the live servers configuration.
This
is
so
there is no clash. Obviously if you add more backup servers you will need to rename those as well,
backup1,
backup2 etc.
</para>
</note>
<para>
Now let's add the server configuration in
<literal>activemq-configuration.xml</literal>
and add it to the same directory
<literal>deploy/activemq-backup1</literal>
and configure it like so:
</para>
<programlisting>
&lt;configuration xmlns="urn:activemq"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:activemq /schema/activemq-configuration.xsd">
&lt;jmx-domain>org.apache.activemq.backup1&lt;/jmx-domain>
&lt;clustered>true&lt;/clustered>
&lt;backup>true&lt;/backup>
&lt;shared-store>true&lt;/shared-store>
&lt;allow-failback>true&lt;/allow-failback>
&lt;bindings-directory>/media/shared/data/activemq-backup/bindings&lt;/bindings-directory>
&lt;journal-directory>/media/shared/data/activemq-backup/journal&lt;/journal-directory>
&lt;journal-min-files>10&lt;/journal-min-files>
&lt;large-messages-directory>/media/shared/data/activemq-backup/largemessages&lt;/large-messages-directory>
&lt;paging-directory>/media/shared/data/activemq-backup/paging&lt;/paging-directory>
&lt;connectors>
&lt;connector name="netty-connector">
&lt;factory-class>org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory&lt;/factory-class>
&lt;param key="host" value="${jboss.bind.address:localhost}"/>
&lt;param key="port" value="${activemq.remoting.backup.netty.port:5446}"/>
&lt;/connector>
&lt;connector name="in-vm">
&lt;factory-class>org.apache.activemq.core.remoting.impl.invm.InVMConnectorFactory&lt;/factory-class>
&lt;param key="server-id" value="${activemq.server-id:0}"/>
&lt;/connector>
&lt;/connectors>
&lt;acceptors>
&lt;acceptor name="netty">
&lt;factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory&lt;/factory-class>
&lt;param key="host" value="${jboss.bind.address:localhost}"/>
&lt;param key="port" value="${activemq.remoting.backup.netty.port:5446}"/>
&lt;/acceptor>
&lt;/acceptors>
&lt;broadcast-groups>
&lt;broadcast-group name="bg-group1">
&lt;group-address>231.7.7.7&lt;/group-address>
&lt;group-port>9876&lt;/group-port>
&lt;broadcast-period>1000&lt;/broadcast-period>
&lt;connector-ref>netty-connector&lt;/connector-ref>
&lt;/broadcast-group>
&lt;/broadcast-groups>
&lt;discovery-groups>
&lt;discovery-group name="dg-group1">
&lt;group-address>231.7.7.7&lt;/group-address>
&lt;group-port>9876&lt;/group-port>
&lt;refresh-timeout>60000&lt;/refresh-timeout>
&lt;/discovery-group>
&lt;/discovery-groups>
&lt;cluster-connections>
&lt;cluster-connection name="my-cluster">
&lt;address>jms&lt;/address>
&lt;connector-ref>netty-connector&lt;/connector-ref>
&lt;discovery-group-ref discovery-group-name="dg-group1"/>
&lt;!--max hops defines how messages are redistributed, the default is 1 meaning only distribute to directly
connected nodes, to disable set to 0-->
&lt;!--&lt;max-hops>0&lt;/max-hops>-->
&lt;/cluster-connection>
&lt;/cluster-connections>
&lt;security-settings>
&lt;security-setting match="#">
&lt;permission type="createNonDurableQueue" roles="guest"/>
&lt;permission type="deleteNonDurableQueue" roles="guest"/>
&lt;permission type="consume" roles="guest"/>
&lt;permission type="send" roles="guest"/>
&lt;/security-setting>
&lt;/security-settings>
&lt;address-settings>
&lt;!--default for catch all-->
&lt;address-setting match="#">
&lt;dead-letter-address>jms.queue.DLQ&lt;/dead-letter-address>
&lt;expiry-address>jms.queue.ExpiryQueue&lt;/expiry-address>
&lt;redelivery-delay>0&lt;/redelivery-delay>
&lt;max-size-bytes>10485760&lt;/max-size-bytes>
&lt;message-counter-history-day-limit>10&lt;/message-counter-history-day-limit>
&lt;address-full-policy>BLOCK&lt;/address-full-policy>
&lt;/address-setting>
&lt;/address-settings>
&lt;/configuration>
</programlisting>
<para>
The second thing you can see is we have added a
<literal>jmx-domain</literal>
attribute, this is used when
adding objects, such as the ActiveMQ server and JMS server to jmx, we change this from the default
<literal>org.apache.activemq</literal>
to avoid naming clashes with the live server
</para>
<para>
The first important part of the configuration is to make sure that this server starts as a backup
server not
a live server, via the
<literal>backup</literal>
attribute.
</para>
<para>
After that we have the same cluster configuration as live, that is
<literal>clustered</literal>
is true and
<literal>shared-store</literal>
is true. However you can see we have added a new configuration element
<literal>allow-failback</literal>. When this is set to true then this backup server will automatically
stop
and fall back into backup node if failover occurs and the live server has become available. If false
then
the user will have to stop the server manually.
</para>
<para>
Next we can see the configuration for the journal location, as in the live configuration this must
point to
the same directory as this backup's live server.
</para>
<para>
Now we see the connectors configuration, we have 3 defined which are needed for the following
</para>
<itemizedlist>
<listitem>
<para>
<literal>netty-connector.</literal>
This is the connector used to connect to this backup server once live.
</para>
</listitem>
</itemizedlist>
<para>After that you will see the acceptors defined, This is the acceptor where clients will reconnect.
</para>
<para>
The Broadcast groups, Discovery group and cluster configurations are as per normal, details of these
can be found in the ActiveMQ user manual.
</para>
<note>
<para>notice the commented out <literal>max-hops</literal> in the cluster connection, set this to 0 if
you want to disable server side load balancing.</para>
</note>
<para>
When the backup becomes it will be not be servicing any JEE components on this eap instance. Instead any
existing messages will be redistributed around the cluster and new messages forwarded to and from the backup
to service any remote clients it has (if it has any).
</para>
</section>
<section>
<title>Configuring multiple backups</title>
<para>
In this instance we have assumed that there are only 2 nodes where each node has a backup for the other
node. However you may want to configure a server too have multiple backup nodes. For example you may want
3 nodes where each node has 2 backups, one for each of the other 2 live servers. For this you would simply
copy the backup configuration and make sure you do the following:
</para>
<itemizedlist>
<listitem>
<para>
Make sure that you give all the beans in the <literal>activemq-jboss-beans.xml</literal> configuration
file a unique name, i.e.
</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Running the shipped example</title>
<para>
EAP ships with an example configuration for this topology. Look under <literal>extras/activemq/resources/examples/symmetric-cluster-with-backups-colocated</literal>
and follow the read me
</para>
</section>
</section>
</section>
<section>
<title>Dedicated Live and Backup in Symmetrical cluster</title>
<para>
In reality the configuration for this is exactly the same as the backup server in the previous section, the only
difference is that a backup will reside on an eap instance of its own rather than colocated with another live server.
Of course this means that the eap instance is passive and not used until the backup comes live and is only
really useful for pure JMS applications.
</para>
<para>The following diagram shows a possible configuration for this:</para>
<para>
<graphic fileref="images/simple-dedicated.jpg" align="center" format="jpg" scale="30"/>
</para>
<para>
Here you can see how this works with remote JMS clients. Once failover occurs the ActiveMQ backup Server takes
running within another eap instance takes over as live.
</para>
<para>
This is fine with applications that are pure JMS and have no JMS components such as MDB's. If you are using
JMS components then there are 2 ways that this can be done. The first is shown in the following diagram:
</para>
<para>
<graphic fileref="images/simple-dedicated-jca.jpg" align="center" format="jpg" scale="30"/>
</para>
<para>
Because there is no live activemq server running by default in the eap instance running the backup server it
makes no sense to host any applications in it. However you can host applications on the server running the live
activemq server. If failure occurs to an live activemq server then remote jms clients will failover as previously
explained however what happens to any messages meant for or sent from JEE components. Well when the backup comes
live, messages will be distributed to and from the backup server over ActiveMQ cluster connections and handled
appropriately.
</para>
<para>
The second way to do this is to have both live and backup server remote form the eap instance as shown in the
following diagram.
</para>
<para>
<graphic fileref="images/simple-dedicated-jca-remote.jpg" align="center" format="jpg" scale="30"/>
</para>
<para>
Here you can see that all the Application (via JCA) will be serviced by a ActiveMQ server in its own eap instance.
</para>
<section>
<title>Configuration of dedicated Live and backup</title>
<para>
The live server configuration is exactly the same as in the previous example. The only difference of course
is that there is no backup in the eap instance.
</para>
<para>
For the backup server the <literal>activemq-configuration.xml</literal> is unchanged, however since there is
no live server we need to make sure that the <literal>activemq-jboss-beans.xml</literal> instantiates all
the beans needed. For this simply use the same configuration as in the live server changing only the
location of the <literal>activemq-configuration.xml</literal> parameter for the <literal>Configuration</literal>
bean.
</para>
<para>
As before there will be no <literal>activemq-jms.xml</literal> or <literal>jms-ds.xml</literal> configuration.
</para>
<para>
If you want both activemq servers to be in there own dedicated server where they are remote to applications,
as in the last diagram. Then simply edit the <literal>jms-ds.xml</literal> and change the following lines to
</para>
<programlisting>
&lt;config-property name="ConnectorClassName" type="java.lang.String">org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory&lt;/config-property>
&lt;config-property name="ConnectionParameters" type="java.lang.String">host=127.0.0.1;port=5446&lt;/config-property>
</programlisting>
<para>
This will change the outbound JCA connector, to configure the inbound connector for MDB's edit the
<literal>ra.xml</literal> config file and change the following parameters.
</para>
<programlisting>
&lt;config-property>
&lt;description>The transport type&lt;/description>
&lt;config-property-name>ConnectorClassName&lt;/config-property-name>
&lt;config-property-type>java.lang.String&lt;/config-property-type>
&lt;config-property-value>org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory&lt;/config-property-value>
&lt;/config-property>
&lt;config-property>
&lt;description>The transport configuration. These values must be in the form of key=val;key=val;&lt;/description>
&lt;config-property-name>ConnectionParameters&lt;/config-property-name>
&lt;config-property-type>java.lang.String&lt;/config-property-type>
&lt;config-property-value>host=127.0.0.1;port=5446&lt;/config-property-value>
&lt;/config-property>
</programlisting>
<para>
In both cases the host and port should match your live server. If you are using Discovery then set the
appropriate parameters for <literal>DiscoveryAddress</literal> and <literal>DiscoveryPort</literal> to match
your configured broadcast groups.
</para>
</section>
<section>
<title>Running the shipped example</title>
<para>
EAP ships with an example configuration for this topology. Look under
<literal>extras/activemq/resources/examples/cluster-with-dedicated-backup</literal>
and follow the read me
</para>
</section>
</section>
</section>
</chapter>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View File

@ -1,309 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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>org.jboss.project</groupId>
<artifactId>${docname}-${translation}</artifactId>
<version>1.0</version>
<packaging>jdocbook</packaging>
<name>${bookname}-(${translation})</name>
<properties>
<translation>en</translation>
<docname>ActiveMQ_EAP_Manual</docname>
<bookname>ActiveMQ EAP Manual</bookname>
</properties>
<repositories>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<!--pluginRepository>
<id>jboss-snapshot-repository-group</id>
<name>JBoss Snapshot Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/snapshot/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository-->
</pluginRepositories>
<profiles>
<!-- mvn compile -->
<profile>
<id>all</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<configuration>
<formats>
<format>
<formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
<finalName>${docname}.pdf</finalName>
</format>
<format>
<formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
<format>
<formatName>html_single</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
</formats>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- mvn compile -Phtml -->
<profile>
<id>html</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<configuration>
<formats>
<format>
<formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
</formats>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- mvn compile -Phtml-single -->
<profile>
<id>html-single</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
</profile>
<!-- mvn compile -Ppdf -->
<profile>
<id>pdf</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.1.0</version>
<extensions>true</extensions>
<configuration>
<formats>
<format>
<formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
<finalName>${docname}.pdf</finalName>
</format>
</formats>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<dependencies>
<dependency>
<groupId>org.jboss.pressgang</groupId>
<artifactId>pressgang-xslt</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jbossorg-jdocbook-style</artifactId>
<version>1.1.1</version>
<type>jdocbook-style</type>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>${project.basedir}</sourceDirectory>
<sourceDocumentName>${docname}.xml</sourceDocumentName>
<masterTranslation>en</masterTranslation>
<imageResource>
<directory>${project.basedir}/en</directory>
<includes>
<include>images/*.png</include>
</includes>
</imageResource>
<formats>
<format>
<formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
<finalName>${pdf.name}</finalName>
</format>
<format>
<formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
<format>
<formatName>html_single</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
</formats>
<options>
<xincludeSupported>true</xincludeSupported>
<xmlTransformerType>saxon</xmlTransformerType>
<docbookVersion>1.72.0</docbookVersion>
<localeSeparator>-</localeSeparator>
<transformerParameters>
<property>
<name>javax.xml.parsers.DocumentBuilderFactory</name>
<value>org.apache.xerces.jaxp.DocumentBuilderFactoryImpl</value>
</property>
<property>
<name>javax.xml.parsers.SAXParserFactory</name>
<value>org.apache.xerces.jaxp.SAXParserFactoryImpl</value>
</property>
</transformerParameters>
</options>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!--<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<dependencies>
<dependency>
<groupId>org.jboss.pressgang</groupId>
<artifactId>pressgang-xslt</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jbossorg-jdocbook-style</artifactId>
<version>1.1.1</version>
<type>jdocbook-style</type>
</dependency>
</dependencies>
<configuration>
<sourceDocumentName>${docname}.xml</sourceDocumentName>
<sourceDirectory>.</sourceDirectory>
<imageResource>
<directory>${translation}</directory>
<includes>
<include>images/*</include>
</includes>
</imageResource>
<options>
<xincludeSupported>true</xincludeSupported>
<xmlTransformerType>saxon</xmlTransformerType>
<transformerParameters>
<property>
<name>javax.xml.parsers.DocumentBuilderFactory</name>
<value>org.apache.xerces.jaxp.DocumentBuilderFactoryImpl</value>
</property>
<property>
<name>javax.xml.parsers.SAXParserFactory</name>
<value>org.apache.xerces.jaxp.SAXParserFactoryImpl</value>
</property>
</transformerParameters>
</options>
</configuration>
</plugin>
</plugins>
</build>-->
</project>

View File

@ -1,55 +0,0 @@
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pom</artifactId>
<version>6.0.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.activemq.docs</groupId>
<artifactId>activemq-docs</artifactId>
<packaging>pom</packaging>
<name>ActiveMQ6 Documentation</name>
<properties>
<skipLicenseCheck>true</skipLicenseCheck>
<skipStyleCheck>true</skipStyleCheck>
</properties>
<modules>
<module>user-manual</module>
<module>quickstart-guide</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,5 +0,0 @@
<!ENTITY PRODUCT "ActiveMQ">
<!ENTITY BOOKID "ActiveMQ_QuickStart_Guide">
<!ENTITY YEAR "2011">
<!ENTITY HOLDER "Red Hat Inc.">
<!ENTITY semi ";">

View File

@ -1,17 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<book>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Book_Info.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="notice.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="about.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="introduction.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="download.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="installation.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="running.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="examples.xml"/>
</book>

View File

@ -1,45 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<authorgroup>
<author>
<firstname>Clebert</firstname>
<surname>Suconic</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Project Lead</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
<email>csuconic@redhat.com</email>
</author>
<author>
<firstname>Andy</firstname>
<surname>Taylor</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Core Developer</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
<email>ataylor@redhat.com</email>
</author>
<author>
<firstname>Tim</firstname>
<surname>Fox</surname>
</author>
<author>
<firstname>Jeff</firstname>
<surname>Mesnil</surname>
</author>
<author>
<firstname>Howard</firstname>
<surname>Gao</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Core Developer</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
<email>ghoward@redhat.com</email>
</author>
</authorgroup>

View File

@ -1,31 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- This document was created with Syntext Serna Free. --><!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<bookinfo id="ActiveMQ_QuickStart_Guide">
<title>ActiveMQ QuickStart Guide</title>
<subtitle>Putting the buzz in messaging</subtitle>
<productname>ActiveMQ</productname>
<edition>2.1.0</edition>
<pubsnumber>1</pubsnumber>
<abstract>
<para>This Quickstart guide will help you get ActiveMQ up and running in a few minutes and will explain the basics needed
to get started.</para>
</abstract>
<corpauthor>
<inlinemediaobject>
<imageobject>
<imagedata fileref="images/hornetQ_logo_600px.png" format="PNG"/>
</imageobject>
<textobject>
<phrase>ActiveMQ Logo</phrase>
</textobject>
</inlinemediaobject>
</corpauthor>
<copyright>
<year>&YEAR;</year>
<holder>&HOLDER;</holder>
</copyright>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml"/>
</bookinfo>

View File

@ -0,0 +1,4 @@
ActiveMQ Quick Start Manual
====================
How to get started with ActiveMQ

View File

@ -0,0 +1,7 @@
* [Legal Notice](notice.md)
* [Introduction](introduction.md)
* [About](about.md)
* [Download](download.md)
* [Installation](installation.md)
* [Running](running.md)
* [Examples](examples.md)

View File

@ -0,0 +1,49 @@
About ActiveMQ
==============
What is ActiveMQ?
- ActiveMQ is an open source project to build a multi-protocol,
embeddable, very high performance, clustered, asynchronous messaging
system.
- For answers to more questions about what ActiveMQ is and what it
isn't please visit the [FAQs wiki
page](http://www.jboss.org/community/wiki/ActiveMQGeneralFAQs).
Why use ActiveMQ? Here are just a few of the reasons:
- 100% open source software. ActiveMQ is licenced using the Apache
Software License v2.0 to minimise barriers to adoption.
- ActiveMQ is designed with usability in mind.
- Written in Java. Runs on any platform with a Java 6+ runtime, that's
everything from Windows desktops to IBM mainframes.
- Amazing performance. Our class beating high performance journal
provides persistent messaging performance at rates normally seen for
non persistent messaging, our non persistent messaging performance
rocks the boat too.
- Full feature set. All the features you'd expect in any serious
messaging system, and others you won't find anywhere else.
- Elegant, clean-cut design with minimal third party dependencies. Run
ActiveMQ stand-alone, run it in integrated in your favourite JEE
application server, or run it embedded inside your own product. It's
up to you.
- Seamless high availability. We provide a HA solution with automatic
client failover so you can guarantee zero message loss or
duplication in event of server failure.
- Hugely flexible clustering. Create clusters of servers that know how
to load balance messages. Link geographically distributed clusters
over unreliable connections to form a global network. Configure
routing of messages in a highly flexible way.
- For a full list of features, please see the [features wiki
page](http://www.jboss.org/community/wiki/ActiveMQFeatures) .

View File

@ -1,83 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="about">
<title>About ActiveMQ</title>
<para>What is ActiveMQ?</para>
<itemizedlist>
<listitem>
<para>ActiveMQ is an open source project to build a multi-protocol, embeddable, very high
performance, clustered, asynchronous messaging system.</para>
</listitem>
<listitem>
<para>For answers to more questions about what ActiveMQ is and what it isn't please visit
the <ulink url="http://www.jboss.org/community/wiki/ActiveMQGeneralFAQs">FAQs wiki
page</ulink>.</para>
</listitem>
</itemizedlist>
<para>Why use ActiveMQ? Here are just a few of the reasons:</para>
<itemizedlist>
<listitem>
<para>100% open source software. ActiveMQ is licenced using the Apache Software License v2.0
to minimise barriers to adoption.</para>
</listitem>
<listitem>
<para>ActiveMQ is designed with usability in mind.</para>
</listitem>
<listitem>
<para>Written in Java. Runs on any platform with a Java 6+ runtime, that's everything
from Windows desktops to IBM mainframes.</para>
</listitem>
<listitem>
<para>Amazing performance. Our class beating high performance journal provides persistent
messaging performance at rates normally seen for non persistent messaging, our non
persistent messaging performance rocks the boat too.</para>
</listitem>
<listitem>
<para>Full feature set. All the features you'd expect in any serious messaging system,
and others you won't find anywhere else.</para>
</listitem>
<listitem>
<para>Elegant, clean-cut design with minimal third party dependencies. Run ActiveMQ
stand-alone, run it in integrated in your favourite JEE application server, or run
it embedded inside your own product. It's up to you.</para>
</listitem>
<listitem>
<para>Seamless high availability. We provide a HA solution with automatic client
failover so you can guarantee zero message loss or duplication in event of server
failure.</para>
</listitem>
<listitem>
<para>Hugely flexible clustering. Create clusters of servers that know how to load
balance messages. Link geographically distributed clusters over unreliable
connections to form a global network. Configure routing of messages in a highly
flexible way.</para>
</listitem>
<listitem>
<para>For a full list of features, please see the <ulink
url="http://www.jboss.org/community/wiki/ActiveMQFeatures">features wiki
page</ulink> .</para>
</listitem>
</itemizedlist>
</chapter>

View File

@ -0,0 +1,36 @@
Download
========
The official ActiveMQ project page is <http://activemq.org/>.
Software Download
=================
The software can be download from the Download
page:<http://activemq.org/downloads.html>
Project Information
===================
- Please take a look at our project
[wiki](http://www.jboss.org/community/wiki/ActiveMQ)
- If you have any user questions please use our [user
forum](https://community.jboss.org/en/activemq)
- If you have development related questions, please use our [developer
forum](http://www.jboss.org/index.html?module=bb&op=viewforum&f=313)
- Pop in and chat to us in our [IRC
channel](irc://irc.freenode.net:6667/activemq)
- Our project [blog](http://activemq.blogspot.com/)
- Follow us on [twitter](http://twitter.com/activemq)
- ActiveMQ Git repository is <https://github.com/activemq/activemq>
- All release tags are available from
<https://github.com/activemq/activemq/tags>

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="download">
<title>Download</title>
<para>The official ActiveMQ project page is <ulink url="http://activemq.org/"
>http://activemq.org/</ulink>.</para>
<section id="download.software">
<title>Software Download</title>
<para>The software can be download from the Download page:<ulink
url="http://activemq.org/downloads.html"
>http://activemq.org/downloads.html</ulink></para>
</section>
<section id="download.git">
<title>Project Information</title>
<para>
<itemizedlist>
<listitem>
<para>Please take a look at our project <ulink
url="http://www.jboss.org/community/wiki/ActiveMQ">wiki</ulink></para>
</listitem>
<listitem>
<para>If you have any user questions please use our <ulink
url="https://community.jboss.org/en/activemq">user
forum</ulink></para>
</listitem>
<listitem>
<para>If you have development related questions, please use our <ulink
url="http://www.jboss.org/index.html?module=bb&amp;op=viewforum&amp;f=313"
>developer forum</ulink></para>
</listitem>
<listitem>
<para>Pop in and chat to us in our <ulink url="irc://irc.freenode.net:6667/activemq"
>IRC channel</ulink></para>
</listitem>
<listitem>
<para>Our project <ulink url="http://activemq.blogspot.com/">blog</ulink></para>
</listitem>
<listitem>
<para>Follow us on <ulink url="http://twitter.com/activemq">twitter</ulink></para>
</listitem>
<listitem>
<para>ActiveMQ Git repository is <ulink
url="https://github.com/activemq/activemq"
>https://github.com/activemq/activemq</ulink></para>
</listitem>
<listitem>
<para>All release tags are available from <ulink
url="https://github.com/activemq/activemq/tags"
>https://github.com/activemq/activemq/tags</ulink></para>
</listitem>
</itemizedlist>
</para>
</section>
</chapter>

View File

@ -0,0 +1,314 @@
Running the Examples
====================
In the directory `examples` there are 2 sets of examples, these are
- JMS Examples - these demonstrate functionality while sending and
consumng JMS messages.
- Java EE Examples - these demonstrate application server integration,
e.g. MDBs, EJBs, Servlets, etc.
The JMS examples
================
The JMS Examples all follow the same format. Each examples is contained
in its own directory which contains the following.
- `pom.xml`
This is the Maven build file used to run the example
- `src` directory
This contains the source code for the example
- `resources/activemq/server0` configuration directory
This contains the configuration files needed to run the server for
the example. There may be multiple configuration directories
`server0`, `server1` etc for clustered examples etc.
Each example will start one or more stand-alone servers and stop them
after the example has completed.
As a quick start we'll run the queue example. For all other examples
refer to the main user manual.
Firstly open a Shell or a Command prompt and navigate to the
`examples/jms/queue` directory.
Type the command `mvn verify` and you should see the following output:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building ActiveMQ JMS Queue Example 2.3.0.BETA-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ activemq-jms-queue-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) @ activemq-jms-queue-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ activemq-jms-queue-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/andy/projects/activemq-master/examples/jms/queue/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.0:testCompile (default-testCompile) @ activemq-jms-queue-example ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.13:test (default-test) @ activemq-jms-queue-example ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ activemq-jms-queue-example ---
[INFO] Building jar: /home/andy/projects/activemq-master/examples/jms/queue/target/activemq-jms-queue-example-2.3.0.BETA-SNAPSHOT.jar
[INFO]
[INFO] >>> maven-source-plugin:2.2.1:jar (attach-sources) @ activemq-jms-queue-example >>>
[INFO]
[INFO] <<< maven-source-plugin:2.2.1:jar (attach-sources) @ activemq-jms-queue-example <<<
[INFO]
[INFO] --- maven-source-plugin:2.2.1:jar (attach-sources) @ activemq-jms-queue-example ---
[INFO] Building jar: /home/andy/projects/activemq-master/examples/jms/queue/target/activemq-jms-queue-example-2.3.0.BETA-SNAPSHOT-sources.jar
[INFO]
[INFO] >>> maven-source-plugin:2.2.1:jar (default) @ activemq-jms-queue-example >>>
[INFO]
[INFO] <<< maven-source-plugin:2.2.1:jar (default) @ activemq-jms-queue-example <<<
[INFO]
[INFO] --- maven-source-plugin:2.2.1:jar (default) @ activemq-jms-queue-example ---
[WARNING] Artifact org.apache.activemq.examples.jms:activemq-jms-queue-example:java-source:sources:2.3.0.BETA-SNAPSHOT already attached to project, ignoring duplicate
[INFO]
[INFO] --- activemq-maven-plugin:1.1.1-SNAPSHOT:start (start) @ activemq-jms-queue-example ---
[file:/home/andy/projects/activemq-master/examples/jms/queue/target/classes/activemq/server0/]
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.deployers.impl.FileConfigurationParser parseMainConfig
WARN: HQ222018: AIO was not located on this platform, it will fall back to using pure Java NIO. If your platform is Linux, install LibAIO to enable the AIO journal
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl start
INFO: HQ221000: live server is starting with configuration ActiveMQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/home/andy/projects/activemq-master/examples/jms/queue/target//server0/data/messaging/journal,bindingsDirectory=/home/andy/projects/activemq-master/examples/jms/queue/target//server0/data/messaging/bindings,largeMessagesDirectory=/home/andy/projects/activemq-master/examples/jms/queue/target//server0/data/messaging/largemessages,pagingDirectory=/home/andy/projects/activemq-master/examples/jms/queue/target//server0/data/messaging/paging)
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl$SharedStoreLiveActivation run
INFO: HQ221006: Waiting to obtain live lock
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.persistence.impl.journal.JournalStorageManager <init>
INFO: HQ221013: Using NIO Journal
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl initialisePart1
WARN: HQ222007: Security risk! ActiveMQ is running with the default cluster admin user and default password. Please see the ActiveMQ user guide, cluster chapter, for instructions on how to change this.
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.FileLockNodeManager startLiveNode
INFO: HQ221034: Waiting to obtain live lock
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.FileLockNodeManager startLiveNode
INFO: HQ221035: Live Server Obtained live lock
Apr 17, 2013 10:51:02 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl deployQueue
INFO: HQ221003: trying to deploy queue jms.queue.exampleQueue
Apr 17, 2013 10:51:02 AM org.apache.activemq.core.remoting.impl.netty.NettyAcceptor start
INFO: HQ221020: Started Netty Acceptor version 3.6.2.Final-c0d783c localhost:5445 for CORE protocol
Apr 17, 2013 10:51:02 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl$SharedStoreLiveActivation run
INFO: HQ221007: Server is now live
Apr 17, 2013 10:51:02 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl start
INFO: HQ221001: ActiveMQ Server version 2.3.0.SNAPSHOT (black'n'yellow, 123) [a57893ff-7783-11e2-9787-07ca142fc9f7]
[INFO]
[INFO] --- activemq-maven-plugin:1.1.1-SNAPSHOT:runClient (runClient) @ activemq-jms-queue-example ---
Apr 17, 2013 10:51:02 AM org.apache.activemq.common.example.ActiveMQExample getContext
INFO: using jnp://localhost:1099 for jndi
Sent message: This is a text message
Received message: This is a text message
example complete
#####################
### SUCCESS! ###
#####################
[INFO]
[INFO] --- activemq-maven-plugin:1.1.1-SNAPSHOT:stop (stop) @ activemq-jms-queue-example ---
Apr 17, 2013 10:51:03 AM org.apache.activemq.core.server.management.impl.ManagementServiceImpl stop
WARN: HQ222113: On ManagementService stop, there are 1 unexpected registered MBeans: [core.acceptor.netty-acceptor]
Apr 17, 2013 10:51:03 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl stop
INFO: HQ221002: ActiveMQ Server version 2.3.0.SNAPSHOT (black'n'yellow, 123) [a57893ff-7783-11e2-9787-07ca142fc9f7] stopped
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.428s
[INFO] Finished at: Wed Apr 17 10:51:03 BST 2013
[INFO] Final Memory: 11M/456M
[INFO] ------------------------------------------------------------------------
Congratulations! You have successfully run your first ActiveMQ example.
Try some of the others.
The Java EE Examples
====================
The Java EE Examples are examples that require a JEE application server
to run. They include MDB, Servlet, EJB examples etc. For this you will
need the JBoss Application Server 7.1.x installed and uses Arquillian to
run the example. How to do this is explained in the previous chapters.
We'll use the MDB example for the purposes of this guide. For the other
examples refer to the user guide. Before going any further ensure that
the JBoss Application Server is running.
The first thing we need to do is set the `JBOSS_HOME` environment
property to the location of the JBoss Application Server, in a Linux
shell this would be something like:
export JBOSS_HOME=/home/jbossas7.1/build/output/jboss-7.1.0
Yoy can then run the example via maven by running `mvn test`
In the shell window you should see something like the following output:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building ActiveMQ JEE MDB Example 2.3.0.BETA-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ activemq-jee-mdb-bmt-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) @ activemq-jee-mdb-bmt-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:copy-resources (as-node-0) @ activemq-jee-mdb-bmt-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1112 resources
[INFO] Copying 5 resources
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ activemq-jee-mdb-bmt-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.0:testCompile (default-testCompile) @ activemq-jee-mdb-bmt-example ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12:test (default-test) @ activemq-jee-mdb-bmt-example ---
[INFO] Surefire report directory: /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.apache.activemq.javaee.example.server.ExampleRunnerTest
log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Apr 17, 2013 10:58:04 AM org.jboss.arquillian.container.impl.MapObject populate
WARNING: Configuration contain properties not supported by the backing object org.jboss.as.arquillian.container.managed.ManagedContainerConfiguration
Unused property entries: {waitForPortsTimeoutInSeconds=8, waitForPorts=8787 9999}
Supported property names: [jbossHome, outputToConsole, enableAssertions, password, managementPort, javaHome, javaVmArguments, username, serverConfig, allowConnectingToRunningServer, managementAddress, startupTimeoutInSeconds, modulePath]
Apr 17, 2013 10:58:04 AM org.jboss.as.arquillian.container.managed.ManagedDeployableContainer startInternal
INFO: Starting container with: [/home/andy/devtools/jdk1.6.0_25//bin/java, -Djboss.inst=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0, -ea, -Djboss.home.dir=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0, -Dorg.jboss.boot.log.file=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/log/boot.log, -Dlogging.configuration=file:/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/configuration/logging.properties, -Djboss.modules.dir=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/modules, -Djboss.bundles.dir=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/bundles, -jar, /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/jboss-modules.jar, -mp, /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/modules, -jaxpmodule, javax.xml.jaxp-provider, org.jboss.as.standalone, -server-config, standalone-example.xml]
10:58:04,525 INFO [org.jboss.modules] JBoss Modules version 1.1.1.GA
10:58:04,664 INFO [org.jboss.msc] JBoss MSC version 1.0.2.GA
10:58:04,703 INFO [org.jboss.as] JBAS015899: JBoss AS 7.1.1.Final "Brontes" starting
10:58:05,492 INFO [org.xnio] XNIO Version 3.0.3.GA
10:58:05,494 INFO [org.jboss.as.server] JBAS015888: Creating http management service using socket-binding (management-http)
10:58:05,502 INFO [org.xnio.nio] XNIO NIO Implementation Version 3.0.3.GA
10:58:05,509 INFO [org.jboss.remoting] JBoss Remoting version 3.2.3.GA
10:58:05,527 INFO [org.jboss.as.logging] JBAS011502: Removing bootstrap log handlers
10:58:05,530 INFO [org.jboss.as.configadmin] (ServerService Thread Pool -- 32) JBAS016200: Activating ConfigAdmin Subsystem
10:58:05,560 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 37) JBAS010280: Activating Infinispan subsystem.
10:58:05,562 INFO [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 33) JBAS010403: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3)
10:58:05,573 INFO [org.jboss.as.jacorb] (ServerService Thread Pool -- 38) JBAS016300: Activating JacORB Subsystem
10:58:05,595 INFO [org.jboss.as.connector] (MSC service thread 1-12) JBAS010408: Starting JCA Subsystem (JBoss IronJacamar 1.0.9.Final)
10:58:05,612 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 48) JBAS011800: Activating Naming Subsystem
10:58:05,625 INFO [org.jboss.as.osgi] (ServerService Thread Pool -- 49) JBAS011940: Activating OSGi Subsystem
10:58:05,649 INFO [org.jboss.as.security] (ServerService Thread Pool -- 54) JBAS013101: Activating Security Subsystem
10:58:05,657 INFO [org.jboss.as.naming] (MSC service thread 1-8) JBAS011802: Starting Naming Service
10:58:05,663 INFO [org.jboss.as.mail.extension] (MSC service thread 1-16) JBAS015400: Bound mail session [java:jboss/mail/Default]
10:58:05,675 INFO [org.jboss.as.security] (MSC service thread 1-14) JBAS013100: Current PicketBox version=4.0.7.Final
10:58:05,683 INFO [org.jboss.as.webservices] (ServerService Thread Pool -- 58) JBAS015537: Activating WebServices Extension
10:58:05,705 INFO [org.jboss.jaxr] (MSC service thread 1-8) JBAS014000: Started JAXR subsystem, binding JAXR connection factory into JNDI as: java:jboss/jaxr/ConnectionFactory
10:58:05,831 INFO [org.jboss.ws.common.management.AbstractServerConfig] (MSC service thread 1-4) JBoss Web Services - Stack CXF Server 4.0.2.GA
10:58:05,943 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-6) Starting Coyote HTTP/1.1 on http-localhost.localdomain-127.0.0.1-8080
10:58:05,966 INFO [org.jboss.as.jacorb] (MSC service thread 1-2) JBAS016330: CORBA ORB Service started
10:58:05,988 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-11) live server is starting with configuration ActiveMQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messagingjournal,bindingsDirectory=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messagingbindings,largeMessagesDirectory=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messaginglargemessages,pagingDirectory=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messagingpaging)
10:58:05,996 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-11) Waiting to obtain live lock
10:58:06,037 INFO [org.apache.activemq.core.persistence.impl.journal.JournalStorageManager] (MSC service thread 1-11) Using AIO Journal
10:58:06,122 INFO [org.jboss.as.jacorb] (MSC service thread 1-14) JBAS016328: CORBA Naming Service started
10:58:06,184 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-7) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS]
10:58:06,204 INFO [org.apache.activemq.core.server.impl.AIOFileLockNodeManager] (MSC service thread 1-11) Waiting to obtain live lock
10:58:06,205 INFO [org.apache.activemq.core.server.impl.AIOFileLockNodeManager] (MSC service thread 1-11) Live Server Obtained live lock
10:58:06,434 INFO [org.jboss.as.remoting] (MSC service thread 1-2) JBAS017100: Listening on localhost.localdomain/127.0.0.1:4447
10:58:06,434 INFO [org.jboss.as.remoting] (MSC service thread 1-15) JBAS017100: Listening on /127.0.0.1:9999
10:58:06,436 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-16) JBAS015012: Started FileSystemDeploymentService for directory /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/deployments
10:58:08,790 INFO [org.apache.activemq.core.remoting.impl.netty.NettyAcceptor] (MSC service thread 1-11) Started Netty Acceptor version 3.2.5.Final-a96d88c localhost.localdomain:5445 for CORE protocol
10:58:08,793 INFO [org.apache.activemq.core.remoting.impl.netty.NettyAcceptor] (MSC service thread 1-11) Started Netty Acceptor version 3.2.5.Final-a96d88c localhost.localdomain:5455 for CORE protocol
10:58:08,795 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-11) Server is now live
10:58:08,797 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-11) ActiveMQ Server version 2.2.13.Final (HQ_2_2_13_FINAL_AS7, 122) [5c499e88-9c63-11e2-bfa3-fe5400591699]) started
10:58:08,822 INFO [org.jboss.as.messaging] (MSC service thread 1-4) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/RemoteConnectionFactory
10:58:08,824 INFO [org.jboss.as.messaging] (MSC service thread 1-4) JBAS011601: Bound messaging object to jndi name java:/RemoteConnectionFactory
10:58:08,825 INFO [org.jboss.as.messaging] (MSC service thread 1-10) JBAS011601: Bound messaging object to jndi name java:/ConnectionFactory
10:58:08,830 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-3) trying to deploy queue jms.queue.testQueue
10:58:08,836 INFO [org.jboss.as.messaging] (MSC service thread 1-3) JBAS011601: Bound messaging object to jndi name java:/queue/test
10:58:08,840 INFO [org.jboss.as.messaging] (MSC service thread 1-3) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/queues/testQueue
10:58:08,859 INFO [org.jboss.as.deployment.connector] (MSC service thread 1-9) JBAS010406: Registered connection factory java:/JmsXA
10:58:08,866 INFO [org.apache.activemq.ra.ActiveMQResourceAdapter] (MSC service thread 1-9) ActiveMQ resource adaptor started
10:58:08,867 INFO [org.jboss.as.connector.services.ResourceAdapterActivatorService$ResourceAdapterActivator] (MSC service thread 1-9) IJ020002: Deployed: file://RaActivatoractivemq-ra
10:58:08,870 INFO [org.jboss.as.deployment.connector] (MSC service thread 1-5) JBAS010401: Bound JCA ConnectionFactory [java:/JmsXA]
10:58:08,898 INFO [org.jboss.as.server.deployment] (MSC service thread 1-10) JBAS015876: Starting deployment of "ONT001-1.0.war"
10:58:09,146 INFO [org.jboss.wsf.stack.cxf.metadata.MetadataBuilder] (MSC service thread 1-1) Add Service
id=com.hpm.webservices.BasicWSImpl
address=http://localhost:8080/hpm/BasicWService
implementor=com.hpm.webservices.BasicWSImpl
invoker=org.jboss.wsf.stack.cxf.JBossWSInvoker
serviceName={http://ont001-hpm.rhcloud.com/BasicWS}BasicWService
portName={http://ont001-hpm.rhcloud.com/BasicWS}BasicWS
wsdlLocation=null
mtomEnabled=false
10:58:09,361 INFO [org.apache.cxf.service.factory.ReflectionServiceFactoryBean] (MSC service thread 1-1) Creating Service {http://ont001-hpm.rhcloud.com/BasicWS}BasicWService from WSDL: WEB-INF/wsdl/BasicWService.wsdl
10:58:09,517 INFO [org.jboss.wsf.stack.cxf.transport.AddressRewritingEndpointInfo] (MSC service thread 1-1) Setting new service endpoint address in wsdl: http://ONT001-HPM.rhcloud.com:80/BasicWService
10:58:09,656 INFO [org.jboss.wsf.stack.cxf.transport.AddressRewritingEndpointInfo] (MSC service thread 1-1) Setting new service endpoint address in wsdl: http://localhost:8080/hpm/BasicWService
10:58:09,688 INFO [org.apache.cxf.endpoint.ServerImpl] (MSC service thread 1-1) Setting the server's publish address to be http://localhost:8080/hpm/BasicWService
10:58:09,729 INFO [org.jboss.wsf.stack.cxf.deployment.WSDLFilePublisher] (MSC service thread 1-1) WSDL published to: file:/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/wsdl/ONT001-1.0.war/BasicWService.wsdl
10:58:09,735 INFO [org.jboss.as.webservices] (MSC service thread 1-11) JBAS015539: Starting service jboss.ws.port-component-link
10:58:09,748 INFO [org.jboss.as.webservices] (MSC service thread 1-10) JBAS015539: Starting service jboss.ws.endpoint."ONT001-1.0.war"."com.hpm.webservices.BasicWSImpl"
10:58:09,753 INFO [org.jboss.ws.common.management.DefaultEndpointRegistry] (MSC service thread 1-10) register: jboss.ws:context=hpm,endpoint=com.hpm.webservices.BasicWSImpl
10:58:09,829 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /hpm
10:58:09,834 INFO [org.jboss.as] (MSC service thread 1-7) JBAS015951: Admin console listening on http://127.0.0.1:9990
10:58:09,835 INFO [org.jboss.as] (MSC service thread 1-7) JBAS015874: JBoss AS 7.1.1.Final "Brontes" started in 5506ms - Started 216 of 296 services (79 services are passive or on-demand)
10:58:09,979 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "ONT001-1.0.war"
mdb.jar:
/org/
/org.apache.activemq/
/org.apache.activemq/javaee/
/org.apache.activemq/javaee/example/
/org.apache.activemq/javaee/example/server/
/org.apache.activemq/javaee/example/server/MDB_BMTExample.class
10:58:11,612 INFO [org.jboss.as.repository] (management-handler-thread - 2) JBAS014900: Content added at location /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/f0/e2d589ab9490193e109c8bc833f725c87defae/content
10:58:11,620 INFO [org.jboss.as.server.deployment] (MSC service thread 1-8) JBAS015876: Starting deployment of "arquillian-service"
10:58:11,811 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.jmx:main") which may be changed or removed in future versions without notice.
10:58:11,812 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.server:main") which may be changed or removed in future versions without notice.
10:58:11,813 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.osgi:main") which may be changed or removed in future versions without notice.
10:58:11,815 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.jandex:main") which may be changed or removed in future versions without notice.
10:58:11,817 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.osgi.framework:main") which may be changed or removed in future versions without notice.
10:58:11,953 INFO [org.jboss.as.server] (management-handler-thread - 2) JBAS018559: Deployed "arquillian-service"
10:58:12,328 INFO [org.jboss.as.repository] (management-handler-thread - 3) JBAS014900: Content added at location /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/59/7dcdb0f420ed57aea638b2599f7a86eecf6c85/content
10:58:12,333 INFO [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015876: Starting deployment of "mdb.jar"
10:58:12,401 INFO [org.jboss.as.arquillian] (MSC service thread 1-14) Arquillian deployment detected: ArquillianConfig[service=jboss.arquillian.config."mdb.jar",unit=mdb.jar,tests=[org.apache.activemq.javaee.example.server.ExampleRunnerTest]]
10:58:12,418 INFO [org.jboss.as.ejb3] (MSC service thread 1-15) JBAS014142: Started message driven bean 'MDB_BMTExample' with 'activemq-ra' resource adapter
10:58:12,562 INFO [org.jboss.as.server] (management-handler-thread - 3) JBAS018559: Deployed "mdb.jar"
Sent message: This is a text message
10:58:13,229 INFO [org.jboss.as.naming] (Remoting "localhost" task-3) JBAS011806: Channel end notification received, closing channel Channel ID 57be4578 (inbound) of Remoting connection 3ac552d5 to /127.0.0.1:58571
10:58:13,255 INFO [stdout] (Thread-0 (ActiveMQ-client-global-threads-1402019528)) message This is a text message received
10:58:13,257 INFO [stdout] (Thread-0 (ActiveMQ-client-global-threads-1402019528)) we're in the middle of a transaction: org.jboss.tm.usertx.client.ServerVMClientUserTransaction@6b04d3c8
10:58:14,292 INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015877: Stopped deployment mdb.jar in 33ms
10:58:14,413 INFO [org.jboss.as.repository] (management-handler-thread - 1) JBAS014901: Content removed from location /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/59/7dcdb0f420ed57aea638b2599f7a86eecf6c85/content
10:58:14,415 INFO [org.jboss.as.server] (management-handler-thread - 1) JBAS018558: Undeployed "mdb.jar"
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.609 sec
10:58:14,436 INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015877: Stopped deployment arquillian-service in 6ms
10:58:14,530 INFO [org.jboss.as.repository] (management-handler-thread - 2) JBAS014901: Content removed from location /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/f0/e2d589ab9490193e109c8bc833f725c87defae/content
10:58:14,532 INFO [org.jboss.as.server] (management-handler-thread - 2) JBAS018558: Undeployed "arquillian-service"
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.441s
[INFO] Finished at: Wed Apr 17 10:58:16 BST 2013
[INFO] Final Memory: 19M/361M
[INFO] ------------------------------------------------------------------------
Congratulations! you have successfully deployed and run a Java EE
example.

View File

@ -1,329 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="examples">
<title>Running the Examples</title>
<para>In the directory <literal>examples</literal> there are 2 sets of examples, these are </para>
<itemizedlist>
<listitem>
<para>JMS Examples - these demonstrate functionality while sending and consumng JMS
messages.</para>
</listitem>
<listitem>
<para>Java EE Examples - these demonstrate application server integration, e.g. MDBs, EJBs,
Servlets, etc.</para>
</listitem>
</itemizedlist>
<section id="examples.jms">
<title>The JMS examples</title>
<para>The JMS Examples all follow the same format. Each examples is contained in its own
directory which contains the following.</para>
<itemizedlist>
<listitem>
<para><literal>pom.xml</literal></para>
<para>This is the Maven build file used to run the example</para>
</listitem>
<listitem>
<para><literal>src</literal> directory</para>
<para>This contains the source code for the example</para>
</listitem>
<listitem>
<para><literal>resources/activemq/server0</literal> configuration directory</para>
<para>This contains the configuration files needed to run the server for the example.
There may be multiple configuration directories <literal>server0</literal>, <literal
>server1</literal> etc for clustered examples etc.</para>
</listitem>
</itemizedlist>
<para>Each example will start one or more stand-alone servers and stop them after the example
has completed.</para>
<para>As a quick start we'll run the queue example. For all other examples refer to the main
user manual.</para>
<para>Firstly open a Shell or a Command prompt and navigate to the <literal
>examples/jms/queue</literal> directory.</para>
<para>Type the command <literal>mvn verify</literal> and you should see the following output:</para>
<programlisting>
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building ActiveMQ JMS Queue Example 2.3.0.BETA-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ activemq-jms-queue-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) @ activemq-jms-queue-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ activemq-jms-queue-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/andy/projects/activemq-master/examples/jms/queue/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.0:testCompile (default-testCompile) @ activemq-jms-queue-example ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.13:test (default-test) @ activemq-jms-queue-example ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ activemq-jms-queue-example ---
[INFO] Building jar: /home/andy/projects/activemq-master/examples/jms/queue/target/activemq-jms-queue-example-2.3.0.BETA-SNAPSHOT.jar
[INFO]
[INFO] >>> maven-source-plugin:2.2.1:jar (attach-sources) @ activemq-jms-queue-example >>>
[INFO]
[INFO] &lt;&lt;&lt; maven-source-plugin:2.2.1:jar (attach-sources) @ activemq-jms-queue-example &lt;&lt;&lt;
[INFO]
[INFO] --- maven-source-plugin:2.2.1:jar (attach-sources) @ activemq-jms-queue-example ---
[INFO] Building jar: /home/andy/projects/activemq-master/examples/jms/queue/target/activemq-jms-queue-example-2.3.0.BETA-SNAPSHOT-sources.jar
[INFO]
[INFO] >>> maven-source-plugin:2.2.1:jar (default) @ activemq-jms-queue-example >>>
[INFO]
[INFO] &lt;&lt;&lt; maven-source-plugin:2.2.1:jar (default) @ activemq-jms-queue-example &lt;&lt;&lt;
[INFO]
[INFO] --- maven-source-plugin:2.2.1:jar (default) @ activemq-jms-queue-example ---
[WARNING] Artifact org.apache.activemq.examples.jms:activemq-jms-queue-example:java-source:sources:2.3.0.BETA-SNAPSHOT already attached to project, ignoring duplicate
[INFO]
[INFO] --- activemq-maven-plugin:1.1.1-SNAPSHOT:start (start) @ activemq-jms-queue-example ---
[file:/home/andy/projects/activemq-master/examples/jms/queue/target/classes/activemq/server0/]
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.deployers.impl.FileConfigurationParser parseMainConfig
WARN: HQ222018: AIO was not located on this platform, it will fall back to using pure Java NIO. If your platform is Linux, install LibAIO to enable the AIO journal
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl start
INFO: HQ221000: live server is starting with configuration ActiveMQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/home/andy/projects/activemq-master/examples/jms/queue/target//server0/data/messaging/journal,bindingsDirectory=/home/andy/projects/activemq-master/examples/jms/queue/target//server0/data/messaging/bindings,largeMessagesDirectory=/home/andy/projects/activemq-master/examples/jms/queue/target//server0/data/messaging/largemessages,pagingDirectory=/home/andy/projects/activemq-master/examples/jms/queue/target//server0/data/messaging/paging)
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl$SharedStoreLiveActivation run
INFO: HQ221006: Waiting to obtain live lock
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.persistence.impl.journal.JournalStorageManager &lt;init>
INFO: HQ221013: Using NIO Journal
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl initialisePart1
WARN: HQ222007: Security risk! ActiveMQ is running with the default cluster admin user and default password. Please see the ActiveMQ user guide, cluster chapter, for instructions on how to change this.
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.FileLockNodeManager startLiveNode
INFO: HQ221034: Waiting to obtain live lock
Apr 17, 2013 10:51:01 AM org.apache.activemq.core.server.impl.FileLockNodeManager startLiveNode
INFO: HQ221035: Live Server Obtained live lock
Apr 17, 2013 10:51:02 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl deployQueue
INFO: HQ221003: trying to deploy queue jms.queue.exampleQueue
Apr 17, 2013 10:51:02 AM org.apache.activemq.core.remoting.impl.netty.NettyAcceptor start
INFO: HQ221020: Started Netty Acceptor version 3.6.2.Final-c0d783c localhost:5445 for CORE protocol
Apr 17, 2013 10:51:02 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl$SharedStoreLiveActivation run
INFO: HQ221007: Server is now live
Apr 17, 2013 10:51:02 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl start
INFO: HQ221001: ActiveMQ Server version 2.3.0.SNAPSHOT (black'n'yellow, 123) [a57893ff-7783-11e2-9787-07ca142fc9f7]
[INFO]
[INFO] --- activemq-maven-plugin:1.1.1-SNAPSHOT:runClient (runClient) @ activemq-jms-queue-example ---
Apr 17, 2013 10:51:02 AM org.apache.activemq.common.example.ActiveMQExample getContext
INFO: using jnp://localhost:1099 for jndi
Sent message: This is a text message
Received message: This is a text message
example complete
#####################
### SUCCESS! ###
#####################
[INFO]
[INFO] --- activemq-maven-plugin:1.1.1-SNAPSHOT:stop (stop) @ activemq-jms-queue-example ---
Apr 17, 2013 10:51:03 AM org.apache.activemq.core.server.management.impl.ManagementServiceImpl stop
WARN: HQ222113: On ManagementService stop, there are 1 unexpected registered MBeans: [core.acceptor.netty-acceptor]
Apr 17, 2013 10:51:03 AM org.apache.activemq.core.server.impl.ActiveMQServerImpl stop
INFO: HQ221002: ActiveMQ Server version 2.3.0.SNAPSHOT (black'n'yellow, 123) [a57893ff-7783-11e2-9787-07ca142fc9f7] stopped
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.428s
[INFO] Finished at: Wed Apr 17 10:51:03 BST 2013
[INFO] Final Memory: 11M/456M
[INFO] ------------------------------------------------------------------------
</programlisting>
<para>Congratulations! You have successfully run your first ActiveMQ example. Try some of the
others.</para>
</section>
<section id="examples.messaging">
<title>The Java EE Examples</title>
<para>The Java EE Examples are examples that require a JEE application server to run. They
include MDB, Servlet, EJB examples etc. For this you will need the JBoss Application Server 7.1.x
installed and uses Arquillian to run the example. How to do this is explained in the previous chapters.</para>
<para>We'll use the MDB example for the purposes of this guide. For the other examples refer
to the user guide. Before going any further ensure that the JBoss Application Server is
running.</para>
<para> The first thing we need to do is set the <literal>JBOSS_HOME</literal> environment property to the location of the JBoss
Application Server, in a Linux shell this would be something like:</para>
<programlisting>export JBOSS_HOME=/home/jbossas7.1/build/output/jboss-7.1.0</programlisting>
<para>Yoy can then run the example via maven by running <literal>mvn test</literal></para>
<para>In the shell window you should see something like the following output:</para>
<programlisting>
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building ActiveMQ JEE MDB Example 2.3.0.BETA-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ activemq-jee-mdb-bmt-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) @ activemq-jee-mdb-bmt-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:copy-resources (as-node-0) @ activemq-jee-mdb-bmt-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1112 resources
[INFO] Copying 5 resources
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ activemq-jee-mdb-bmt-example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.0:testCompile (default-testCompile) @ activemq-jee-mdb-bmt-example ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12:test (default-test) @ activemq-jee-mdb-bmt-example ---
[INFO] Surefire report directory: /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.apache.activemq.javaee.example.server.ExampleRunnerTest
log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Apr 17, 2013 10:58:04 AM org.jboss.arquillian.container.impl.MapObject populate
WARNING: Configuration contain properties not supported by the backing object org.jboss.as.arquillian.container.managed.ManagedContainerConfiguration
Unused property entries: {waitForPortsTimeoutInSeconds=8, waitForPorts=8787 9999}
Supported property names: [jbossHome, outputToConsole, enableAssertions, password, managementPort, javaHome, javaVmArguments, username, serverConfig, allowConnectingToRunningServer, managementAddress, startupTimeoutInSeconds, modulePath]
Apr 17, 2013 10:58:04 AM org.jboss.as.arquillian.container.managed.ManagedDeployableContainer startInternal
INFO: Starting container with: [/home/andy/devtools/jdk1.6.0_25//bin/java, -Djboss.inst=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0, -ea, -Djboss.home.dir=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0, -Dorg.jboss.boot.log.file=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/log/boot.log, -Dlogging.configuration=file:/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/configuration/logging.properties, -Djboss.modules.dir=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/modules, -Djboss.bundles.dir=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/bundles, -jar, /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/jboss-modules.jar, -mp, /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/modules, -jaxpmodule, javax.xml.jaxp-provider, org.jboss.as.standalone, -server-config, standalone-example.xml]
10:58:04,525 INFO [org.jboss.modules] JBoss Modules version 1.1.1.GA
10:58:04,664 INFO [org.jboss.msc] JBoss MSC version 1.0.2.GA
10:58:04,703 INFO [org.jboss.as] JBAS015899: JBoss AS 7.1.1.Final "Brontes" starting
10:58:05,492 INFO [org.xnio] XNIO Version 3.0.3.GA
10:58:05,494 INFO [org.jboss.as.server] JBAS015888: Creating http management service using socket-binding (management-http)
10:58:05,502 INFO [org.xnio.nio] XNIO NIO Implementation Version 3.0.3.GA
10:58:05,509 INFO [org.jboss.remoting] JBoss Remoting version 3.2.3.GA
10:58:05,527 INFO [org.jboss.as.logging] JBAS011502: Removing bootstrap log handlers
10:58:05,530 INFO [org.jboss.as.configadmin] (ServerService Thread Pool -- 32) JBAS016200: Activating ConfigAdmin Subsystem
10:58:05,560 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 37) JBAS010280: Activating Infinispan subsystem.
10:58:05,562 INFO [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 33) JBAS010403: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3)
10:58:05,573 INFO [org.jboss.as.jacorb] (ServerService Thread Pool -- 38) JBAS016300: Activating JacORB Subsystem
10:58:05,595 INFO [org.jboss.as.connector] (MSC service thread 1-12) JBAS010408: Starting JCA Subsystem (JBoss IronJacamar 1.0.9.Final)
10:58:05,612 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 48) JBAS011800: Activating Naming Subsystem
10:58:05,625 INFO [org.jboss.as.osgi] (ServerService Thread Pool -- 49) JBAS011940: Activating OSGi Subsystem
10:58:05,649 INFO [org.jboss.as.security] (ServerService Thread Pool -- 54) JBAS013101: Activating Security Subsystem
10:58:05,657 INFO [org.jboss.as.naming] (MSC service thread 1-8) JBAS011802: Starting Naming Service
10:58:05,663 INFO [org.jboss.as.mail.extension] (MSC service thread 1-16) JBAS015400: Bound mail session [java:jboss/mail/Default]
10:58:05,675 INFO [org.jboss.as.security] (MSC service thread 1-14) JBAS013100: Current PicketBox version=4.0.7.Final
10:58:05,683 INFO [org.jboss.as.webservices] (ServerService Thread Pool -- 58) JBAS015537: Activating WebServices Extension
10:58:05,705 INFO [org.jboss.jaxr] (MSC service thread 1-8) JBAS014000: Started JAXR subsystem, binding JAXR connection factory into JNDI as: java:jboss/jaxr/ConnectionFactory
10:58:05,831 INFO [org.jboss.ws.common.management.AbstractServerConfig] (MSC service thread 1-4) JBoss Web Services - Stack CXF Server 4.0.2.GA
10:58:05,943 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-6) Starting Coyote HTTP/1.1 on http-localhost.localdomain-127.0.0.1-8080
10:58:05,966 INFO [org.jboss.as.jacorb] (MSC service thread 1-2) JBAS016330: CORBA ORB Service started
10:58:05,988 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-11) live server is starting with configuration ActiveMQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messagingjournal,bindingsDirectory=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messagingbindings,largeMessagesDirectory=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messaginglargemessages,pagingDirectory=/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messagingpaging)
10:58:05,996 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-11) Waiting to obtain live lock
10:58:06,037 INFO [org.apache.activemq.core.persistence.impl.journal.JournalStorageManager] (MSC service thread 1-11) Using AIO Journal
10:58:06,122 INFO [org.jboss.as.jacorb] (MSC service thread 1-14) JBAS016328: CORBA Naming Service started
10:58:06,184 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-7) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS]
10:58:06,204 INFO [org.apache.activemq.core.server.impl.AIOFileLockNodeManager] (MSC service thread 1-11) Waiting to obtain live lock
10:58:06,205 INFO [org.apache.activemq.core.server.impl.AIOFileLockNodeManager] (MSC service thread 1-11) Live Server Obtained live lock
10:58:06,434 INFO [org.jboss.as.remoting] (MSC service thread 1-2) JBAS017100: Listening on localhost.localdomain/127.0.0.1:4447
10:58:06,434 INFO [org.jboss.as.remoting] (MSC service thread 1-15) JBAS017100: Listening on /127.0.0.1:9999
10:58:06,436 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-16) JBAS015012: Started FileSystemDeploymentService for directory /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/deployments
10:58:08,790 INFO [org.apache.activemq.core.remoting.impl.netty.NettyAcceptor] (MSC service thread 1-11) Started Netty Acceptor version 3.2.5.Final-a96d88c localhost.localdomain:5445 for CORE protocol
10:58:08,793 INFO [org.apache.activemq.core.remoting.impl.netty.NettyAcceptor] (MSC service thread 1-11) Started Netty Acceptor version 3.2.5.Final-a96d88c localhost.localdomain:5455 for CORE protocol
10:58:08,795 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-11) Server is now live
10:58:08,797 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-11) ActiveMQ Server version 2.2.13.Final (HQ_2_2_13_FINAL_AS7, 122) [5c499e88-9c63-11e2-bfa3-fe5400591699]) started
10:58:08,822 INFO [org.jboss.as.messaging] (MSC service thread 1-4) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/RemoteConnectionFactory
10:58:08,824 INFO [org.jboss.as.messaging] (MSC service thread 1-4) JBAS011601: Bound messaging object to jndi name java:/RemoteConnectionFactory
10:58:08,825 INFO [org.jboss.as.messaging] (MSC service thread 1-10) JBAS011601: Bound messaging object to jndi name java:/ConnectionFactory
10:58:08,830 INFO [org.apache.activemq.core.server.impl.ActiveMQServerImpl] (MSC service thread 1-3) trying to deploy queue jms.queue.testQueue
10:58:08,836 INFO [org.jboss.as.messaging] (MSC service thread 1-3) JBAS011601: Bound messaging object to jndi name java:/queue/test
10:58:08,840 INFO [org.jboss.as.messaging] (MSC service thread 1-3) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/queues/testQueue
10:58:08,859 INFO [org.jboss.as.deployment.connector] (MSC service thread 1-9) JBAS010406: Registered connection factory java:/JmsXA
10:58:08,866 INFO [org.apache.activemq.ra.ActiveMQResourceAdapter] (MSC service thread 1-9) ActiveMQ resource adaptor started
10:58:08,867 INFO [org.jboss.as.connector.services.ResourceAdapterActivatorService$ResourceAdapterActivator] (MSC service thread 1-9) IJ020002: Deployed: file://RaActivatoractivemq-ra
10:58:08,870 INFO [org.jboss.as.deployment.connector] (MSC service thread 1-5) JBAS010401: Bound JCA ConnectionFactory [java:/JmsXA]
10:58:08,898 INFO [org.jboss.as.server.deployment] (MSC service thread 1-10) JBAS015876: Starting deployment of "ONT001-1.0.war"
10:58:09,146 INFO [org.jboss.wsf.stack.cxf.metadata.MetadataBuilder] (MSC service thread 1-1) Add Service
id=com.hpm.webservices.BasicWSImpl
address=http://localhost:8080/hpm/BasicWService
implementor=com.hpm.webservices.BasicWSImpl
invoker=org.jboss.wsf.stack.cxf.JBossWSInvoker
serviceName={http://ont001-hpm.rhcloud.com/BasicWS}BasicWService
portName={http://ont001-hpm.rhcloud.com/BasicWS}BasicWS
wsdlLocation=null
mtomEnabled=false
10:58:09,361 INFO [org.apache.cxf.service.factory.ReflectionServiceFactoryBean] (MSC service thread 1-1) Creating Service {http://ont001-hpm.rhcloud.com/BasicWS}BasicWService from WSDL: WEB-INF/wsdl/BasicWService.wsdl
10:58:09,517 INFO [org.jboss.wsf.stack.cxf.transport.AddressRewritingEndpointInfo] (MSC service thread 1-1) Setting new service endpoint address in wsdl: http://ONT001-HPM.rhcloud.com:80/BasicWService
10:58:09,656 INFO [org.jboss.wsf.stack.cxf.transport.AddressRewritingEndpointInfo] (MSC service thread 1-1) Setting new service endpoint address in wsdl: http://localhost:8080/hpm/BasicWService
10:58:09,688 INFO [org.apache.cxf.endpoint.ServerImpl] (MSC service thread 1-1) Setting the server's publish address to be http://localhost:8080/hpm/BasicWService
10:58:09,729 INFO [org.jboss.wsf.stack.cxf.deployment.WSDLFilePublisher] (MSC service thread 1-1) WSDL published to: file:/home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/wsdl/ONT001-1.0.war/BasicWService.wsdl
10:58:09,735 INFO [org.jboss.as.webservices] (MSC service thread 1-11) JBAS015539: Starting service jboss.ws.port-component-link
10:58:09,748 INFO [org.jboss.as.webservices] (MSC service thread 1-10) JBAS015539: Starting service jboss.ws.endpoint."ONT001-1.0.war"."com.hpm.webservices.BasicWSImpl"
10:58:09,753 INFO [org.jboss.ws.common.management.DefaultEndpointRegistry] (MSC service thread 1-10) register: jboss.ws:context=hpm,endpoint=com.hpm.webservices.BasicWSImpl
10:58:09,829 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /hpm
10:58:09,834 INFO [org.jboss.as] (MSC service thread 1-7) JBAS015951: Admin console listening on http://127.0.0.1:9990
10:58:09,835 INFO [org.jboss.as] (MSC service thread 1-7) JBAS015874: JBoss AS 7.1.1.Final "Brontes" started in 5506ms - Started 216 of 296 services (79 services are passive or on-demand)
10:58:09,979 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "ONT001-1.0.war"
mdb.jar:
/org/
/org.apache.activemq/
/org.apache.activemq/javaee/
/org.apache.activemq/javaee/example/
/org.apache.activemq/javaee/example/server/
/org.apache.activemq/javaee/example/server/MDB_BMTExample.class
10:58:11,612 INFO [org.jboss.as.repository] (management-handler-thread - 2) JBAS014900: Content added at location /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/f0/e2d589ab9490193e109c8bc833f725c87defae/content
10:58:11,620 INFO [org.jboss.as.server.deployment] (MSC service thread 1-8) JBAS015876: Starting deployment of "arquillian-service"
10:58:11,811 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.jmx:main") which may be changed or removed in future versions without notice.
10:58:11,812 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.server:main") which may be changed or removed in future versions without notice.
10:58:11,813 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.osgi:main") which may be changed or removed in future versions without notice.
10:58:11,815 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.jandex:main") which may be changed or removed in future versions without notice.
10:58:11,817 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.osgi.framework:main") which may be changed or removed in future versions without notice.
10:58:11,953 INFO [org.jboss.as.server] (management-handler-thread - 2) JBAS018559: Deployed "arquillian-service"
10:58:12,328 INFO [org.jboss.as.repository] (management-handler-thread - 3) JBAS014900: Content added at location /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/59/7dcdb0f420ed57aea638b2599f7a86eecf6c85/content
10:58:12,333 INFO [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015876: Starting deployment of "mdb.jar"
10:58:12,401 INFO [org.jboss.as.arquillian] (MSC service thread 1-14) Arquillian deployment detected: ArquillianConfig[service=jboss.arquillian.config."mdb.jar",unit=mdb.jar,tests=[org.apache.activemq.javaee.example.server.ExampleRunnerTest]]
10:58:12,418 INFO [org.jboss.as.ejb3] (MSC service thread 1-15) JBAS014142: Started message driven bean 'MDB_BMTExample' with 'activemq-ra' resource adapter
10:58:12,562 INFO [org.jboss.as.server] (management-handler-thread - 3) JBAS018559: Deployed "mdb.jar"
Sent message: This is a text message
10:58:13,229 INFO [org.jboss.as.naming] (Remoting "localhost" task-3) JBAS011806: Channel end notification received, closing channel Channel ID 57be4578 (inbound) of Remoting connection 3ac552d5 to /127.0.0.1:58571
10:58:13,255 INFO [stdout] (Thread-0 (ActiveMQ-client-global-threads-1402019528)) message This is a text message received
10:58:13,257 INFO [stdout] (Thread-0 (ActiveMQ-client-global-threads-1402019528)) we're in the middle of a transaction: org.jboss.tm.usertx.client.ServerVMClientUserTransaction@6b04d3c8
10:58:14,292 INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015877: Stopped deployment mdb.jar in 33ms
10:58:14,413 INFO [org.jboss.as.repository] (management-handler-thread - 1) JBAS014901: Content removed from location /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/59/7dcdb0f420ed57aea638b2599f7a86eecf6c85/content
10:58:14,415 INFO [org.jboss.as.server] (management-handler-thread - 1) JBAS018558: Undeployed "mdb.jar"
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.609 sec
10:58:14,436 INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015877: Stopped deployment arquillian-service in 6ms
10:58:14,530 INFO [org.jboss.as.repository] (management-handler-thread - 2) JBAS014901: Content removed from location /home/andy/projects/activemq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/f0/e2d589ab9490193e109c8bc833f725c87defae/content
10:58:14,532 INFO [org.jboss.as.server] (management-handler-thread - 2) JBAS018558: Undeployed "arquillian-service"
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.441s
[INFO] Finished at: Wed Apr 17 10:58:16 BST 2013
[INFO] Final Memory: 19M/361M
[INFO] ------------------------------------------------------------------------
</programlisting>
<para>Congratulations! you have successfully deployed and run a Java EE example.</para>
</section>
</chapter>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,85 @@
Installation
============
This section describes how to install ActiveMQ.
Prerequisites
=============
> **Note**
>
> ActiveMQ only runs on Java 7 or later.
By default, ActiveMQ server runs with 1GiB of memory. If your computer
has less memory, or you want to run it with more available RAM, modify
the value in `bin/run.sh` accordingly.
For persistence, ActiveMQ uses its own fast journal, which you can
configure to use libaio (which is the default when running on Linux) or
Java NIO. In order to use the libaio module on Linux, you'll need to
install libaio, if it's not already installed.
If you're not running on Linux then you don't need to worry about this.
You can install libaio using the following steps as the root user:
Using yum, (e.g. on Fedora or Red Hat Enterprise Linux):
yum install libaio
Using aptitude, (e.g. on Ubuntu or Debian system):
apt-get install libaio
Stand-alone ActiveMQ Server
===========================
After downloading the distribution, unzip it into your chosen directory.
At this point it should be possible to [run straight out of the
box](#running.standalone), the following describes the directory
structure:
|___ bin
|
|___ config
| |___ jboss-as-4
| |___ jboss-as-5
| |___ stand-alone
|
|___ docs
| |___ api
| |___ quickstart-guide
| |___ user-manual
|
|___ examples
| |___ core
| |___ javaee
| |___ jms
|
|___ lib
|
|___ licenses
|
|___ schemas
- `bin` -- binaries and scripts needed to run ActiveMQ.
- `config` -- configuration files needed to configure ActiveMQ. This
contains configurations to run ActiveMQ either in stand-alone or
inside JBoss AS 4 and 5. Please refer to the reference guide for
details on configuration.
- `docs` -- guides and javadocs for ActiveMQ
- `examples` -- JMS and Java EE examples. Please refer to the 'running
examples' chapter for details on how to run them.
- `lib` -- jars and libraries needed to run ActiveMQ
- `licenses` -- licenses for ActiveMQ
- `schemas` -- XML Schemas used to validate ActiveMQ configuration
files

View File

@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="installation">
<title>Installation</title>
<para>This section describes how to install ActiveMQ. </para>
<section id="installation.prerequisites">
<title>Prerequisites</title>
<note>
<para>ActiveMQ only runs on Java 7 or later.</para>
</note>
<para>By default, ActiveMQ server runs with 1GiB of memory. If your computer has less memory,
or you want to run it with more available RAM, modify the value in <literal
>bin/run.sh</literal> accordingly.</para>
<para>For persistence, ActiveMQ uses its own fast journal, which you can configure to use
libaio (which is the default when running on Linux) or Java NIO. In order to use the libaio
module on Linux, you'll need to install libaio, if it's not already installed.</para>
<para>If you're not running on Linux then you don't need to worry about this.</para>
<para>You can install libaio using the following steps as the root user:</para>
<para>Using yum, (e.g. on Fedora or Red Hat Enterprise Linux):</para>
<programlisting>yum install libaio</programlisting>
<para>Using aptitude, (e.g. on Ubuntu or Debian system):</para>
<programlisting>apt-get install libaio</programlisting>
</section>
<section id="installation.standalone">
<title>Stand-alone ActiveMQ Server</title>
<para>After downloading the distribution, unzip it into your chosen directory. At this point
it should be possible to <link linkend="running.standalone">run straight out of the
box</link>, the following describes the directory structure: </para>
<programlisting>
|___ bin
|
|___ config
| |___ jboss-as-4
| |___ jboss-as-5
| |___ stand-alone
|
|___ docs
| |___ api
| |___ quickstart-guide
| |___ user-manual
|
|___ examples
| |___ core
| |___ javaee
| |___ jms
|
|___ lib
|
|___ licenses
|
|___ schemas
</programlisting>
<itemizedlist>
<listitem>
<para><literal>bin</literal> -- binaries and scripts needed to run ActiveMQ.</para>
</listitem>
<listitem>
<para><literal>config</literal> -- configuration files needed to configure ActiveMQ. This
contains configurations to run ActiveMQ either in stand-alone or inside JBoss AS 4 and 5.
Please refer to the reference guide for details on configuration. </para>
</listitem>
<listitem>
<para><literal>docs</literal> -- guides and javadocs for ActiveMQ </para>
</listitem>
<listitem>
<para><literal>examples</literal> -- JMS and Java EE examples. Please refer to the
'running examples' chapter for details on how to run them. </para>
</listitem>
<listitem>
<para><literal>lib</literal> -- jars and libraries needed to run ActiveMQ </para>
</listitem>
<listitem>
<para><literal>licenses</literal> -- licenses for ActiveMQ </para>
</listitem>
<listitem>
<para><literal>schemas</literal> -- XML Schemas used to validate ActiveMQ configuration
files</para>
</listitem>
</itemizedlist>
</section>
</chapter>

View File

@ -0,0 +1,13 @@
Getting Started
===============
This short guide explains how to download, install and quickly get
started with ActiveMQ.
After downloading and installing we highly recommend you run the
examples to get acquainted with ActiveMQ. We ship with over 70 examples
demonstrating most of the features.
This guide is not intended to be a replacement for the user manual. The
user manual goes into much more depth, so please consult that for
further information.

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="introduction">
<title>Getting Started</title>
<para>This short guide explains how to download, install and quickly get started with
ActiveMQ.</para>
<para>After downloading and installing we highly recommend you run the examples to get
acquainted with ActiveMQ. We ship with over 70 examples demonstrating most of the
features.</para>
<para>This guide is not intended to be a replacement for the user manual. The user manual goes
into much more depth, so please consult that for further information.</para>
</chapter>

View File

@ -0,0 +1,6 @@
#!/bin/sh
for i in `find . -name "*.xml"`; do
newFile=`echo $i | sed 's/xml/md/'`
echo creating $newFile
pandoc -f docbook -t markdown $i -o $newFile
done

View File

@ -0,0 +1,17 @@
Legal Notice
============
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. The
ASF licenses this file to You under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,40 +0,0 @@
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="notice">
<title>Legal Notice</title>
<para>Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at</para>
<para></para>
<para>http://www.apache.org/licenses/LICENSE-2.0</para>
<para></para>
<para>Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.</para>
</chapter>

View File

@ -0,0 +1,106 @@
Starting The Server
===================
Standalone ActiveMQ
===================
To run a stand-alone server, open up a shell or command prompt and
navigate into the `bin` directory. Then execute `./activemq run` (or
`./activemq.cmd run` on Windows) and you should see the following output
bin$ ./activemq run
11:05:06,589 INFO [org.apache.activemq.integration.bootstrap] HQ101000: Starting ActiveMQ Server
...
11:05:10,848 INFO [org.apache.activemq.core.server] HQ221001: ActiveMQ Server version 2.5.0.SNAPSHOT (Wild Hornet, 125) [e32ae252-52ee-11e4-a716-7785dc3013a3]
ActiveMQ is now running.
Both the run and the stop scripts use the config under
`config/non-clustered` by default. The configuration can be changed by
running `./activemq run xml:../config/non-clustered/bootstrap.xml` or
another config of your choosing.
The server can be stopped by running `./activemq stop`
ActiveMQ In Wildfly
===================
ActiveMQ is the Default Messaging Provider in the [Wildfly Application
Server](http://www.wildfly.org/) To run the server you need to run the
standalone-full.xml configuration by running the command
'./standalone.sh -c standalone-full.xml'. You will see something like:/
bin$ ./standalone.sh -c standalone-full.xml
=========================================================================
JBoss Bootstrap Environment
JBOSS_HOME: /home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT
JAVA: java
JAVA_OPTS: -server -XX:+UseCompressedOops -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true
=========================================================================
14:47:33,642 INFO [org.jboss.modules] (main) JBoss Modules version 1.3.0.Final
14:47:34,780 INFO [org.jboss.msc] (main) JBoss MSC version 1.2.0.Beta2
14:47:34,875 INFO [org.jboss.as] (MSC service thread 1-6) JBAS015899: WildFly 8.0.0.Beta1-SNAPSHOT "WildFly" starting
14:47:40,382 INFO [org.jboss.as.server] (Controller Boot Thread) JBAS015888: Creating http management service using socket-binding (management-http)
14:47:40,383 INFO [org.xnio] (MSC service thread 1-15) XNIO version 3.1.0.CR7
14:47:40,402 INFO [org.xnio.nio] (MSC service thread 1-15) XNIO NIO Implementation Version 3.1.0.CR7
14:47:40,488 INFO [org.jboss.remoting] (MSC service thread 1-15) JBoss Remoting version 4.0.0.Beta1
14:47:40,547 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 36) JBAS010280: Activating Infinispan subsystem.
14:47:40,560 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 47) JBAS011800: Activating Naming Subsystem
14:47:40,560 INFO [org.jboss.as.security] (ServerService Thread Pool -- 52) JBAS013171: Activating Security Subsystem
14:47:40,567 INFO [org.jboss.as.jacorb] (ServerService Thread Pool -- 37) JBAS016300: Activating JacORB Subsystem
14:47:40,571 INFO [org.jboss.as.jsf] (ServerService Thread Pool -- 43) JBAS012605: Activated the following JSF Implementations: [main]
14:47:40,574 INFO [org.jboss.as.webservices] (ServerService Thread Pool -- 56) JBAS015537: Activating WebServices Extension
14:47:40,721 INFO [org.jboss.as.connector.logging] (MSC service thread 1-6) JBAS010408: Starting JCA Subsystem (IronJacamar 1.1.0.Final)
14:47:41,321 INFO [org.jboss.as.naming] (MSC service thread 1-4) JBAS011802: Starting Naming Service
14:47:41,323 INFO [org.jboss.as.mail.extension] (MSC service thread 1-11) JBAS015400: Bound mail session [java:jboss/mail/Default]
14:47:41,552 INFO [org.wildfly.extension.undertow] (MSC service thread 1-10) JBAS017502: Undertow 1.0.0.Beta16 starting
14:47:41,552 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 55) JBAS017502: Undertow 1.0.0.Beta16 starting
14:47:41,573 INFO [org.jboss.as.security] (MSC service thread 1-6) JBAS013170: Current PicketBox version=4.0.17.SP1
14:47:41,775 INFO [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 31) JBAS010403: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3)
14:47:41,777 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-16) JBAS010417: Started Driver service with driver-name = h2
14:47:42,085 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 55) JBAS017527: Creating file handler for path /home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/welcome-content
14:47:42,086 INFO [org.wildfly.extension.undertow] (MSC service thread 1-2) JBAS017525: Started server default-server.
14:47:42,088 INFO [org.wildfly.extension.undertow] (MSC service thread 1-13) JBAS017531: Host default-host starting
14:47:42,471 INFO [org.wildfly.extension.undertow] (MSC service thread 1-7) JBAS017519: Undertow HTTP listener default listening on /127.0.0.1:8080
14:47:42,823 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-10) JBAS015012: Started FileSystemDeploymentService for directory /home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/deployments
14:47:42,882 INFO [org.jboss.as.remoting] (MSC service thread 1-16) JBAS017100: Listening on 127.0.0.1:9999
14:47:43,037 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221000: live server is starting with configuration ActiveMQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messagingjournal,bindingsDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messagingbindings,largeMessagesDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messaginglargemessages,pagingDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messagingpaging)
14:47:43,062 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221006: Waiting to obtain live lock
14:47:43,103 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221012: Using AIO Journal
14:47:43,313 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support CORE
14:47:43,426 INFO [org.jboss.ws.common.management] (MSC service thread 1-3) JBWS022052: Starting JBoss Web Services - Stack CXF Server 4.2.1.Final
14:47:43,448 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support AMQP
14:47:43,451 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support STOMP
14:47:43,453 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support STOMP_WS
14:47:43,567 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221034: Waiting to obtain live lock
14:47:43,567 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221035: Live Server Obtained live lock
14:47:43,777 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-8) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS]
14:47:43,781 INFO [org.jboss.as.jacorb] (MSC service thread 1-1) JBAS016330: CORBA ORB Service started
14:47:44,115 INFO [org.jboss.as.jacorb] (MSC service thread 1-13) JBAS016328: CORBA Naming Service started
14:47:44,345 INFO [org.wildfly.extension.undertow] (MSC service thread 1-3) JBAS018210: Register web context: /activemq-server
14:47:44,361 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221020: Started Netty Acceptor version 3.6.6.Final-90e1eb2 127.0.0.1:5455 for CORE protocol
14:47:44,362 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221020: Started Netty Acceptor version 3.6.6.Final-90e1eb2 127.0.0.1:5445 for CORE protocol
14:47:44,364 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221020: Started Netty Acceptor version 3.6.6.Final-90e1eb2 org.apache.activemq.default.servlet:5445 for CORE protocol
14:47:44,366 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221007: Server is now live
14:47:44,366 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221001: ActiveMQ Server version 2.4.0.Beta2 (Andromedian Flyer, 123) [bcc1cd10-2bfb-11e3-ad5f-9f88840f9e1a]
14:47:44,435 INFO [org.jboss.as.messaging] (ServerService Thread Pool -- 58) JBAS011601: Bound messaging object to jndi name java:/ConnectionFactory
14:47:44,437 INFO [org.jboss.as.messaging] (ServerService Thread Pool -- 59) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/ServletConnectionFactory
14:47:44,439 INFO [org.jboss.as.messaging] (ServerService Thread Pool -- 60) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/RemoteConnectionFactory
14:47:44,462 INFO [org.jboss.as.connector.deployment] (MSC service thread 1-3) JBAS010406: Registered connection factory java:/JmsXA
14:47:44,531 INFO [org.apache.activemq.ra] (MSC service thread 1-3) ActiveMQ resource adaptor started
14:47:44,532 INFO [org.jboss.as.connector.services.resourceadapters.ResourceAdapterActivatorService$ResourceAdapterActivator] (MSC service thread 1-3) IJ020002: Deployed: file://RaActivatoractivemq-ra
14:47:44,535 INFO [org.jboss.as.connector.deployment] (MSC service thread 1-12) JBAS010401: Bound JCA ConnectionFactory [java:/JmsXA]
14:47:44,536 INFO [org.jboss.as.messaging] (MSC service thread 1-15) JBAS011601: Bound messaging object to jndi name java:jboss/DefaultJMSConnectionFactory
14:47:44,719 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management
14:47:44,720 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
14:47:44,721 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.0.0.Beta1-SNAPSHOT "WildFly" started in 12184ms - Started 213 of 249 services (73 services are lazy, passive or on-demand)

View File

@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_QuickStart_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter id="running">
<title>Starting The Server</title>
<section id="running.standalone">
<title>Standalone ActiveMQ</title>
<para>To run a stand-alone server, open up a shell or command prompt and navigate into the
<literal>bin</literal> directory. Then execute <literal>./activemq run</literal> (or <literal
>./activemq.cmd run</literal> on Windows) and you should see the following output </para>
<programlisting>
bin$ ./activemq run
11:05:06,589 INFO [org.apache.activemq.integration.bootstrap] HQ101000: Starting ActiveMQ Server
...
11:05:10,848 INFO [org.apache.activemq.core.server] HQ221001: ActiveMQ Server version 2.5.0.SNAPSHOT (Wild Hornet, 125) [e32ae252-52ee-11e4-a716-7785dc3013a3]
</programlisting>
<para>ActiveMQ is now running.</para>
<para>Both the run and the stop scripts use the config under <literal
>config/non-clustered</literal> by default. The configuration can be changed
by running <literal>./activemq run xml:../config/non-clustered/bootstrap.xml</literal> or another config of
your choosing.</para>
<para>The server can be stopped by running <literal>./activemq stop</literal></para>
</section>
<section id="running.jboss.Wildfly">
<title>ActiveMQ In Wildfly</title>
<para>ActiveMQ is the Default Messaging Provider in the <ulink
url="http://www.wildfly.org/" >Wildfly Application Server</ulink>
To run the server you need to run the standalone-full.xml configuration by running the command './standalone.sh -c standalone-full.xml'.
You will see something like:/</para>
<programlisting>
bin$ ./standalone.sh -c standalone-full.xml
=========================================================================
JBoss Bootstrap Environment
JBOSS_HOME: /home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT
JAVA: java
JAVA_OPTS: -server -XX:+UseCompressedOops -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true
=========================================================================
14:47:33,642 INFO [org.jboss.modules] (main) JBoss Modules version 1.3.0.Final
14:47:34,780 INFO [org.jboss.msc] (main) JBoss MSC version 1.2.0.Beta2
14:47:34,875 INFO [org.jboss.as] (MSC service thread 1-6) JBAS015899: WildFly 8.0.0.Beta1-SNAPSHOT "WildFly" starting
14:47:40,382 INFO [org.jboss.as.server] (Controller Boot Thread) JBAS015888: Creating http management service using socket-binding (management-http)
14:47:40,383 INFO [org.xnio] (MSC service thread 1-15) XNIO version 3.1.0.CR7
14:47:40,402 INFO [org.xnio.nio] (MSC service thread 1-15) XNIO NIO Implementation Version 3.1.0.CR7
14:47:40,488 INFO [org.jboss.remoting] (MSC service thread 1-15) JBoss Remoting version 4.0.0.Beta1
14:47:40,547 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 36) JBAS010280: Activating Infinispan subsystem.
14:47:40,560 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 47) JBAS011800: Activating Naming Subsystem
14:47:40,560 INFO [org.jboss.as.security] (ServerService Thread Pool -- 52) JBAS013171: Activating Security Subsystem
14:47:40,567 INFO [org.jboss.as.jacorb] (ServerService Thread Pool -- 37) JBAS016300: Activating JacORB Subsystem
14:47:40,571 INFO [org.jboss.as.jsf] (ServerService Thread Pool -- 43) JBAS012605: Activated the following JSF Implementations: [main]
14:47:40,574 INFO [org.jboss.as.webservices] (ServerService Thread Pool -- 56) JBAS015537: Activating WebServices Extension
14:47:40,721 INFO [org.jboss.as.connector.logging] (MSC service thread 1-6) JBAS010408: Starting JCA Subsystem (IronJacamar 1.1.0.Final)
14:47:41,321 INFO [org.jboss.as.naming] (MSC service thread 1-4) JBAS011802: Starting Naming Service
14:47:41,323 INFO [org.jboss.as.mail.extension] (MSC service thread 1-11) JBAS015400: Bound mail session [java:jboss/mail/Default]
14:47:41,552 INFO [org.wildfly.extension.undertow] (MSC service thread 1-10) JBAS017502: Undertow 1.0.0.Beta16 starting
14:47:41,552 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 55) JBAS017502: Undertow 1.0.0.Beta16 starting
14:47:41,573 INFO [org.jboss.as.security] (MSC service thread 1-6) JBAS013170: Current PicketBox version=4.0.17.SP1
14:47:41,775 INFO [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 31) JBAS010403: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3)
14:47:41,777 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-16) JBAS010417: Started Driver service with driver-name = h2
14:47:42,085 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 55) JBAS017527: Creating file handler for path /home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/welcome-content
14:47:42,086 INFO [org.wildfly.extension.undertow] (MSC service thread 1-2) JBAS017525: Started server default-server.
14:47:42,088 INFO [org.wildfly.extension.undertow] (MSC service thread 1-13) JBAS017531: Host default-host starting
14:47:42,471 INFO [org.wildfly.extension.undertow] (MSC service thread 1-7) JBAS017519: Undertow HTTP listener default listening on /127.0.0.1:8080
14:47:42,823 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-10) JBAS015012: Started FileSystemDeploymentService for directory /home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/deployments
14:47:42,882 INFO [org.jboss.as.remoting] (MSC service thread 1-16) JBAS017100: Listening on 127.0.0.1:9999
14:47:43,037 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221000: live server is starting with configuration ActiveMQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messagingjournal,bindingsDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messagingbindings,largeMessagesDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messaginglargemessages,pagingDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messagingpaging)
14:47:43,062 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221006: Waiting to obtain live lock
14:47:43,103 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221012: Using AIO Journal
14:47:43,313 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support CORE
14:47:43,426 INFO [org.jboss.ws.common.management] (MSC service thread 1-3) JBWS022052: Starting JBoss Web Services - Stack CXF Server 4.2.1.Final
14:47:43,448 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support AMQP
14:47:43,451 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support STOMP
14:47:43,453 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support STOMP_WS
14:47:43,567 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221034: Waiting to obtain live lock
14:47:43,567 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221035: Live Server Obtained live lock
14:47:43,777 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-8) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS]
14:47:43,781 INFO [org.jboss.as.jacorb] (MSC service thread 1-1) JBAS016330: CORBA ORB Service started
14:47:44,115 INFO [org.jboss.as.jacorb] (MSC service thread 1-13) JBAS016328: CORBA Naming Service started
14:47:44,345 INFO [org.wildfly.extension.undertow] (MSC service thread 1-3) JBAS018210: Register web context: /activemq-server
14:47:44,361 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221020: Started Netty Acceptor version 3.6.6.Final-90e1eb2 127.0.0.1:5455 for CORE protocol
14:47:44,362 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221020: Started Netty Acceptor version 3.6.6.Final-90e1eb2 127.0.0.1:5445 for CORE protocol
14:47:44,364 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221020: Started Netty Acceptor version 3.6.6.Final-90e1eb2 org.apache.activemq.default.servlet:5445 for CORE protocol
14:47:44,366 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221007: Server is now live
14:47:44,366 INFO [org.apache.activemq.core.server] (ServerService Thread Pool -- 58) HQ221001: ActiveMQ Server version 2.4.0.Beta2 (Andromedian Flyer, 123) [bcc1cd10-2bfb-11e3-ad5f-9f88840f9e1a]
14:47:44,435 INFO [org.jboss.as.messaging] (ServerService Thread Pool -- 58) JBAS011601: Bound messaging object to jndi name java:/ConnectionFactory
14:47:44,437 INFO [org.jboss.as.messaging] (ServerService Thread Pool -- 59) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/ServletConnectionFactory
14:47:44,439 INFO [org.jboss.as.messaging] (ServerService Thread Pool -- 60) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/RemoteConnectionFactory
14:47:44,462 INFO [org.jboss.as.connector.deployment] (MSC service thread 1-3) JBAS010406: Registered connection factory java:/JmsXA
14:47:44,531 INFO [org.apache.activemq.ra] (MSC service thread 1-3) ActiveMQ resource adaptor started
14:47:44,532 INFO [org.jboss.as.connector.services.resourceadapters.ResourceAdapterActivatorService$ResourceAdapterActivator] (MSC service thread 1-3) IJ020002: Deployed: file://RaActivatoractivemq-ra
14:47:44,535 INFO [org.jboss.as.connector.deployment] (MSC service thread 1-12) JBAS010401: Bound JCA ConnectionFactory [java:/JmsXA]
14:47:44,536 INFO [org.jboss.as.messaging] (MSC service thread 1-15) JBAS011601: Bound messaging object to jndi name java:jboss/DefaultJMSConnectionFactory
14:47:44,719 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management
14:47:44,720 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
14:47:44,721 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.0.0.Beta1-SNAPSHOT "WildFly" started in 12184ms - Started 213 of 249 services (73 services are lazy, passive or on-demand)
</programlisting>
</section>
</chapter>

View File

@ -1,300 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<parent>
<groupId>org.apache.activemq.docs</groupId>
<artifactId>activemq-docs</artifactId>
<version>6.0.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.activemq.docs</groupId>
<artifactId>quickstart-guide</artifactId>
<version>1.0</version>
<packaging>jdocbook</packaging>
<name>quickstart-guide</name>
<properties>
<translation>en</translation>
<docname>ActiveMQ_QuickStart_Guide</docname>
<bookname>ActiveMQ QuickStart Guide</bookname>
</properties>
<repositories>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<!--pluginRepository>
<id>jboss-snapshot-repository-group</id>
<name>JBoss Snapshot Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/snapshot/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository-->
</pluginRepositories>
<profiles>
<!-- mvn compile -->
<profile>
<id>all</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.3.5</version>
<extensions>true</extensions>
<configuration>
<formats>
<format>
<formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
<finalName>${docname}.pdf</finalName>
</format>
<format>
<formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
<format>
<formatName>html_single</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
</formats>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- mvn compile -Phtml -->
<profile>
<id>html</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<configuration>
<formats>
<format>
<formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
</formats>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- mvn compile -Phtml-single -->
<profile>
<id>html-single</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
</profile>
<!-- mvn compile -Ppdf -->
<profile>
<id>pdf</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<configuration>
<formats>
<format>
<formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
<finalName>${docname}.pdf</finalName>
</format>
</formats>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<dependencies>
<dependency>
<groupId>org.jboss.pressgang</groupId>
<artifactId>pressgang-xslt</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jbossorg-jdocbook-style</artifactId>
<version>1.1.1</version>
<type>jdocbook-style</type>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>${project.basedir}</sourceDirectory>
<sourceDocumentName>${docname}.xml</sourceDocumentName>
<masterTranslation>en</masterTranslation>
<imageResource>
<directory>${project.basedir}/en</directory>
<includes>
<include>images/*.png</include>
</includes>
</imageResource>
<formats>
<format>
<formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
<finalName>${pdf.name}</finalName>
</format>
<format>
<formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
<format>
<formatName>html_single</formatName>
<stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
<finalName>index.html</finalName>
</format>
</formats>
<options>
<xincludeSupported>true</xincludeSupported>
<xmlTransformerType>saxon</xmlTransformerType>
<docbookVersion>1.72.0</docbookVersion>
<localeSeparator>-</localeSeparator>
<applyStandardInjectionValues>false</applyStandardInjectionValues>
<transformerParameters>
<property>
<name>javax.xml.parsers.DocumentBuilderFactory</name>
<value>org.apache.xerces.jaxp.DocumentBuilderFactoryImpl</value>
</property>
<property>
<name>javax.xml.parsers.SAXParserFactory</name>
<value>org.apache.xerces.jaxp.SAXParserFactoryImpl</value>
</property>
</transformerParameters>
</options>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!--<build>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.1</version>
<extensions>true</extensions>
<dependencies>
<dependency>
<groupId>org.jboss.pressgang</groupId>
<artifactId>pressgang-xslt</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jbossorg-jdocbook-style</artifactId>
<version>1.1.1</version>
<type>jdocbook-style</type>
</dependency>
</dependencies>
<configuration>
<sourceDocumentName>${docname}.xml</sourceDocumentName>
<sourceDirectory>.</sourceDirectory>
<imageResource>
<directory>${translation}</directory>
<includes>
<include>images/*</include>
</includes>
</imageResource>
<options>
<xincludeSupported>true</xincludeSupported>
<xmlTransformerType>saxon</xmlTransformerType>
<transformerParameters>
<property>
<name>javax.xml.parsers.DocumentBuilderFactory</name>
<value>org.apache.xerces.jaxp.DocumentBuilderFactoryImpl</value>
</property>
<property>
<name>javax.xml.parsers.SAXParserFactory</name>
<value>org.apache.xerces.jaxp.SAXParserFactoryImpl</value>
</property>
</transformerParameters>
</options>
</configuration>
</plugin>
</plugins>
</build>-->
</project>

View File

@ -1,22 +0,0 @@
<!ENTITY PRODUCT "ActiveMQ">
<!ENTITY BOOKID "ActiveMQ_QuickStart_Guide">
<!ENTITY YEAR "2011">
<!ENTITY HOLDER "Red Hat Inc.">
<!ENTITY semi ";"><!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

View File

@ -1,79 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- This document was created with Syntext Serna Free. --><!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<book>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Book_Info.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="notice.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="preface.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="project-info.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="messaging-concepts.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="architecture.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="using-server.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="using-jms.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="using-core.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="jms-core-mapping.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="client-classpath.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="examples.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="wildcard-routing.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="wildcard-syntax.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="filter-expressions.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="persistence.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="configuring-transports.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="connection-ttl.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="slow-consumers.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="transaction-config.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="flow-control.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="send-guarantees.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="undelivered-messages.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="message-expiry.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="large-messages.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="paging.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="queue-attributes.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="scheduled-messages.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="last-value-queues.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="message-grouping.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pre-acknowledge.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="management.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="security.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="appserver-integration.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="jms-bridge.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="client-reconnection.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="diverts.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="core-bridges.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="duplicate-detection.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="clusters.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="ha.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="libaio.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="thread-pooling.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="logging.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="rest.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="embedding-activemq.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="spring-integration.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="aerogear-integration.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="vertx-integration.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="intercepting-operations.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="interoperability.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="tools.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="perf-tuning.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="configuration-index.xml"/>
</book>

View File

@ -1,86 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<authorgroup>
<author>
<firstname>Clebert</firstname>
<surname>Suconic</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Project Lead</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
<email>csuconic@redhat.com</email>
</author>
<author>
<firstname>Andy</firstname>
<surname>Taylor</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Core Developer</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
<email>ataylor@redhat.com</email>
</author>
<author>
<firstname>Tim</firstname>
<surname>Fox</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Core Developer</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
</author>
<author>
<firstname>Jeff</firstname>
<surname>Mesnil</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Core Developer</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
</author>
<author>
<firstname>Howard</firstname>
<surname>Gao</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Core Developer</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
<email>ghoward@redhat.com</email>
</author>
<author>
<firstname>Francisco</firstname>
<surname>Borges</surname>
</author>
<author>
<firstname>Justin</firstname>
<surname>Bertram</surname>
<affiliation>
<shortaffil>Red Hat, Inc.</shortaffil>
<jobtitle>Core Developer</jobtitle>
<orgdiv>JBoss</orgdiv>
</affiliation>
<email>jbertram@redhat.com</email>
</author>
</authorgroup>

View File

@ -1,48 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<bookinfo id="ActiveMQ_User_Manual">
<title>ActiveMQ User Manual</title>
<subtitle>Putting the buzz in messaging</subtitle>
<productname>ActiveMQ</productname>
<productnumber>2</productnumber>
<edition>2.1.0</edition>
<pubsnumber>1</pubsnumber>
<abstract>
<para>The User manual is an in depth manual on all aspects of ActiveMQ</para>
</abstract>
<!--corpauthor>
<inlinemediaobject>
<imageobject>
<imagedata fileref="images/hornetQ_logo_600px.png" format="PNG"/>
</imageobject>
<textobject>
<phrase>ActiveMQ Logo</phrase>
</textobject>
</inlinemediaobject>
</corpauthor-->
<copyright>
<year>&YEAR;</year>
<holder>&HOLDER;</holder>
</copyright>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml"/>
</bookinfo>

View File

@ -0,0 +1,7 @@
![ActiveMQ logo](images/activemq-logo.jpg)
ActiveMQ User Manual
====================
The User manual is an in depth manual on all aspects of ActiveMQ

View File

@ -0,0 +1,53 @@
* [Legal Notice](notice.md)
* [Preface](preface.md)
* [Project Info](project-info.md)
* [Messaging Concepts](messaging-concepts.md)
* [Architecture](architecture.md)
* [Using the Server](using-server.md)
* [Using JMS](using-jms.md)
* [Using Core](using-core.md)
* [Mapping JMS Concepts to the Core API](jms-core-mapping.md)
* [The Client Classpath](client-classpath.md)
* [Examples](examples.md)
* [Routing Messages With Wild Cards](wildcard-routing.md)
* [Understanding the ActiveMQ Wildcard Syntax](wildcard-syntax.md)
* [Filter Expressions](filter-expressions.md)
* [Persistence](persistence.md)
* [Configuring Transports](configuring-transports.md)
* [Detecting Dead Connections](connection-ttl.md)
* [Detecting Slow Consumers](slow-consumers.md)
* [Resource Manager Configuration](transaction-config.md)
* [Flow Control](flow-control.md)
* [Guarantees of sends and commits](send-guarantees.md)
* [Message Redelivery and Undelivered Messages](undelivered-messages.md)
* [Message Expiry](message-expiry.md)
* [Large Messages](large-messages.md)
* [Paging](paging.md)
* [Queue Attributes](queue-attributes.md)
* [Scheduled Messages](scheduled-messages.md)
* [Last-Value Queues](last-value-queues.md)
* [Message Grouping](message-grouping.md)
* [Extra Acknowledge Modes](pre-acknowledge.md)
* [Management](management.md)
* [Security](security.md)
* [Application Server Integration and Java EE](appserver-integration.md)
* [The JMS Bridge](jms-bridge.md)
* [Client Reconnection and Session Reattachment](client-reconnection.md)
* [Diverting and Splitting Message Flows](diverts.md)
* [Core Bridges](core-bridges.md)
* [Duplicate Message Detection](duplicate-detection.md)
* [Clusters](clusters.md)
* [High Availability and Failover](ha.md)
* [Libaio Native Libraries](libaio.md)
* [Thread management](thread-pooling.md)
* [Logging](logging.md)
* [REST Interface](rest.md)
* [Embedding ActiveMQ](embedding-activemq.md)
* [Spring Integration](spring-integration.md)
* [AeroGear Integration](aerogear-integration.md)
* [VertX Integration](vertx-integration.md)
* [Intercepting Operations](intercepting-operations.md)
* [Interoperability](interoperability.md)
* [Tools](tools.md)
* [Performance Tuning](perf-tuning.md)
* [Configuration Reference](configuration-index.md)

View File

@ -0,0 +1,101 @@
AeroGear Integration
====================
AeroGears push technology provides support for different push
notification technologies like Google Cloud Messaging, Apple's APNs or
Mozilla's SimplePush. ActiveMQ allows you to configure a Connector
Service that will consume messages from a queue and forward them to an
AeroGear push server and subsequently sent as notifications to mobile
devices.
Configuring an AeroGear Connector Service
=========================================
AeroGear Connector services are configured in the connector-services
configuration:
<connector-service name="aerogear-connector">
<factory-class>org.apache.activemq.integration.aerogear.AeroGearConnectorServiceFactory</factory-class>
<param key="endpoint" value="endpoint"/>
<param key="queue" value="jms.queue.aerogearQueue"/>
<param key="application-id" value="an applicationid"/>
<param key="master-secret" value="a mastersecret"/>
</connector-service>
<address-setting match="jms.queue.lastValueQueue">
<last-value-queue>true</last-value-queue>
</address-setting>
Shown are the required params for the connector service and are:
- `endpoint`. The endpoint or URL of you AeroGear application.
- `queue`. The name of the queue to consume from.
- `application-id`. The application id of your mobile application in
AeroGear.
- `master-secret`. The secret of your mobile application in AeroGear.
As well as these required paramaters there are the following optional
parameters
- `ttl`. The time to live for the message once AeroGear receives it.
- `badge`. The badge the mobile app should use for the notification.
- `sound`. The sound the mobile app should use for the notification.
- `filter`. A message filter(selector) to use on the connector.
- `retry-interval`. If an error occurs on send, how long before we try
again to connect.
- `retry-attempts`. How many times we should try to reconnect after an
error.
- `variants`. A comma separated list of variants that should get the
message.
- `aliases`. A list of aliases that should get the message.
- `device-types`. A list of device types that should get the messag.
More in depth explanations of the AeroGear related parameters can be
found in the [AeroGear Push docs](http://aerogear.org/push/)
How to send a message for AeroGear
==================================
To send a message intended for AeroGear simply send a JMS Message and
set the appropriate headers, like so
Message message = session.createMessage();
message.setStringProperty("AEROGEAR_ALERT", "Hello this is a notification from ActiveMQ");
producer.send(message);
The 'AEROGEAR\_ALERT' property will be the alert sent to the mobile
device.
> **Note**
>
> If the message does not contain this property then it will be simply
> ignored and left on the queue
Its also possible to override any of the other AeroGear parameters by
simply setting them on the message, for instance if you wanted to set
ttl of a message you would:
message.setIntProperty("AEROGEAR_TTL", 1234);
or if you wanted to set the list of variants you would use:
message.setStringProperty("AEROGEAR_VARIANTS", "variant1,variant2,variant3");
Again refer to the AeroGear documentation for a more in depth view on
how to use these settings

View File

@ -1,115 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="aerogear-integration">
<title>AeroGear Integration</title>
<para>AeroGears push technology provides support for different push notification technologies like Google Cloud Messaging,
Apple's APNs or Mozilla's SimplePush. ActiveMQ allows you to configure a Connector Service that will consume messages
from a queue and forward them to an AeroGear push server and subsequently sent as notifications to mobile devices.</para>
<section>
<title>Configuring an AeroGear Connector Service</title>
<para>AeroGear Connector services are configured in the connector-services configuration:</para>
<programlisting>
&lt;connector-service name="aerogear-connector">
&lt;factory-class>org.apache.activemq.integration.aerogear.AeroGearConnectorServiceFactory&lt;/factory-class>
&lt;param key="endpoint" value="endpoint"/>
&lt;param key="queue" value="jms.queue.aerogearQueue"/>
&lt;param key="application-id" value="an applicationid"/>
&lt;param key="master-secret" value="a mastersecret"/>
&lt;/connector-service>
&lt;address-setting match="jms.queue.lastValueQueue">
&lt;last-value-queue>true&lt;/last-value-queue>
&lt;/address-setting>
</programlisting>
<para>Shown are the required params for the connector service and are:</para>
<itemizedlist>
<listitem>
<para><literal>endpoint</literal>. The endpoint or URL of you AeroGear application.</para>
</listitem>
<listitem>
<para><literal>queue</literal>. The name of the queue to consume from.</para>
</listitem>
<listitem>
<para><literal>application-id</literal>. The application id of your mobile application in AeroGear.</para>
</listitem>
<listitem>
<para><literal>master-secret</literal>. The secret of your mobile application in AeroGear.</para>
</listitem>
</itemizedlist>
<para>As well as these required paramaters there are the following optional parameters</para>
<itemizedlist>
<listitem>
<para><literal>ttl</literal>. The time to live for the message once AeroGear receives it.</para>
</listitem>
<listitem>
<para><literal>badge</literal>. The badge the mobile app should use for the notification.</para>
</listitem>
<listitem>
<para><literal>sound</literal>. The sound the mobile app should use for the notification.</para>
</listitem>
<listitem>
<para><literal>filter</literal>. A message filter(selector) to use on the connector.</para>
</listitem>
<listitem>
<para><literal>retry-interval</literal>. If an error occurs on send, how long before we try again to connect.</para>
</listitem>
<listitem>
<para><literal>retry-attempts</literal>. How many times we should try to reconnect after an error.</para>
</listitem>
<listitem>
<para><literal>variants</literal>. A comma separated list of variants that should get the message.</para>
</listitem>
<listitem>
<para><literal>aliases</literal>. A list of aliases that should get the message.</para>
</listitem>
<listitem>
<para><literal>device-types</literal>. A list of device types that should get the messag.</para>
</listitem>
</itemizedlist>
<para>More in depth explanations of the AeroGear related parameters can be found in the <ulink
url="http://aerogear.org/push/">AeroGear Push docs</ulink></para>
</section>
<section>
<title>How to send a message for AeroGear</title>
<para>To send a message intended for AeroGear simply send a JMS Message and set the appropriate headers, like so</para>
<programlisting>
Message message = session.createMessage();
message.setStringProperty("AEROGEAR_ALERT", "Hello this is a notification from ActiveMQ");
producer.send(message);
</programlisting>
<para>The 'AEROGEAR_ALERT' property will be the alert sent to the mobile device.</para>
<note><para>If the message does not contain this property then it will be simply ignored and left on the queue</para></note>
<para>Its also possible to override any of the other AeroGear parameters by simply setting them on the message,
for instance if you wanted to set ttl of a message you would:</para>
<programlisting>
message.setIntProperty("AEROGEAR_TTL", 1234);
</programlisting>
<para>or if you wanted to set the list of variants you would use:</para>
<programlisting>
message.setStringProperty("AEROGEAR_VARIANTS", "variant1,variant2,variant3");
</programlisting>
<para>Again refer to the AeroGear documentation for a more in depth view on how to use these settings</para>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,159 @@
Architecture
============
In this section we will give an overview of the ActiveMQ high level
architecture.
Core Architecture
=================
ActiveMQ core is designed simply as set of Plain Old Java Objects
(POJOs) - we hope you like its clean-cut design.
We've also designed it to have as few dependencies on external jars as
possible. In fact, ActiveMQ core has only one jar dependency, netty.jar,
other than the standard JDK classes! This is because we use some of the
netty buffer classes internally.
This allows ActiveMQ to be easily embedded in your own project, or
instantiated in any dependency injection framework such as JBoss
Microcontainer, Spring or Google Guice.
Each ActiveMQ server has its own ultra high performance persistent
journal, which it uses for message and other persistence.
Using a high performance journal allows outrageous persistence message
performance, something not achievable when using a relational database
for persistence.
ActiveMQ clients, potentially on different physical machines interact
with the ActiveMQ server. ActiveMQ currently provides two APIs for
messaging at the client side:
1. Core client API. This is a simple intuitive Java API that allows the
full set of messaging functionality without some of the complexities
of JMS.
2. JMS client API. The standard JMS API is available at the client
side.
JMS semantics are implemented by a thin JMS facade layer on the client
side.
The ActiveMQ server does not speak JMS and in fact does not know
anything about JMS, it is a protocol agnostic messaging server designed
to be used with multiple different protocols.
When a user uses the JMS API on the client side, all JMS interactions
are translated into operations on the ActiveMQ core client API before
being transferred over the wire using the ActiveMQ wire format.
The server always just deals with core API interactions.
A schematic illustrating this relationship is shown in figure 3.1 below:
![ActiveMQ architecture1](images/architecture1.jpg)
Figure 3.1 shows two user applications interacting with a ActiveMQ
server. User Application 1 is using the JMS API, while User Application
2 is using the core client API directly.
You can see from the diagram that the JMS API is implemented by a thin
facade layer on the client side.
ActiveMQ embedded in your own application
=========================================
ActiveMQ core is designed as a set of simple POJOs so if you have an
application that requires messaging functionality internally but you
don't want to expose that as a ActiveMQ server you can directly
instantiate and embed ActiveMQ servers in your own application.
For more information on embedding ActiveMQ, see ?.
ActiveMQ integrated with a JEE application server
=================================================
ActiveMQ provides its own fully functional Java Connector Architecture
(JCA) adaptor which enables it to be integrated easily into any JEE
compliant application server or servlet engine.
JEE application servers provide Message Driven Beans (MDBs), which are a
special type of Enterprise Java Beans (EJBs) that can process messages
from sources such as JMS systems or mail systems.
Probably the most common use of an MDB is to consume messages from a JMS
messaging system.
According to the JEE specification, a JEE application server uses a JCA
adapter to integrate with a JMS messaging system so it can consume
messages for MDBs.
However, the JCA adapter is not only used by the JEE application server
for *consuming* messages via MDBs, it is also used when sending message
to the JMS messaging system e.g. from inside an EJB or servlet.
When integrating with a JMS messaging system from inside a JEE
application server it is always recommended that this is done via a JCA
adaptor. In fact, communicating with a JMS messaging system directly,
without using JCA would be illegal according to the JEE specification.
The application server's JCA service provides extra functionality such
as connection pooling and automatic transaction enlistment, which are
desirable when using messaging, say, from inside an EJB. It is possible
to talk to a JMS messaging system directly from an EJB, MDB or servlet
without going through a JCA adapter, but this is not recommended since
you will not be able to take advantage of the JCA features, such as
caching of JMS sessions, which can result in poor performance.
Figure 3.2 below shows a JEE application server integrating with a
ActiveMQ server via the ActiveMQ JCA adaptor. Note that all
communication between EJB sessions or entity beans and Message Driven
beans go through the adaptor and not directly to ActiveMQ.
The large arrow with the prohibited sign shows an EJB session bean
talking directly to the ActiveMQ server. This is not recommended as
you'll most likely end up creating a new connection and session every
time you want to interact from the EJB, which is an anti-pattern.
![ActiveMQ architecture2](images/architecture2.jpg)
For more information on using the JCA adaptor, please see ?.
ActiveMQ stand-alone server
===========================
ActiveMQ can also be deployed as a stand-alone server. This means a
fully independent messaging server not dependent on a JEE application
server.
The standard stand-alone messaging server configuration comprises a core
messaging server, a JMS service and a JNDI service.
The role of the JMS Service is to deploy any JMS Queue, Topic and
ConnectionFactory instances from any server side `activemq-jms.xml`
configuration files. It also provides a simple management API for
creating and destroying Queues, Topics and ConnectionFactory instances
which can be accessed via JMX or the connection. It is a separate
service to the ActiveMQ core server, since the core server is JMS
agnostic. If you don't want to deploy any JMS Queue, Topic or
ConnectionFactory instances via server side XML configuration and don't
require a JMS management API on the server side then you can disable
this service.
We also include a JNDI server since JNDI is a common requirement when
using JMS to lookup Queues, Topics and ConnectionFactory instances. If
you do not require JNDI then this service can also be disabled. ActiveMQ
allows you to programmatically create JMS and core objects directly on
the client side as opposed to looking them up from JNDI, so a JNDI
server is not always a requirement.
The stand-alone server configuration uses JBoss Microcontainer to
instantiate and enforce dependencies between the components. JBoss
Microcontainer is a very lightweight POJO bootstrapper.
The stand-alone server architecture is shown in figure 3.3 below:
![ActiveMQ architecture3](images/architecture3.jpg)
For more information on server configuration files see ?. \$

View File

@ -1,151 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="architecture">
<title>Architecture</title>
<para>In this section we will give an overview of the ActiveMQ high level architecture.</para>
<section>
<title>Core Architecture</title>
<para>ActiveMQ core is designed simply as set of Plain Old Java Objects (POJOs) - we hope you
like its clean-cut design.</para>
<para>We've also designed it to have as few dependencies on external jars as possible. In
fact, ActiveMQ core has only one jar dependency, netty.jar,
other than the standard JDK classes! This is because we use some of the netty buffer classes
internally.</para>
<para>This allows ActiveMQ to be easily embedded in your own project, or instantiated in any
dependency injection framework such as JBoss Microcontainer, Spring or Google
Guice.</para>
<para>Each ActiveMQ server has its own ultra high performance persistent journal, which it
uses for message and other persistence.</para>
<para>Using a high performance journal allows outrageous persistence message performance,
something not achievable when using a relational database for persistence.</para>
<para>ActiveMQ clients, potentially on different physical machines interact with the ActiveMQ
server. ActiveMQ currently provides two APIs for messaging at the client side:</para>
<para>
<orderedlist>
<listitem>
<para>Core client API. This is a simple intuitive Java API that allows the full
set of messaging functionality without some of the complexities of
JMS.</para>
</listitem>
<listitem>
<para>JMS client API. The standard JMS API is available at the client
side.</para>
</listitem>
</orderedlist>
</para>
<para>JMS semantics are implemented by a thin JMS facade layer on the client side.</para>
<para>The ActiveMQ server does not speak JMS and in fact does not know anything about JMS,
it is a protocol agnostic messaging server designed to be used with multiple different
protocols.</para>
<para>When a user uses the JMS API on the client side, all JMS interactions are translated
into operations on the ActiveMQ core client API before being transferred over the wire
using the ActiveMQ wire format.</para>
<para>The server always just deals with core API interactions.</para>
<para>A schematic illustrating this relationship is shown in figure 3.1 below:</para>
<para>
<graphic fileref="images/architecture1.jpg" align="center"/>
</para>
<para>Figure 3.1 shows two user applications interacting with a ActiveMQ server. User
Application 1 is using the JMS API, while User Application 2 is using the core client
API directly.</para>
<para>You can see from the diagram that the JMS API is implemented by a thin facade layer on
the client side.</para>
</section>
<section>
<title>ActiveMQ embedded in your own application</title>
<para>ActiveMQ core is designed as a set of simple POJOs so if you have an application that
requires messaging functionality internally but you don't want to expose that as a
ActiveMQ server you can directly instantiate and embed ActiveMQ servers in your own
application.</para>
<para>For more information on embedding ActiveMQ, see <xref linkend="embedding-activemq"
/>.</para>
</section>
<section>
<title>ActiveMQ integrated with a JEE application server</title>
<para>ActiveMQ provides its own fully functional Java Connector Architecture (JCA) adaptor
which enables it to be integrated easily into any JEE compliant application server or
servlet engine.</para>
<para>JEE application servers provide Message Driven Beans (MDBs), which are a special type
of Enterprise Java Beans (EJBs) that can process messages from sources such as JMS
systems or mail systems.</para>
<para>Probably the most common use of an MDB is to consume messages from a JMS messaging
system.</para>
<para>According to the JEE specification, a JEE application server uses a JCA adapter to
integrate with a JMS messaging system so it can consume messages for MDBs.</para>
<para>However, the JCA adapter is not only used by the JEE application server for <emphasis
role="italic">consuming</emphasis> messages via MDBs, it is also used when sending
message to the JMS messaging system e.g. from inside an EJB or servlet.</para>
<para>When integrating with a JMS messaging system from inside a JEE application server it
is always recommended that this is done via a JCA adaptor. In fact, communicating with a
JMS messaging system directly, without using JCA would be illegal according to the JEE
specification.</para>
<para>The application server's JCA service provides extra functionality such as connection
pooling and automatic transaction enlistment, which are desirable when using messaging,
say, from inside an EJB. It is possible to talk to a JMS messaging system directly from
an EJB, MDB or servlet without going through a JCA adapter, but this is not recommended
since you will not be able to take advantage of the JCA features, such as caching of JMS
sessions, which can result in poor performance.</para>
<para>Figure 3.2 below shows a JEE application server integrating with a ActiveMQ server via
the ActiveMQ JCA adaptor. Note that all communication between EJB sessions or entity
beans and Message Driven beans go through the adaptor and not directly to
ActiveMQ.</para>
<para>The large arrow with the prohibited sign shows an EJB session bean talking directly to
the ActiveMQ server. This is not recommended as you'll most likely end up creating a new
connection and session every time you want to interact from the EJB, which is an
anti-pattern.</para>
<para>
<graphic fileref="images/architecture2.jpg"/>
</para>
<para>For more information on using the JCA adaptor, please see <xref
linkend="appserver-integration"/>.</para>
</section>
<section>
<title>ActiveMQ stand-alone server</title>
<para>ActiveMQ can also be deployed as a stand-alone server. This means a fully independent
messaging server not dependent on a JEE application server.</para>
<para>The standard stand-alone messaging server configuration comprises a core messaging
server, a JMS service and a JNDI service.</para>
<para>The role of the JMS Service is to deploy any JMS Queue, Topic and ConnectionFactory
instances from any server side <literal>activemq-jms.xml</literal> configuration files.
It also provides a simple management API for creating and destroying Queues, Topics and
ConnectionFactory instances which can be accessed via JMX or the connection. It is a
separate service to the ActiveMQ core server, since the core server is JMS agnostic. If
you don't want to deploy any JMS Queue, Topic or ConnectionFactory instances via server
side XML configuration and don't require a JMS management API on the server side then
you can disable this service.</para>
<para>We also include a JNDI server since JNDI is a common requirement when using JMS to
lookup Queues, Topics and ConnectionFactory instances. If you do not require JNDI then
this service can also be disabled. ActiveMQ allows you to programmatically create JMS and
core objects directly on the client side as opposed to looking them up from JNDI, so a
JNDI server is not always a requirement.</para>
<para>The stand-alone server configuration uses JBoss Microcontainer to instantiate and
enforce dependencies between the components. JBoss Microcontainer is a very lightweight
POJO bootstrapper.</para>
<para>The stand-alone server architecture is shown in figure 3.3 below:</para>
<para>
<graphic fileref="images/architecture3.jpg"/>
</para>
<para>For more information on server configuration files see <xref
linkend="server.configuration"/>. $ </para>
</section>
</chapter>

View File

@ -0,0 +1,12 @@
{
"title": "ActiveMQ Documentation",
"description": "ActiveMQ User Guide and Reference Documentation",
"github": "apache/activemq-6",
"githubHost": "https://github.com/",
"links": {
"home": "http://activemq.apache.org/",
"issues": "http://activemq.apache.org/",
"contribute": "http://activemq.apache.org/contributing.html"
}
}

View File

@ -0,0 +1,32 @@
The Client Classpath
====================
ActiveMQ requires several jars on the *Client Classpath* depending on
whether the client uses ActiveMQ Core API, JMS, and JNDI.
> **Warning**
>
> All the jars mentioned here can be found in the `lib` directory of the
> ActiveMQ distribution. Be sure you only use the jars from the correct
> version of the release, you *must not* mix and match versions of jars
> from different ActiveMQ versions. Mixing and matching different jar
> versions may cause subtle errors and failures to occur.
ActiveMQ Core Client
====================
If you are using just a pure ActiveMQ Core client (i.e. no JMS) then you
need `activemq-core-client.jar`, `activemq-commons.jar`, and `netty.jar`
on your client classpath.
JMS Client
==========
If you are using JMS on the client side, then you will also need to
include `activemq-jms-client.jar` and `jboss-jms-api.jar`.
> **Note**
>
> `jboss-jms-api.jar` just contains Java EE API interface classes needed
> for the `javax.jms.*` classes. If you already have a jar with these
> interface classes on your classpath, you will not need it.

View File

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="client-classpath">
<title>The Client Classpath</title>
<para>ActiveMQ requires several jars on the <emphasis>Client Classpath</emphasis> depending on
whether the client uses ActiveMQ Core API, JMS, and JNDI.</para>
<warning>
<para>All the jars mentioned here can be found in the <literal>lib</literal> directory of
the ActiveMQ distribution. Be sure you only use the jars from the correct version of the
release, you <emphasis>must not</emphasis> mix and match versions of jars from different
ActiveMQ versions. Mixing and matching different jar versions may cause subtle errors and
failures to occur.</para>
</warning>
<section>
<title>ActiveMQ Core Client</title>
<para>If you are using just a pure ActiveMQ Core client (i.e. no JMS) then you need <literal
>activemq-core-client.jar</literal>, <literal>activemq-commons.jar</literal>, and
<literal>netty.jar</literal> on your client classpath.</para>
</section>
<section>
<title>JMS Client</title>
<para>If you are using JMS on the client side, then you will also need to include <literal
>activemq-jms-client.jar</literal> and <literal>jboss-jms-api.jar</literal>.</para>
<note>
<para><literal>jboss-jms-api.jar</literal> just contains Java EE API interface classes
needed for the <literal>javax.jms.*</literal> classes. If you already have a jar
with these interface classes on your classpath, you will not need it.</para>
</note>
</section>
</chapter>

View File

@ -0,0 +1,149 @@
Client Reconnection and Session Reattachment
============================================
ActiveMQ clients can be configured to automatically reconnect or
re-attach to the server in the event that a failure is detected in the
connection between the client and the server.
100% Transparent session re-attachment
======================================
If the failure was due to some transient failure such as a temporary
network failure, and the target server was not restarted, then the
sessions will still be existent on the server, assuming the client
hasn't been disconnected for more than connection-ttl ?.
In this scenario, ActiveMQ will automatically re-attach the client
sessions to the server sessions when the connection reconnects. This is
done 100% transparently and the client can continue exactly as if
nothing had happened.
The way this works is as follows:
As ActiveMQ clients send commands to their servers they store each sent
command in an in-memory buffer. In the case that connection failure
occurs and the client subsequently reattaches to the same server, as
part of the reattachment protocol the server informs the client during
reattachment with the id of the last command it successfully received
from that client.
If the client has sent more commands than were received before failover
it can replay any sent commands from its buffer so that the client and
server can reconcile their states.
The size of this buffer is configured by the `ConfirmationWindowSize`
parameter, when the server has received `ConfirmationWindowSize` bytes
of commands and processed them it will send back a command confirmation
to the client, and the client can then free up space in the buffer.
If you are using JMS and you're using the JMS service on the server to
load your JMS connection factory instances into JNDI then this parameter
can be configured in `activemq-jms.xml` using the element
`confirmation-window-size` a. If you're using JMS but not using JNDI
then you can set these values directly on the
`ActiveMQConnectionFactory` instance using the appropriate setter
method.
If you're using the core API you can set these values directly on the
`ServerLocator` instance using the appropriate setter method.
The window is specified in bytes.
Setting this parameter to `-1` disables any buffering and prevents any
re-attachment from occurring, forcing reconnect instead. The default
value for this parameter is `-1`. (Which means by default no auto
re-attachment will occur)
Session reconnection
====================
Alternatively, the server might have actually been restarted after
crashing or being stopped. In this case any sessions will no longer be
existent on the server and it won't be possible to 100% transparently
re-attach to them.
In this case, ActiveMQ will automatically reconnect the connection and
*recreate* any sessions and consumers on the server corresponding to the
sessions and consumers on the client. This process is exactly the same
as what happens during failover onto a backup server.
Client reconnection is also used internally by components such as core
bridges to allow them to reconnect to their target servers.
Please see the section on failover ? to get a full understanding of how
transacted and non-transacted sessions are reconnected during
failover/reconnect and what you need to do to maintain *once and only
once*delivery guarantees.
Configuring reconnection/reattachment attributes
================================================
Client reconnection is configured using the following parameters:
- `retry-interval`. This optional parameter determines the period in
milliseconds between subsequent reconnection attempts, if the
connection to the target server has failed. The default value is
`2000` milliseconds.
- `retry-interval-multiplier`. This optional parameter determines
determines a multiplier to apply to the time since the last retry to
compute the time to the next retry.
This allows you to implement an *exponential backoff* between retry
attempts.
Let's take an example:
If we set `retry-interval` to `1000` ms and we set
`retry-interval-multiplier` to `2.0`, then, if the first reconnect
attempt fails, we will wait `1000` ms then `2000` ms then `4000` ms
between subsequent reconnection attempts.
The default value is `1.0` meaning each reconnect attempt is spaced
at equal intervals.
- `max-retry-interval`. This optional parameter determines the maximum
retry interval that will be used. When setting
`retry-interval-multiplier` it would otherwise be possible that
subsequent retries exponentially increase to ridiculously large
values. By setting this parameter you can set an upper limit on that
value. The default value is `2000` milliseconds.
- `reconnect-attempts`. This optional parameter determines the total
number of reconnect attempts to make before giving up and shutting
down. A value of `-1` signifies an unlimited number of attempts. The
default value is `0`.
If you're using JMS and you're using JNDI on the client to look up your
JMS connection factory instances then you can specify these parameters
in the JNDI context environment in, e.g. `jndi.properties`:
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url = tcp://localhost:5445
connection.ConnectionFactory.retryInterval=1000
connection.ConnectionFactory.retryIntervalMultiplier=1.5
connection.ConnectionFactory.maxRetryInterval=60000
connection.ConnectionFactory.reconnectAttempts=1000
If you're using JMS, but instantiating your JMS connection factory
directly, you can specify the parameters using the appropriate setter
methods on the `ActiveMQConnectionFactory` immediately after creating
it.
If you're using the core API and instantiating the `ServerLocator`
instance directly you can also specify the parameters using the
appropriate setter methods on the `ServerLocator` immediately after
creating it.
If your client does manage to reconnect but the session is no longer
available on the server, for instance if the server has been restarted
or it has timed out, then the client won't be able to re-attach, and any
`ExceptionListener` or `FailureListener` instances registered on the
connection or session will be called.
ExceptionListeners and SessionFailureListeners
==============================================
Please note, that when a client reconnects or re-attaches, any
registered JMS `ExceptionListener` or core API `SessionFailureListener`
will be called.

View File

@ -1,147 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="client-reconnection">
<title>Client Reconnection and Session Reattachment</title>
<para>ActiveMQ clients can be configured to automatically reconnect or re-attach to the server in
the event that a failure is detected in the connection between the client and the server. </para>
<section>
<title>100% Transparent session re-attachment</title>
<para>If the failure was due to some transient failure such as a temporary network failure,
and the target server was not restarted, then the sessions will still be existent on the
server, assuming the client hasn't been disconnected for more than connection-ttl <xref
linkend="connection-ttl"/>.</para>
<para>In this scenario, ActiveMQ will automatically re-attach the client sessions to the
server sessions when the connection reconnects. This is done 100% transparently and the
client can continue exactly as if nothing had happened.</para>
<para>The way this works is as follows:</para>
<para>As ActiveMQ clients send commands to their servers they store each sent command in an
in-memory buffer. In the case that connection failure occurs and the client subsequently
reattaches to the same server, as part of the reattachment protocol the server informs
the client during reattachment with the id of the last command it successfully received
from that client.</para>
<para>If the client has sent more commands than were received before failover it can replay
any sent commands from its buffer so that the client and server can reconcile their
states.</para>
<para>The size of this buffer is configured by the <literal>ConfirmationWindowSize</literal>
parameter, when the server has received <literal>ConfirmationWindowSize</literal> bytes
of commands and processed them it will send back a command confirmation to the client,
and the client can then free up space in the buffer.</para>
<para>If you are using JMS and you're using the JMS service on the server to load your JMS
connection factory instances into JNDI then this parameter can be configured in <literal
>activemq-jms.xml</literal> using the element <literal
>confirmation-window-size</literal> a. If you're using JMS but not using JNDI then
you can set these values directly on the <literal>ActiveMQConnectionFactory</literal>
instance using the appropriate setter method.</para>
<para>If you're using the core API you can set these values directly on the <literal
>ServerLocator</literal> instance using the appropriate setter method.</para>
<para>The window is specified in bytes.</para>
<para>Setting this parameter to <literal>-1</literal> disables any buffering and prevents
any re-attachment from occurring, forcing reconnect instead. The default value for this
parameter is <literal>-1</literal>. (Which means by default no auto re-attachment will occur)</para>
</section>
<section>
<title>Session reconnection</title>
<para>Alternatively, the server might have actually been restarted after crashing or being
stopped. In this case any sessions will no longer be existent on the server and it won't
be possible to 100% transparently re-attach to them.</para>
<para>In this case, ActiveMQ will automatically reconnect the connection and <emphasis
role="italic">recreate</emphasis> any sessions and consumers on the server
corresponding to the sessions and consumers on the client. This process is exactly the
same as what happens during failover onto a backup server.</para>
<para>Client reconnection is also used internally by components such as core bridges to
allow them to reconnect to their target servers.</para>
<para>Please see the section on failover <xref linkend="ha.automatic.failover"/> to get a
full understanding of how transacted and non-transacted sessions are reconnected during
failover/reconnect and what you need to do to maintain <emphasis role="italic">once and
only once </emphasis>delivery guarantees.</para>
</section>
<section>
<title>Configuring reconnection/reattachment attributes</title>
<para>Client reconnection is configured using the following parameters:</para>
<itemizedlist>
<listitem>
<para><literal>retry-interval</literal>. This optional parameter determines the
period in milliseconds between subsequent reconnection attempts, if the
connection to the target server has failed. The default value is <literal
>2000</literal> milliseconds.</para>
</listitem>
<listitem>
<para><literal>retry-interval-multiplier</literal>. This optional parameter
determines determines a multiplier to apply to the time since the last retry to
compute the time to the next retry.</para>
<para>This allows you to implement an <emphasis>exponential backoff</emphasis>
between retry attempts.</para>
<para>Let's take an example:</para>
<para>If we set <literal>retry-interval</literal> to <literal>1000</literal> ms and
we set <literal>retry-interval-multiplier</literal> to <literal>2.0</literal>,
then, if the first reconnect attempt fails, we will wait <literal>1000</literal>
ms then <literal>2000</literal> ms then <literal>4000</literal> ms between
subsequent reconnection attempts.</para>
<para>The default value is <literal>1.0</literal> meaning each reconnect attempt is
spaced at equal intervals.</para>
</listitem>
<listitem>
<para><literal>max-retry-interval</literal>. This optional parameter determines the
maximum retry interval that will be used. When setting <literal
>retry-interval-multiplier</literal> it would otherwise be possible that
subsequent retries exponentially increase to ridiculously large values. By
setting this parameter you can set an upper limit on that value. The default
value is <literal>2000</literal> milliseconds.</para>
</listitem>
<listitem>
<para><literal>reconnect-attempts</literal>. This optional parameter determines the
total number of reconnect attempts to make before giving up and shutting down. A
value of <literal>-1</literal> signifies an unlimited number of attempts. The
default value is <literal>0</literal>.</para>
</listitem>
</itemizedlist>
<para>If you're using JMS and you're using JNDI on the client to look up your JMS
connection factory instances then you can specify these parameters
in the JNDI context environment in, e.g. <literal>jndi.properties</literal>:</para>
<programlisting>
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url = tcp://localhost:5445
connection.ConnectionFactory.retryInterval=1000
connection.ConnectionFactory.retryIntervalMultiplier=1.5
connection.ConnectionFactory.maxRetryInterval=60000
connection.ConnectionFactory.reconnectAttempts=1000</programlisting>
<para>If you're using JMS, but instantiating your JMS connection factory directly, you can
specify the parameters using the appropriate setter methods on the <literal
>ActiveMQConnectionFactory</literal> immediately after creating it.</para>
<para>If you're using the core API and instantiating the <literal
>ServerLocator</literal> instance directly you can also specify the
parameters using the appropriate setter methods on the <literal
>ServerLocator</literal> immediately after creating it.</para>
<para>If your client does manage to reconnect but the session is no longer available on the
server, for instance if the server has been restarted or it has timed out, then the
client won't be able to re-attach, and any <literal>ExceptionListener</literal> or
<literal>FailureListener</literal> instances registered on the connection or session
will be called.</para>
</section>
<section id="client-reconnection.exceptionlistener">
<title>ExceptionListeners and SessionFailureListeners</title>
<para>Please note, that when a client reconnects or re-attaches, any registered JMS <literal
>ExceptionListener</literal> or core API <literal>SessionFailureListener</literal>
will be called.</para>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@ -1,998 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="clusters">
<title>Clusters</title>
<section>
<title>Clusters Overview</title>
<para>ActiveMQ clusters allow groups of ActiveMQ servers to be grouped together in order to
share message processing load. Each active node in the cluster is an active ActiveMQ
server which manages its own messages and handles its own connections. </para>
<note id="clustered-deprecation">
<para>The <emphasis>clustered</emphasis> parameter is deprecated and no longer needed for
setting up a cluster. If your configuration contains this parameter it will be ignored and
a message with the ID <literal>HQ221038</literal> will be logged.</para>
</note>
<para>The cluster is formed by each node declaring <emphasis>cluster connections</emphasis>
to other nodes in the core configuration file <literal
>activemq-configuration.xml</literal>. When a node forms a cluster connection to
another node, internally it creates a <emphasis>core bridge</emphasis> (as described in
<xref linkend="core-bridges"/>) connection between it and the other node, this is
done transparently behind the scenes - you don't have to declare an explicit bridge for
each node. These cluster connections allow messages to flow between the nodes of the
cluster to balance load.</para>
<para>Nodes can be connected together to form a cluster in many different topologies, we
will discuss a couple of the more common topologies later in this chapter.</para>
<para>We'll also discuss client side load balancing, where we can balance client connections
across the nodes of the cluster, and we'll consider message redistribution where ActiveMQ
will redistribute messages between nodes to avoid starvation.</para>
<para>Another important part of clustering is <emphasis>server discovery</emphasis> where
servers can broadcast their connection details so clients or other servers can connect
to them with the minimum of configuration.</para>
<warning id="copy-warning">
<para>Once a cluster node has been configured it is common to simply copy that configuration
to other nodes to produce a symmetric cluster. However, care must be taken when copying the
ActiveMQ files. Do not copy the ActiveMQ <emphasis>data</emphasis> (i.e. the
<literal>bindings</literal>, <literal>journal</literal>, and <literal>large-messages</literal>
directories) from one node to another. When a node is started for the first time and initializes
its journal files it also persists a special identifier to the <literal>journal</literal>
directory. This id <emphasis>must</emphasis> be unique among nodes in the cluster or the
cluster will not form properly.</para>
</warning>
</section>
<section id="clusters.server-discovery">
<title>Server discovery</title>
<para>Server discovery is a mechanism by which servers can propagate their connection details to:</para>
<itemizedlist>
<listitem>
<para>
Messaging clients. A messaging client wants to be able to connect
to the servers of the cluster without having specific knowledge of which servers
in the cluster are up at any one time.
</para>
</listitem>
<listitem>
<para>Other servers. Servers in a cluster want to be able to create
cluster connections to each other without having prior knowledge of all the
other servers in the cluster.</para>
</listitem>
</itemizedlist>
<para>
This information, let's call it the Cluster Topology, is actually sent around normal ActiveMQ
connections to clients and to other servers over cluster connections. This being the case we need a
way of establishing the initial first connection. This can be done using
dynamic discovery techniques like <ulink url="http://en.wikipedia.org/wiki/User_Datagram_Protocol" >UDP</ulink>
and <ulink url="http://www.jgroups.org/">JGroups</ulink>, or by
providing a list of initial connectors.
</para>
<section>
<title>Dynamic Discovery</title>
<para>
Server discovery uses <ulink url="http://en.wikipedia.org/wiki/User_Datagram_Protocol" >UDP</ulink>
multicast or <ulink url="http://www.jgroups.org/">JGroups</ulink> to broadcast server connection settings.
</para>
<section id="clusters.broadcast-groups">
<title>Broadcast Groups</title>
<para>A broadcast group is the means by which a server broadcasts connectors over the
network. A connector defines a way in which a client (or other server) can make
connections to the server. For more information on what a connector is, please see
<xref linkend="configuring-transports"/>.</para>
<para>The broadcast group takes a set of connector pairs, each connector pair contains
connection settings for a live and backup server (if one exists) and broadcasts them on
the network. Depending on which broadcasting technique you configure the cluster, it
uses either UDP or JGroups to broadcast connector pairs information.</para>
<para>Broadcast groups are defined in the server configuration file <literal
>activemq-configuration.xml</literal>. There can be many broadcast groups per
ActiveMQ server. All broadcast groups must be defined in a <literal
>broadcast-groups</literal> element.</para>
<para>Let's take a look at an example broadcast group from <literal
>activemq-configuration.xml</literal> that defines a UDP broadcast group:</para>
<programlisting>
&lt;broadcast-groups>
&lt;broadcast-group name="my-broadcast-group">
&lt;local-bind-address>172.16.9.3&lt;/local-bind-address>
&lt;local-bind-port>5432&lt;/local-bind-port>
&lt;group-address>231.7.7.7&lt;/group-address>
&lt;group-port>9876&lt;/group-port>
&lt;broadcast-period>2000&lt;/broadcast-period>
&lt;connector-ref connector-name="netty-connector"/>
&lt;/broadcast-group>
&lt;/broadcast-groups></programlisting>
<para>Some of the broadcast group parameters are optional and you'll normally use the
defaults, but we specify them all in the above example for clarity. Let's discuss
each one in turn:</para>
<itemizedlist>
<listitem>
<para><literal>name</literal> attribute. Each broadcast group in the server must
have a unique name. </para>
</listitem>
<listitem>
<para><literal>local-bind-address</literal>. This is the local bind address that
the datagram socket is bound to. If you have multiple network interfaces on
your server, you would specify which one you wish to use for broadcasts by
setting this property. If this property is not specified then the socket
will be bound to the wildcard address, an IP address chosen by the
kernel. This is a UDP specific attribute.</para>
</listitem>
<listitem>
<para><literal>local-bind-port</literal>. If you want to specify a local port to
which the datagram socket is bound you can specify it here. Normally you
would just use the default value of <literal>-1</literal> which signifies
that an anonymous port should be used. This parameter is always specified in conjunction with
<literal>local-bind-address</literal>. This is a UDP specific attribute.</para>
</listitem>
<listitem>
<para><literal>group-address</literal>. This is the multicast address to which
the data will be broadcast. It is a class D IP address in the range <literal
>224.0.0.0</literal> to <literal>239.255.255.255</literal>, inclusive.
The address <literal>224.0.0.0</literal> is reserved and is not available
for use. This parameter is mandatory. This is a UDP specific attribute.</para>
</listitem>
<listitem>
<para><literal>group-port</literal>. This is the UDP port number used for
broadcasting. This parameter is mandatory. This is a UDP specific attribute.</para>
</listitem>
<listitem>
<para><literal>broadcast-period</literal>. This is the period in milliseconds
between consecutive broadcasts. This parameter is optional, the default
value is <literal>2000</literal> milliseconds.</para>
</listitem>
<listitem>
<para><literal>connector-ref</literal>. This specifies the connector and
optional backup connector that will be broadcasted (see <xref
linkend="configuring-transports"/> for more information on connectors).
The connector to be broadcasted is specified by the <literal
>connector-name</literal> attribute.</para>
</listitem>
</itemizedlist>
<para id="clusters.jgroups-example">Here is another example broadcast group that defines a JGroups broadcast group:</para>
<programlisting>
&lt;broadcast-groups>
&lt;broadcast-group name="my-broadcast-group">
&lt;jgroups-file>test-jgroups-file_ping.xml&lt;/jgroups-file>
&lt;jgroups-channel>activemq_broadcast_channel&lt;/jgroups-channel>
&lt;broadcast-period>2000&lt;/broadcast-period>
&lt;connector-ref connector-name="netty-connector"/>
&lt;/broadcast-group>
&lt;/broadcast-groups></programlisting>
<para>To be able to use JGroups to broadcast, one must specify two attributes, i.e.
<literal>jgroups-file</literal> and <literal>jgroups-channel</literal>, as discussed
in details as following:</para>
<itemizedlist>
<listitem>
<para><literal>jgroups-file</literal> attribute. This is the name of JGroups configuration
file. It will be used to initialize JGroups channels. Make sure the file is in the
java resource path so that ActiveMQ can load it. </para>
</listitem>
<listitem>
<para><literal>jgroups-channel</literal> attribute. The name that JGroups channels connect
to for broadcasting.</para>
</listitem>
</itemizedlist>
<note>
<para>The JGroups attributes (<literal>jgroups-file</literal> and <literal>jgroups-channel</literal>)
and UDP specific attributes described above are exclusive of each other. Only one set can be
specified in a broadcast group configuration. Don't mix them!</para>
</note>
<para id="clusters.jgroups-file">
The following is an example of a JGroups file
<programlisting>
&lt;config xmlns="urn:org:jgroups"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/JGroups-3.0.xsd">
&lt;TCP loopback="true"
recv_buf_size="20000000"
send_buf_size="640000"
discard_incompatible_packets="true"
max_bundle_size="64000"
max_bundle_timeout="30"
enable_bundling="true"
use_send_queues="false"
sock_conn_timeout="300"
thread_pool.enabled="true"
thread_pool.min_threads="1"
thread_pool.max_threads="10"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="false"
thread_pool.queue_max_size="100"
thread_pool.rejection_policy="run"
oob_thread_pool.enabled="true"
oob_thread_pool.min_threads="1"
oob_thread_pool.max_threads="8"
oob_thread_pool.keep_alive_time="5000"
oob_thread_pool.queue_enabled="false"
oob_thread_pool.queue_max_size="100"
oob_thread_pool.rejection_policy="run"/>
&lt;FILE_PING location="../file.ping.dir"/>
&lt;MERGE2 max_interval="30000"
min_interval="10000"/>
&lt;FD_SOCK/>
&lt;FD timeout="10000" max_tries="5" />
&lt;VERIFY_SUSPECT timeout="1500" />
&lt;BARRIER />
&lt;pbcast.NAKACK
use_mcast_xmit="false"
retransmit_timeout="300,600,1200,2400,4800"
discard_delivered_msgs="true"/>
&lt;UNICAST timeout="300,600,1200" />
&lt;pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
max_bytes="400000"/>
&lt;pbcast.GMS print_local_addr="true" join_timeout="3000"
view_bundling="true"/>
&lt;FC max_credits="2000000"
min_threshold="0.10"/>
&lt;FRAG2 frag_size="60000" />
&lt;pbcast.STATE_TRANSFER/>
&lt;pbcast.FLUSH timeout="0"/>
&lt;/config></programlisting>
</para>
<para>
As it shows, the file content defines a jgroups protocol stacks. If you want activemq
to use this stacks for channel creation, you have to make sure the value of
<literal>jgroups-file</literal> in your broadcast-group/discovery-group configuration
to be the name of this jgroups configuration file. For example if the above stacks
configuration is stored in a file named "jgroups-stacks.xml" then your
<literal>jgroups-file</literal> should be like
<programlisting>
&lt;jgroups-file>jgroups-stacks.xml&lt;/jgroups-file></programlisting>
</para>
</section>
<section id="clusters.discovery-groups">
<title>Discovery Groups</title>
<para>While the broadcast group defines how connector information is broadcasted from a
server, a discovery group defines how connector information is received from a
broadcast endpoint (a UDP multicast address or JGroup channel).</para>
<para>A discovery group maintains a list of connector pairs - one for each broadcast by
a different server. As it receives broadcasts on the broadcast endpoint from a
particular server it updates its entry in the list for that server.</para>
<para>If it has not received a broadcast from a particular server for a length of time
it will remove that server's entry from its list.</para>
<para>Discovery groups are used in two places in ActiveMQ:</para>
<itemizedlist>
<listitem>
<para>By cluster connections so they know how to obtain an initial connection to download the topology</para>
</listitem>
<listitem>
<para>By messaging clients so they know how to obtain an initial connection to download the topology</para>
</listitem>
</itemizedlist>
<para>
Although a discovery group will always accept broadcasts, its current list of available live and
backup servers is only ever used when an initial connection is made, from then server discovery is
done over the normal ActiveMQ connections.
</para>
<note>
<para>
Each discovery group must be configured with broadcast endpoint (UDP or JGroups) that matches its broadcast
group counterpart. For example, if broadcast is configured using UDP, the discovery group must also use UDP, and the same
multicast address.
</para>
</note>
</section>
<section>
<title>Defining Discovery Groups on the Server</title>
<para>For cluster connections, discovery groups are defined in the server side
configuration file <literal>activemq-configuration.xml</literal>. All discovery
groups must be defined inside a <literal>discovery-groups</literal> element. There
can be many discovery groups defined by ActiveMQ server. Let's look at an
example:</para>
<programlisting>
&lt;discovery-groups>
&lt;discovery-group name="my-discovery-group">
&lt;local-bind-address>172.16.9.7&lt;/local-bind-address>
&lt;group-address>231.7.7.7&lt;/group-address>
&lt;group-port>9876&lt;/group-port>
&lt;refresh-timeout>10000&lt;/refresh-timeout>
&lt;/discovery-group>
&lt;/discovery-groups></programlisting>
<para>We'll consider each parameter of the discovery group:</para>
<itemizedlist>
<listitem>
<para><literal>name</literal> attribute. Each discovery group must have a unique
name per server.</para>
</listitem>
<listitem>
<para><literal>local-bind-address</literal>. If you are running with multiple network interfaces on the same machine, you
may want to specify that the discovery group listens only only a specific interface. To do this you can specify the interface
address with this parameter. This parameter is optional. This is a UDP specific attribute.</para>
</listitem>
<listitem>
<para><literal>group-address</literal>. This is the multicast IP address of the
group to listen on. It should match the <literal>group-address</literal> in
the broadcast group that you wish to listen from. This parameter is
mandatory. This is a UDP specific attribute.</para>
</listitem>
<listitem>
<para><literal>group-port</literal>. This is the UDP port of the multicast
group. It should match the <literal>group-port</literal> in the broadcast
group that you wish to listen from. This parameter is mandatory. This is a UDP specific attribute.</para>
</listitem>
<listitem>
<para><literal>refresh-timeout</literal>. This is the period the discovery group
waits after receiving the last broadcast from a particular server before
removing that servers connector pair entry from its list. You would normally
set this to a value significantly higher than the <literal
>broadcast-period</literal> on the broadcast group otherwise servers
might intermittently disappear from the list even though they are still
broadcasting due to slight differences in timing. This parameter is
optional, the default value is <literal>10000</literal> milliseconds (10
seconds).</para>
</listitem>
</itemizedlist>
<para>Here is another example that defines a JGroups discovery group:</para>
<programlisting>
&lt;discovery-groups>
&lt;discovery-group name="my-broadcast-group">
&lt;jgroups-file>test-jgroups-file_ping.xml&lt;/jgroups-file>
&lt;jgroups-channel>activemq_broadcast_channel&lt;/jgroups-channel>
&lt;refresh-timeout>10000&lt;/refresh-timeout>
&lt;/discovery-group>
&lt;/discovery-groups></programlisting>
<para>To receive broadcast from JGroups channels, one must specify two attributes,
<literal>jgroups-file</literal> and <literal>jgroups-channel</literal>, as discussed
in details as following:</para>
<itemizedlist>
<listitem>
<para><literal>jgroups-file</literal> attribute. This is the name of JGroups configuration
file. It will be used to initialize JGroups channels. Make sure the file is in the
java resource path so that ActiveMQ can load it. </para>
</listitem>
<listitem>
<para><literal>jgroups-channel</literal> attribute. The name that JGroups channels connect
to for receiving broadcasts.</para>
</listitem>
</itemizedlist>
<note>
<para>The JGroups attributes (<literal>jgroups-file</literal> and <literal>jgroups-channel</literal>)
and UDP specific attributes described above are exclusive of each other. Only one set can be
specified in a discovery group configuration. Don't mix them!</para>
</note>
</section>
<section id="clusters-discovery.groups.clientside">
<title>Discovery Groups on the Client Side</title>
<para>Let's discuss how to configure a ActiveMQ client to use discovery to discover a
list of servers to which it can connect. The way to do this differs depending on
whether you're using JMS or the core API.</para>
<section>
<title>Configuring client discovery using JMS</title>
<para>If you're using JMS and you're using JNDI on the client to look up your JMS
connection factory instances then you can specify these parameters in the JNDI
context environment. e.g. in <literal>jndi.properties</literal>. Simply ensure the
host:port combination matches the group-address and group-port from the corresponding
<literal>broadcast-group</literal> on the server. Let's take a look at an
example:</para>
<programlisting>
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url = udp://231.7.7.7:9876</programlisting>
<para>The element <literal>discovery-group-ref</literal> specifies the name of a
discovery group defined in <literal>activemq-configuration.xml</literal>.</para>
<para>When this connection factory is downloaded from JNDI by a client application
and JMS connections are created from it, those connections will be load-balanced
across the list of servers that the discovery group maintains by listening on
the multicast address specified in the discovery group configuration.</para>
<para>If you're using JMS, but you're not using JNDI to lookup a connection factory
- you're instantiating the JMS connection factory directly then you can specify
the discovery group parameters directly when creating the JMS connection
factory. Here's an
example:</para>
<programlisting>
final String groupAddress = "231.7.7.7";
final int groupPort = 9876;
ConnectionFactory jmsConnectionFactory =
ActiveMQJMSClient.createConnectionFactory(new DiscoveryGroupConfiguration(groupAddress, groupPort,
new UDPBroadcastGroupConfiguration(groupAddress, groupPort, null, -1)), JMSFactoryType.CF);
Connection jmsConnection1 = jmsConnectionFactory.createConnection();
Connection jmsConnection2 = jmsConnectionFactory.createConnection();</programlisting>
<para>The <literal>refresh-timeout</literal> can be set directly on the DiscoveryGroupConfiguration
by using the setter method <literal>setDiscoveryRefreshTimeout()</literal> if you
want to change the default value.</para>
<para>There is also a further parameter settable on the DiscoveryGroupConfiguration using the
setter method <literal>setDiscoveryInitialWaitTimeout()</literal>. If the connection
factory is used immediately after creation then it may not have had enough time
to received broadcasts from all the nodes in the cluster. On first usage, the
connection factory will make sure it waits this long since creation before
creating the first connection. The default value for this parameter is <literal
>10000</literal> milliseconds.</para>
</section>
<section>
<title>Configuring client discovery using Core</title>
<para>If you're using the core API to directly instantiate
<literal>ClientSessionFactory</literal> instances, then you can specify the
discovery group parameters directly when creating the session factory. Here's an
example:</para>
<programlisting>
final String groupAddress = "231.7.7.7";
final int groupPort = 9876;
ServerLocator factory = ActiveMQClient.createServerLocatorWithHA(new DiscoveryGroupConfiguration(groupAddress, groupPort,
new UDPBroadcastGroupConfiguration(groupAddress, groupPort, null, -1))));
ClientSessionFactory factory = locator.createSessionFactory();
ClientSession session1 = factory.createSession();
ClientSession session2 = factory.createSession();</programlisting>
<para>The <literal>refresh-timeout</literal> can be set directly on the DiscoveryGroupConfiguration
by using the setter method <literal>setDiscoveryRefreshTimeout()</literal> if you
want to change the default value.</para>
<para>There is also a further parameter settable on the DiscoveryGroupConfiguration using the
setter method <literal>setDiscoveryInitialWaitTimeout()</literal>. If the session factory
is used immediately after creation then it may not have had enough time to
received broadcasts from all the nodes in the cluster. On first usage, the
session factory will make sure it waits this long since creation before creating
the first session. The default value for this parameter is <literal
>10000</literal> milliseconds.</para>
</section>
</section>
</section>
<section>
<title>Discovery using static Connectors</title>
<para>Sometimes it may be impossible to use UDP on the network you are using. In this case its
possible to configure a connection with an initial list if possible servers. This could be just
one server that you know will always be available or a list of servers where at least one will
be available.</para>
<para>This doesn't mean that you have to know where all your servers are going to be hosted, you
can configure these servers to use the reliable servers to connect to. Once they are connected
there connection details will be propagated via the server it connects to</para>
<section>
<title>Configuring a Cluster Connection</title>
<para>For cluster connections there is no extra configuration needed, you just need to make sure that any
connectors are defined in the usual manner, (see <xref linkend="configuring-transports"/> for more
information on connectors). These are then referenced by the cluster connection configuration.</para>
</section>
<section>
<title>Configuring a Client Connection</title>
<para>A static list of possible servers can also be used by a normal client.</para>
<section>
<title>Configuring client discovery using JMS</title>
<para>If you're using JMS and you're using JNDI on the client to look up your JMS
connection factory instances then you can specify these parameters
in the JNDI context environment in, e.g. <literal>jndi.properties</literal>:</para>
<programlisting>
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://myhost:5445,myhost2:5445</programlisting>
<para>
The <literal>java.naming.provider.url</literal> contains a list of servers to use for the
connection factory. When this connection factory used client application and JMS connections
are created from it, those connections will be load-balanced across the list of servers defined
by the <literal>java.naming.provider.url</literal>.
</para>
<para>
If you're using JMS, but you're not using JNDI to lookup a connection factory - you're instantiating
the JMS connection factory directly then you can specify the connector list directly when creating
the JMS connection factory. Here's an example:
</para>
<programlisting>
HashMap&lt;String, Object> map = new HashMap&lt;String, Object>();
map.put("host", "myhost");
map.put("port", "5445");
TransportConfiguration server1 = new TransportConfiguration(NettyConnectorFactory.class.getName(), map);
HashMap&lt;String, Object> map2 = new HashMap&lt;String, Object>();
map2.put("host", "myhost2");
map2.put("port", "5446");
TransportConfiguration server2 = new TransportConfiguration(NettyConnectorFactory.class.getName(), map2);
ActiveMQConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithHA(JMSFactoryType.CF, server1, server2);</programlisting>
</section>
<section>
<title>Configuring client discovery using Core</title>
<para>If you are using the core API then the same can be done as follows:</para>
<programlisting>
HashMap&lt;String, Object> map = new HashMap&lt;String, Object>();
map.put("host", "myhost");
map.put("port", "5445");
TransportConfiguration server1 = new TransportConfiguration(NettyConnectorFactory.class.getName(), map);
HashMap&lt;String, Object> map2 = new HashMap&lt;String, Object>();
map2.put("host", "myhost2");
map2.put("port", "5446");
TransportConfiguration server2 = new TransportConfiguration(NettyConnectorFactory.class.getName(), map2);
ServerLocator locator = ActiveMQClient.createServerLocatorWithHA(server1, server2);
ClientSessionFactory factory = locator.createSessionFactory();
ClientSession session = factory.createSession();</programlisting>
</section>
</section>
</section>
</section>
<section>
<title>Server-Side Message Load Balancing</title>
<para>If cluster connections are defined between nodes of a cluster, then ActiveMQ will load
balance messages arriving at a particular node from a client.</para>
<para>Let's take a simple example of a cluster of four nodes A, B, C, and D arranged in a
<emphasis>symmetric cluster</emphasis> (described in
<xref linkend="symmetric-cluster"/>). We have a queue called <literal>OrderQueue</literal>
deployed on each node of the cluster.</para>
<para>We have client Ca connected to node A, sending orders to the server. We have also have
order processor clients Pa, Pb, Pc, and Pd connected to each of the nodes A, B, C, D. If
no cluster connection was defined on node A, then as order messages arrive on node A
they will all end up in the <literal>OrderQueue</literal> on node A, so will only get
consumed by the order processor client attached to node A, Pa.</para>
<para>If we define a cluster connection on node A, then as ordered messages arrive on node A
instead of all of them going into the local <literal>OrderQueue</literal> instance, they
are distributed in a round-robin fashion between all the nodes of the cluster. The
messages are forwarded from the receiving node to other nodes of the cluster. This is
all done on the server side, the client maintains a single connection to node A.</para>
<para>For example, messages arriving on node A might be distributed in the following order
between the nodes: B, D, C, A, B, D, C, A, B, D. The exact order depends on the order
the nodes started up, but the algorithm used is round robin.</para>
<para>ActiveMQ cluster connections can be configured to always blindly load balance messages
in a round robin fashion irrespective of whether there are any matching consumers on
other nodes, but they can be a bit cleverer than that and also be configured to only
distribute to other nodes if they have matching consumers. We'll look at both these
cases in turn with some examples, but first we'll discuss configuring cluster
connections in general.</para>
<section id="clusters.cluster-connections">
<title>Configuring Cluster Connections</title>
<para>Cluster connections group servers into clusters so that messages can be load
balanced between the nodes of the cluster. Let's take a look at a typical cluster
connection. Cluster connections are always defined in <literal
>activemq-configuration.xml</literal> inside a <literal
>cluster-connection</literal> element. There can be zero or more cluster
connections defined per ActiveMQ server.</para>
<programlisting>
&lt;cluster-connections>
&lt;cluster-connection name="my-cluster">
&lt;address>jms&lt;/address>
&lt;connector-ref>netty-connector&lt;/connector-ref>
&lt;check-period>1000&lt;/check-period>
&lt;connection-ttl>5000&lt;/connection-ttl>
&lt;min-large-message-size>50000&lt;/min-large-message-size>
&lt;call-timeout>5000&lt;/call-timeout>
&lt;retry-interval>500&lt;/retry-interval>
&lt;retry-interval-multiplier>1.0&lt;/retry-interval-multiplier>
&lt;max-retry-interval>5000&lt;/max-retry-interval>
&lt;initial-connect-attempts>-1&lt;/initial-connect-attempts>
&lt;reconnect-attempts>-1&lt;/reconnect-attempts>
&lt;use-duplicate-detection>true&lt;/use-duplicate-detection>
&lt;forward-when-no-consumers>false&lt;/forward-when-no-consumers>
&lt;max-hops>1&lt;/max-hops>
&lt;confirmation-window-size>32000&lt;/confirmation-window-size>
&lt;call-failover-timeout>30000&lt;/call-failover-timeout>
&lt;notification-interval>1000&lt;/notification-interval>
&lt;notification-attempts>2&lt;/notification-attempts>
&lt;discovery-group-ref discovery-group-name="my-discovery-group"/>
&lt;/cluster-connection>
&lt;/cluster-connections></programlisting>
<para>In the above cluster connection all parameters have been explicitly specified. The following
shows all the available configuration options</para>
<itemizedlist>
<listitem id="clusters.address">
<para><literal>address</literal> Each cluster connection only applies to addresses that match the
specified address field. An address is matched on the cluster connection when it begins with the
string specified in this field. The address field on a cluster connection also supports comma
separated lists and an exclude syntax '!'. To prevent an address from being matched on this
cluster connection, prepend a cluster connection address string with '!'.</para>
<para>In the case shown above the cluster connection will load balance messages sent to
addresses that start with <literal>jms</literal>. This cluster connection,
will, in effect apply to all JMS queues and topics since they map to core
queues that start with the substring "jms".</para>
<para>The address can be any value and you can have many cluster connections
with different values of <literal>address</literal>, simultaneously
balancing messages for those addresses, potentially to different clusters of
servers. By having multiple cluster connections on different addresses a
single ActiveMQ Server can effectively take part in multiple clusters
simultaneously.</para>
<para>Be careful not to have multiple cluster connections with overlapping
values of <literal>address</literal>, e.g. "europe" and "europe.news" since
this could result in the same messages being distributed between more than
one cluster connection, possibly resulting in duplicate deliveries.</para>
<para>
Examples:
<itemizedlist>
<listitem><literal>'jms.eu'</literal> matches all addresses starting with 'jms.eu'</listitem>
<listitem><literal>'!jms.eu'</literal> matches all address except for those starting with
'jms.eu'</listitem>
<listitem><literal>'jms.eu.uk,jms.eu.de'</literal> matches all addresses starting with either
'jms.eu.uk' or 'jms.eu.de'</listitem>
<listitem><literal>'jms.eu,!jms.eu.uk'</literal> matches all addresses starting with 'jms.eu'
but not those starting with 'jms.eu.uk'</listitem>
</itemizedlist>
Notes:
<itemizedlist>
<listitem>Address exclusion will always takes precedence over address inclusion.</listitem>
<listitem>Address matching on cluster connections does not support wild-card matching.
</listitem>
</itemizedlist>
</para>
<para>This parameter is mandatory.</para>
</listitem>
<listitem>
<para><literal>connector-ref</literal>. This is the connector which will be sent to other nodes in
the cluster so they have the correct cluster topology.</para>
<para>This parameter is mandatory.</para>
</listitem>
<listitem>
<para><literal>check-period</literal>. The period (in milliseconds) used to check if the cluster connection
has failed to receive pings from another server. Default is 30000.</para>
</listitem>
<listitem>
<para><literal>connection-ttl</literal>. This is how long a cluster connection should stay alive if it
stops receiving messages from a specific node in the cluster. Default is 60000.</para>
</listitem>
<listitem>
<para><literal>min-large-message-size</literal>. If the message size (in bytes) is larger than this
value then it will be split into multiple segments when sent over the network to other cluster
members. Default is 102400.</para>
</listitem>
<listitem>
<para><literal>call-timeout</literal>. When a packet is sent via a cluster connection and is a blocking
call, i.e. for acknowledgements, this is how long it will wait (in milliseconds) for the reply before
throwing an exception. Default is 30000.</para>
</listitem>
<listitem>
<para><literal>retry-interval</literal>. We mentioned before that, internally,
cluster connections cause bridges to be created between the nodes of the
cluster. If the cluster connection is created and the target node has not
been started, or say, is being rebooted, then the cluster connections from
other nodes will retry connecting to the target until it comes back up, in
the same way as a bridge does.</para>
<para>This parameter determines the interval in milliseconds between retry
attempts. It has the same meaning as the <literal>retry-interval</literal>
on a bridge (as described in <xref linkend="core-bridges"/>).</para>
<para>This parameter is optional and its default value is <literal>500</literal>
milliseconds.</para>
</listitem>
<listitem>
<para><literal>retry-interval-multiplier</literal>. This is a multiplier used to increase the
<literal>retry-interval</literal> after each reconnect attempt, default is 1.</para>
</listitem>
<listitem>
<para><literal>max-retry-interval</literal>. The maximum delay (in milliseconds) for retries.
Default is 2000.</para>
</listitem>
<listitem>
<para><literal>initial-connect-attempts</literal>. The number of times the system will
try to connect a node in the cluster initially. If the max-retry is achieved this
node will be considered permanently down and the system will not route messages
to this node. Default is -1 (infinite retries).</para>
</listitem>
<listitem>
<para><literal>reconnect-attempts</literal>. The number of times the system will
try to reconnect to a node in the cluster. If the max-retry is achieved this node will
be considered permanently down and the system will stop routing messages to this
node. Default is -1 (infinite retries).</para>
</listitem>
<listitem>
<para><literal>use-duplicate-detection</literal>. Internally cluster connections
use bridges to link the nodes, and bridges can be configured to add a
duplicate id property in each message that is forwarded. If the target node
of the bridge crashes and then recovers, messages might be resent from the
source node. By enabling duplicate detection any duplicate messages will be
filtered out and ignored on receipt at the target node.</para>
<para>This parameter has the same meaning as <literal>use-duplicate-detection</literal>
on a bridge. For more information on duplicate detection, please see
<xref linkend="duplicate-detection"/>. Default is true.</para>
</listitem>
<listitem>
<para><literal>forward-when-no-consumers</literal>. This parameter determines
whether messages will be distributed round robin between other nodes of the
cluster <emphasis>regardless</emphasis> of whether or not there are matching or
indeed any consumers on other nodes. </para>
<para>If this is set to <literal>true</literal> then each incoming message will
be round robin'd even though the same queues on the other nodes of the
cluster may have no consumers at all, or they may have consumers that have
non matching message filters (selectors). Note that ActiveMQ will
<emphasis>not</emphasis> forward messages to other nodes if there are no
<emphasis>queues</emphasis> of the same name on the other nodes, even if
this parameter is set to <literal>true</literal>.</para>
<para>If this is set to <literal>false</literal> then ActiveMQ will only forward
messages to other nodes of the cluster if the address to which they are
being forwarded has queues which have consumers, and if those consumers have
message filters (selectors) at least one of those selectors must match the
message.</para>
<para>Default is false.</para>
</listitem>
<listitem>
<para><literal>max-hops</literal>. When a cluster connection decides the set of
nodes to which it might load balance a message, those nodes do not have to
be directly connected to it via a cluster connection. ActiveMQ can be
configured to also load balance messages to nodes which might be connected
to it only indirectly with other ActiveMQ servers as intermediates in a
chain.</para>
<para>This allows ActiveMQ to be configured in more complex topologies and still
provide message load balancing. We'll discuss this more later in this
chapter.</para>
<para>The default value for this parameter is <literal>1</literal>, which means
messages are only load balanced to other ActiveMQ serves which are directly
connected to this server. This parameter is optional.</para>
</listitem>
<listitem>
<para><literal>confirmation-window-size</literal>. The size (in bytes) of the window
used for sending confirmations from the server connected to. So once the server has
received <literal>confirmation-window-size</literal> bytes it notifies its client,
default is 1048576. A value of -1 means no window.</para>
</listitem>
<listitem>
<para><literal>call-failover-timeout</literal>. Similar to <literal>call-timeout</literal> but used
when a call is made during a failover attempt. Default is -1 (no timeout).</para>
</listitem>
<listitem>
<para><literal>notification-interval</literal>. How often (in milliseconds) the cluster connection
should broadcast itself when attaching to the cluster. Default is 1000.</para>
</listitem>
<listitem>
<para><literal>notification-attempts</literal>. How many times the cluster connection should
broadcast itself when connecting to the cluster. Default is 2.</para>
</listitem>
<listitem>
<para><literal>discovery-group-ref</literal>. This parameter determines which
discovery group is used to obtain the list of other servers in the cluster
that this cluster connection will make connections to.</para>
</listitem>
</itemizedlist>
<para>
Alternatively if you would like your cluster connections to use a static list of
servers for discovery then you can do it like this.
</para>
<programlisting>
&lt;cluster-connection name="my-cluster">
...
&lt;static-connectors>
&lt;connector-ref>server0-connector&lt;/connector-ref>
&lt;connector-ref>server1-connector&lt;/connector-ref>
&lt;/static-connectors>
&lt;/cluster-connection></programlisting>
<para>
Here we have defined 2 servers that we know for sure will that at least one will be available. There may
be many more servers in the cluster but these will; be discovered via one of these connectors once an
initial connection has been made.</para>
</section>
<section id="clusters.clusteruser">
<title>Cluster User Credentials</title>
<para>When creating connections between nodes of a cluster to form a cluster connection,
ActiveMQ uses a cluster user and cluster password which is defined in <literal
>activemq-configuration.xml</literal>:</para>
<programlisting>
&lt;cluster-user>ACTIVEMQ.CLUSTER.ADMIN.USER&lt;/cluster-user>
&lt;cluster-password>CHANGE ME!!&lt;/cluster-password></programlisting>
<warning>
<para>It is imperative that these values are changed from their default, or remote
clients will be able to make connections to the server using the default values.
If they are not changed from the default, ActiveMQ will detect this and pester
you with a warning on every start-up.</para>
</warning>
</section>
</section>
<section id="clusters.client.loadbalancing">
<title>Client-Side Load balancing</title>
<para>With ActiveMQ client-side load balancing, subsequent sessions created using a single
session factory can be connected to different nodes of the cluster. This allows sessions
to spread smoothly across the nodes of a cluster and not be "clumped" on any particular
node.</para>
<para>The load balancing policy to be used by the client factory is configurable. ActiveMQ
provides four out-of-the-box load balancing policies, and you can also implement your own
and use that.</para>
<para>The out-of-the-box policies are</para>
<itemizedlist>
<listitem>
<para>Round Robin. With this policy the first node is chosen randomly then each
subsequent node is chosen sequentially in the same order.</para>
<para>For example nodes might be chosen in the order B, C, D, A, B, C, D, A, B or D,
A, B, C, D, A, B, C, D or C, D, A, B, C, D, A, B, C.</para>
<para>Use <literal>org.apache.activemq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy</literal>
as the <literal>&lt;connection-load-balancing-policy-class-name></literal>.</para>
</listitem>
<listitem>
<para>Random. With this policy each node is chosen randomly.</para>
<para>Use <literal>org.apache.activemq.api.core.client.loadbalance.RandomConnectionLoadBalancingPolicy</literal>
as the <literal>&lt;connection-load-balancing-policy-class-name></literal>.</para>
</listitem>
<listitem>
<para>Random Sticky. With this policy the first node is chosen randomly and then re-used for subsequent
connections.</para>
<para>Use <literal>org.apache.activemq.api.core.client.loadbalance.RandomStickyConnectionLoadBalancingPolicy</literal>
as the <literal>&lt;connection-load-balancing-policy-class-name></literal>.</para>
</listitem>
<listitem>
<para>First Element. With this policy the "first" (i.e. 0th) node is always returned.</para>
<para>Use <literal>org.apache.activemq.api.core.client.loadbalance.FirstElementConnectionLoadBalancingPolicy</literal>
as the <literal>&lt;connection-load-balancing-policy-class-name></literal>.</para>
</listitem>
</itemizedlist>
<para>You can also implement your own policy by implementing the interface <literal
>org.apache.activemq.api.core.client.loadbalance.ConnectionLoadBalancingPolicy</literal></para>
<para>Specifying which load balancing policy to use differs whether you are using JMS or the
core API. If you don't specify a policy then the default will be used which is <literal
>org.apache.activemq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy</literal>.</para>
<para>If you're using JMS and you're using JNDI on the client to look up your JMS connection factory instances
then you can specify these parameters in the JNDI context environment in, e.g.
<literal>jndi.properties</literal>, to specify the load balancing policy directly:</para>
<programlisting>
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:5445
connection.ConnectionFactory.loadBalancingPolicyClassName=org.apache.activemq.api.core.client.loadbalance.RandomConnectionLoadBalancingPolicy</programlisting>
<para>The above example would instantiate a JMS connection factory that uses the random connection load
balancing policy. </para>
<para>If you're using JMS but you're instantiating your connection factory directly on the
client side then you can set the load balancing policy using the setter on the
<literal>ActiveMQConnectionFactory</literal> before using it:</para>
<programlisting>
ConnectionFactory jmsConnectionFactory = ActiveMQJMSClient.createConnectionFactory(...);
jmsConnectionFactory.setLoadBalancingPolicyClassName("com.acme.MyLoadBalancingPolicy");</programlisting>
<para>If you're using the core API, you can set the load balancing policy directly on the
<literal>ServerLocator</literal> instance you are using:</para>
<programlisting>
ServerLocator locator = ActiveMQClient.createServerLocatorWithHA(server1, server2);
locator.setLoadBalancingPolicyClassName("com.acme.MyLoadBalancingPolicy");</programlisting>
<para>The set of servers over which the factory load balances can be determined in one of
two ways:</para>
<itemizedlist>
<listitem>
<para>Specifying servers explicitly</para>
</listitem>
<listitem>
<para>Using discovery.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Specifying Members of a Cluster Explicitly</title>
<para>
Sometimes you want to explicitly define a cluster more explicitly, that is control which
server connect to each other in the cluster. This is typically used to form non symmetrical clusters
such as chain cluster or ring clusters. This can only be done using a static list of connectors and is
configured as follows:
</para>
<programlisting>
&lt;cluster-connection name="my-cluster">
&lt;address>jms&lt;/address>
&lt;connector-ref>netty-connector&lt;/connector-ref>
&lt;retry-interval>500&lt;/retry-interval>
&lt;use-duplicate-detection>true&lt;/use-duplicate-detection>
&lt;forward-when-no-consumers>true&lt;/forward-when-no-consumers>
&lt;max-hops>1&lt;/max-hops>
&lt;static-connectors allow-direct-connections-only="true">
&lt;connector-ref>server1-connector&lt;/connector-ref>
&lt;/static-connectors>
&lt;/cluster-connection></programlisting>
<para>
In this example we have set the attribute <literal>allow-direct-connections-only</literal> which means that
the only server that this server can create a cluster connection to is server1-connector. This means you can
explicitly create any cluster topology you want.
</para>
</section>
<section id="clusters.message-redistribution">
<title>Message Redistribution</title>
<para>Another important part of clustering is message redistribution. Earlier we learned how
server side message load balancing round robins messages across the cluster. If <literal
>forward-when-no-consumers</literal> is false, then messages won't be forwarded to
nodes which don't have matching consumers, this is great and ensures that messages don't
arrive on a queue which has no consumers to consume them, however there is a situation
it doesn't solve: What happens if the consumers on a queue close after the messages have
been sent to the node? If there are no consumers on the queue the message won't get
consumed and we have a <emphasis>starvation</emphasis> situation.</para>
<para>This is where message redistribution comes in. With message redistribution ActiveMQ can
be configured to automatically <emphasis>redistribute</emphasis> messages from queues
which have no consumers back to other nodes in the cluster which do have matching
consumers.</para>
<para>Message redistribution can be configured to kick in immediately after the last
consumer on a queue is closed, or to wait a configurable delay after the last consumer
on a queue is closed before redistributing. By default message redistribution is
disabled.</para>
<para>Message redistribution can be configured on a per address basis, by specifying the
redistribution delay in the address settings, for more information on configuring
address settings, please see <xref linkend="queue-attributes"/>.</para>
<para>Here's an address settings snippet from <literal>activemq-configuration.xml</literal>
showing how message redistribution is enabled for a set of queues:</para>
<programlisting>
&lt;address-settings>
&lt;address-setting match="jms.#">
&lt;redistribution-delay>0&lt;/redistribution-delay>
&lt;/address-setting>
&lt;/address-settings></programlisting>
<para>The above <literal>address-settings</literal> block would set a <literal
>redistribution-delay</literal> of <literal>0</literal> for any queue which is bound
to an address that starts with "jms.". All JMS queues and topic subscriptions are bound
to addresses that start with "jms.", so the above would enable instant (no delay)
redistribution for all JMS queues and topic subscriptions.</para>
<para>The attribute <literal>match</literal> can be an exact match or it can be a string
that conforms to the ActiveMQ wildcard syntax (described in <xref
linkend="wildcard-syntax"/>).</para>
<para>The element <literal>redistribution-delay</literal> defines the delay in milliseconds
after the last consumer is closed on a queue before redistributing messages from that
queue to other nodes of the cluster which do have matching consumers. A delay of zero
means the messages will be immediately redistributed. A value of <literal>-1</literal>
signifies that messages will never be redistributed. The default value is <literal
>-1</literal>.</para>
<para>It often makes sense to introduce a delay before redistributing as it's a common case
that a consumer closes but another one quickly is created on the same queue, in such a
case you probably don't want to redistribute immediately since the new consumer will
arrive shortly.</para>
</section>
<section>
<title>Cluster topologies</title>
<para>ActiveMQ clusters can be connected together in many different topologies, let's
consider the two most common ones here</para>
<section id="symmetric-cluster">
<title>Symmetric cluster</title>
<para>A symmetric cluster is probably the most common cluster topology, and you'll be
familiar with if you've had experience of JBoss Application Server
clustering.</para>
<para>With a symmetric cluster every node in the cluster is connected to every other
node in the cluster. In other words every node in the cluster is no more than one
hop away from every other node.</para>
<para>To form a symmetric cluster every node in the cluster defines a cluster connection
with the attribute <literal>max-hops</literal> set to <literal>1</literal>.
Typically the cluster connection will use server discovery in order to know what
other servers in the cluster it should connect to, although it is possible to
explicitly define each target server too in the cluster connection if, for example,
UDP is not available on your network.</para>
<para>With a symmetric cluster each node knows about all the queues that exist on all
the other nodes and what consumers they have. With this knowledge it can determine
how to load balance and redistribute messages around the nodes.</para>
<para>Don't forget <link linkend="copy-warning">this warning</link> when creating a
symmetric cluster.</para>
</section>
<section>
<title>Chain cluster</title>
<para>With a chain cluster, each node in the cluster is not connected to every node in
the cluster directly, instead the nodes form a chain with a node on each end of the
chain and all other nodes just connecting to the previous and next nodes in the
chain.</para>
<para>An example of this would be a three node chain consisting of nodes A, B and C.
Node A is hosted in one network and has many producer clients connected to it
sending order messages. Due to corporate policy, the order consumer clients need to
be hosted in a different network, and that network is only accessible via a third
network. In this setup node B acts as a mediator with no producers or consumers on
it. Any messages arriving on node A will be forwarded to node B, which will in turn
forward them to node C where they can get consumed. Node A does not need to directly
connect to C, but all the nodes can still act as a part of the cluster.</para>
<para>To set up a cluster in this way, node A would define a cluster connection that
connects to node B, and node B would define a cluster connection that connects to
node C. In this case we only want cluster connections in one direction since we're
only moving messages from node A->B->C and never from C->B->A.</para>
<para>For this topology we would set <literal>max-hops</literal> to <literal
>2</literal>. With a value of <literal>2</literal> the knowledge of what queues and
consumers that exist on node C would be propagated from node C to node B to node A.
Node A would then know to distribute messages to node B when they arrive, even
though node B has no consumers itself, it would know that a further hop away is node
C which does have consumers.</para>
</section>
</section>
<section>
<title>Scaling Down</title>
<para>ActiveMQ supports scaling down a cluster with no message loss (even for non-durable messages). This is especially
useful in certain environments (e.g. the cloud) where the size of a cluster may change relatively frequently.
When scaling up a cluster (i.e. adding nodes) there is no risk of message loss, but when scaling down a cluster
(i.e. removing nodes) the messages on those nodes would be lost unless the broker sent them to another node in
the cluster. ActiveMQ can be configured to do just that.</para>
<para>The simplest way to enable this behavior is to set <literal>scale-down</literal> to
<literal>true</literal>. If the server is clustered and <literal>scale-down</literal> is
<literal>true</literal> then when the server is shutdown gracefully (i.e. stopped without crashing) it will find
another node in the cluster and send <emphasis>all</emphasis> of its messages (both durable and non-durable)
to that node. The messages are processed in order and go to the <emphasis>back</emphasis> of the respective
queues on the other node (just as if the messages were sent from an external client for the first time).</para>
<para>If more control over where the messages go is required then specify <literal>scale-down-group-name</literal>.
Messages will only be sent to another node in the cluster that uses the same <literal>scale-down-group-name</literal>
as the server being shutdown.</para>
<warning>
<para>If cluster nodes are grouped together with different <literal>scale-down-group-name</literal> values beware.
If all the nodes in a single group are shut down then the messages from that node/group will be lost.</para>
</warning>
<para>If the server is using multiple <literal>cluster-connection</literal> then use <literal>scale-down-clustername</literal>
to identify the name of the <literal>cluster-connection</literal> which should be used for scaling down.</para>
</section>
</chapter>

View File

@ -0,0 +1,273 @@
Configuration Reference
=======================
This section is a quick index for looking up configuration. Click on the
element name to go to the specific chapter.
Server Configuration
====================
activemq-configuration.xml
--------------------------
This is the main core server configuration file.
activemq-jms.xml
----------------
This is the configuration file used by the server side JMS service to
load JMS Queues, Topics and Connection Factories.
Using Masked Passwords in Configuration Files
---------------------------------------------
By default all passwords in ActiveMQ server's configuration files are in
plain text form. This usually poses no security issues as those files
should be well protected from unauthorized accessing. However, in some
circumstances a user doesn't want to expose its passwords to more eyes
than necessary.
ActiveMQ can be configured to use 'masked' passwords in its
configuration files. A masked password is an obscure string
representation of a real password. To mask a password a user will use an
'encoder'. The encoder takes in the real password and outputs the masked
version. A user can then replace the real password in the configuration
files with the new masked password. When ActiveMQ loads a masked
password, it uses a suitable 'decoder' to decode it into real password.
ActiveMQ provides a default password encoder and decoder. Optionally
users can use or implement their own encoder and decoder for masking the
passwords.
### Password Masking in Server Configuration File
#### The password masking property
The server configuration file has a property that defines the default
masking behaviors over the entire file scope.
`mask-password`: this boolean type property indicates if a password
should be masked or not. Set it to "true" if you want your passwords
masked. The default value is "false".
#### Specific masking behaviors
##### cluster-password
The nature of the value of cluster-password is subject to the value of
property 'mask-password'. If it is true the cluster-password is masked.
##### Passwords in connectors and acceptors
In the server configuration, Connectors and Acceptors sometimes needs to
specify passwords. For example if a users wants to use an SSL-enabled
NettyAcceptor, it can specify a key-store-password and a
trust-store-password. Because Acceptors and Connectors are pluggable
implementations, each transport will have different password masking
needs.
When a Connector or Acceptor configuration is initialised, ActiveMQ will
add the "mask-password" and "password-codec" values to the Connector or
Acceptors params using the keys `activemq.usemaskedpassword` and
`activemq.passwordcodec` respectively. The Netty and InVM
implementations will use these as needed and any other implementations
will have access to these to use if they so wish.
##### Passwords in Core Bridge configurations
Core Bridges are configured in the server configuration file and so the
masking of its 'password' properties follows the same rules as that of
'cluster-password'.
#### Examples
The following table summarizes the relations among the above-mentioned
properties
mask-password cluster-password acceptor/connector passwords bridge password
--------------- ------------------ ------------------------------ -----------------
absent plain text plain text plain text
false plain text plain text plain text
true masked masked masked
Examples
Note: In the following examples if related attributed or properties are
absent, it means they are not specified in the configure file.
example 1
<cluster-password>bbc</cluster-password>
This indicates the cluster password is a plain text value ("bbc").
example 2
<mask-password>true</mask-password>
<cluster-password>80cf731af62c290</cluster-password>
This indicates the cluster password is a masked value and ActiveMQ will
use its built-in decoder to decode it. All other passwords in the
configuration file, Connectors, Acceptors and Bridges, will also use
masked passwords.
### JMS Bridge password masking
The JMS Bridges are configured and deployed as separate beans so they
need separate configuration to control the password masking. A JMS
Bridge has two password parameters in its constructor, SourcePassword
and TargetPassword. It uses the following two optional properties to
control their masking:
`useMaskedPassword` -- If set to "true" the passwords are masked.
Default is false.
`passwordCodec` -- Class name and its parameters for the Decoder used to
decode the masked password. Ignored if `useMaskedPassword` is false. The
format of this property is a full qualified class name optionally
followed by key/value pairs, separated by semi-colons. For example:
\<property name="useMaskedPassword"\>true\</property\>
\<property
name="passwordCodec"\>com.foo.FooDecoder;key=value\</property\>
ActiveMQ will load this property and initialize the class with a
parameter map containing the "key"-\>"value" pair. If `passwordCodec` is
not specified, the built-in decoder is used.
### Masking passwords in ActiveMQ ResourceAdapters and MDB activation configurations
Both ra.xml and MDB activation configuration have a 'password' property
that can be masked. They are controlled by the following two optional
Resource Adapter properties in ra.xml:
`UseMaskedPassword` -- If setting to "true" the passwords are masked.
Default is false.
`PasswordCodec` -- Class name and its parameters for the Decoder used to
decode the masked password. Ignored if UseMaskedPassword is false. The
format of this property is a full qualified class name optionally
followed by key/value pairs. It is the same format as that for JMS
Bridges. Example:
<config-property>
<config-property-name>UseMaskedPassword</config-property-name>
<config-property-type>boolean</config-property-type>
<config-property-value>true</config-property-value>
</config-property>
<config-property>
<config-property-name>PasswordCodec</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>com.foo.ADecoder;key=helloworld</config-property-value>
</config-property>
With this configuration, both passwords in ra.xml and all of its MDBs
will have to be in masked form.
### Masking passwords in activemq-users.xml
ActiveMQ's built-in security manager uses plain configuration files
where the user passwords are specified in plaintext forms by default. To
mask those parameters the following two properties are needed:
`mask-password` -- If set to "true" all the passwords are masked.
Default is false.
`password-codec` -- Class name and its parameters for the Decoder used
to decode the masked password. Ignored if `mask-password` is false. The
format of this property is a full qualified class name optionally
followed by key/value pairs. It is the same format as that for JMS
Bridges. Example:
<mask-password>true</mask-password>
<password-codec>org.apache.activemq.utils.DefaultSensitiveStringCodec;key=hello world</password-codec>
When so configured, the ActiveMQ security manager will initialize a
DefaultSensitiveStringCodec with the parameters "key"-\>"hello world",
then use it to decode all the masked passwords in this configuration
file.
### Choosing a decoder for password masking
As described in the previous sections, all password masking requires a
decoder. A decoder uses an algorithm to convert a masked password into
its original clear text form in order to be used in various security
operations. The algorithm used for decoding must match that for
encoding. Otherwise the decoding may not be successful.
For user's convenience ActiveMQ provides a default built-in Decoder.
However a user can if they so wish implement their own.
#### The built-in Decoder
Whenever no decoder is specified in the configuration file, the built-in
decoder is used. The class name for the built-in decoder is
org.apache.activemq.utils.DefaultSensitiveStringCodec. It has both
encoding and decoding capabilities. It uses java.crypto.Cipher utilities
to encrypt (encode) a plaintext password and decrypt a mask string using
same algorithm. Using this decoder/encoder is pretty straightforward. To
get a mask for a password, just run the following in command line:
java org.apache.activemq.utils.DefaultSensitiveStringCodec "your plaintext password"
Make sure the classpath is correct. You'll get something like
Encoded password: 80cf731af62c290
Just copy "80cf731af62c290" and replace your plaintext password with it.
#### Using a different decoder
It is possible to use a different decoder rather than the built-in one.
Simply make sure the decoder is in ActiveMQ's classpath and configure
the server to use it as follows:
<password-codec>com.foo.SomeDecoder;key1=value1;key2=value2</password-codec>
If your decoder needs params passed to it you can do this via key/value
pairs when configuring. For instance if your decoder needs say a
"key-location" parameter, you can define like so:
<password-codec>com.foo.NewDecoder;key-location=/some/url/to/keyfile</password-codec>
Then configure your cluster-password like this:
<mask-password>true</mask-password>
<cluster-password>masked_password</cluster-password>
When ActiveMQ reads the cluster-password it will initialize the
NewDecoder and use it to decode "mask\_password". It also process all
passwords using the new defined decoder.
#### Implementing your own codecs
To use a different decoder than the built-in one, you either pick one
from existing libraries or you implement it yourself. All decoders must
implement the `org.apache.activemq.utils.SensitiveDataCodec<T>`
interface:
public interface SensitiveDataCodec<T>
{
T decode(Object mask) throws Exception;
void init(Map<String, String> params);
}
This is a generic type interface but normally for a password you just
need String type. So a new decoder would be defined like
public class MyNewDecoder implements SensitiveDataCodec<String>
{
public String decode(Object mask) throws Exception
{
//decode the mask into clear text password
return "the password";
}
public void init(Map<String, String> params)
{
//initialization done here. It is called right after the decoder has been created.
}
}
Last but not least, once you get your own decoder, please add it to the
classpath. Otherwise ActiveMQ will fail to load it!

View File

@ -1,396 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="configuration-index">
<title>Configuration Reference</title>
<para>This section is a quick index for looking up configuration. Click on the element name to
go to the specific chapter.</para>
<section id="server.configuration">
<title>Server Configuration</title>
<section>
<title>activemq-configuration.xml</title>
<para>This is the main core server configuration file.</para>
<table frame="topbot" border="2">
<title>Server Configuration</title>
<tgroup cols="4">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<colspec colname="c3" colnum="3"/>
<colspec colname="c4" colnum="4"/>
<thead>
<row>
<entry>Element Name</entry>
<entry>Element Type</entry>
<entry>Description</entry>
<entry>Default</entry>
</row>
</thead>
<!-- The options reference is generated from the schema. If something is wrong
in the reference, it must be fixed in the annotations present in the
schema. -->
<xi:include href="../target/generated-resources/xml/xslt/activemq-configuration.xml"
xmlns:xi="http://www.w3.org/2001/XInclude"/>
</tgroup>
</table>
</section>
<section>
<title>activemq-jms.xml</title>
<para>This is the configuration file used by the server side JMS service to load JMS
Queues, Topics and Connection Factories.</para>
<table frame="topbot" border="2">
<title>JMS Server Configuration</title>
<tgroup cols="4">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<colspec colname="c3" colnum="3"/>
<colspec colname="c4" colnum="4"/>
<thead>
<row>
<entry>Element Name</entry>
<entry>Element Type</entry>
<entry>Description</entry>
<entry>Default</entry>
</row>
</thead>
<tbody>
<row>
<entry><link linkend="using-jms.server.configuration">queue</link></entry>
<entry>Queue</entry>
<entry>a queue to create and add to JNDI</entry>
<entry/>
</row>
<row>
<entry><link linkend="using-jms.server.configuration">queue.name (attribute)</link></entry>
<entry>String</entry>
<entry>unique name of the queue</entry>
<entry/>
</row>
<row>
<entry><link linkend="using-jms.server.configuration">queue.entry</link></entry>
<entry>String</entry>
<entry>context where the queue will be bound in JNDI (there can be many)</entry>
<entry/>
</row>
<row>
<entry><link linkend="using-jms.server.configuration">queue.durable</link></entry>
<entry>Boolean</entry>
<entry>is the queue durable?</entry>
<entry>true</entry>
</row>
<row>
<entry><link linkend="using-jms.server.configuration">queue.filter</link></entry>
<entry>String</entry>
<entry>optional filter expression for the queue</entry>
<entry/>
</row>
<row>
<entry><link linkend="using-jms.server.configuration">topic</link></entry>
<entry>Topic</entry>
<entry>a topic to create and add to JNDI</entry>
<entry/>
</row>
<row>
<entry><link linkend="using-jms.server.configuration">topic.name (attribute)</link></entry>
<entry>String</entry>
<entry>unique name of the topic</entry>
<entry/>
</row>
<row>
<entry><link linkend="using-jms.server.configuration">topic.entry</link></entry>
<entry>String</entry>
<entry>context where the topic will be bound in JNDI (there can be many)</entry>
<entry/>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="configuration.masked-password">
<title>Using Masked Passwords in Configuration Files</title>
<para>By default all passwords in ActiveMQ server's configuration files are in plain text form. This usually poses no security issues as those
files should be well protected from unauthorized accessing. However, in some circumstances a user doesn't want to expose its passwords to more
eyes than necessary. </para>
<para>ActiveMQ can be configured to use 'masked' passwords in its configuration files. A masked password is an obscure string representation
of a real password. To mask a password a user will use an 'encoder'. The encoder takes in the real password and outputs the masked version.
A user can then replace the real password in the configuration files with the new masked password.
When ActiveMQ loads a masked password, it uses a suitable 'decoder' to decode it into real password.</para>
<para>ActiveMQ provides a default password encoder and decoder. Optionally users can use or implement their own encoder and decoder for
masking the passwords.</para>
<section> <title>Password Masking in Server Configuration File</title>
<section> <title>The password masking property</title>
<para>The server configuration file has a property that defines the default masking behaviors over the entire file scope.</para>
<para><literal>mask-password</literal>: this boolean type property indicates if a password should be masked or not. Set it to "true"
if you want your passwords masked. The default value is "false".</para>
</section>
<section> <title>Specific masking behaviors</title>
<section> <title>cluster-password</title>
<para>The nature of the value of cluster-password is subject to the value of property 'mask-password'. If it is true
the cluster-password is masked.</para>
</section>
<section> <title>Passwords in connectors and acceptors</title>
<para>In the server configuration, Connectors and Acceptors sometimes needs to specify passwords. For example
if a users wants to use an SSL-enabled NettyAcceptor, it can specify a key-store-password and a trust-store-password. Because
Acceptors and Connectors are pluggable implementations, each transport will have different password masking needs.</para>
<para>When a Connector or Acceptor configuration is initialised, ActiveMQ will add the "mask-password" and
"password-codec" values to the Connector or Acceptors params using the keys <literal>activemq.usemaskedpassword</literal>
and <literal>activemq.passwordcodec</literal> respectively. The Netty and InVM implementations will use these
as needed and any other implementations will have access to these to use if they so wish.</para>
</section>
<section> <title>Passwords in Core Bridge configurations</title>
<para>Core Bridges are configured in the server configuration file and so the masking of its 'password' properties
follows the same rules as that of 'cluster-password'.</para>
</section>
</section>
<section> <title>Examples</title>
<para>The following table summarizes the relations among the above-mentioned properties</para>
<table frame="topbot" border="2">
<tgroup cols="4">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<colspec colname="c3" colnum="3"/>
<colspec colname="c4" colnum="4"/>
<thead>
<row>
<entry>mask-password</entry>
<entry>cluster-password</entry>
<entry>acceptor/connector passwords</entry>
<entry>bridge password</entry>
</row>
</thead>
<tbody>
<row>
<entry>absent</entry>
<entry>plain text</entry>
<entry>plain text</entry>
<entry>plain text</entry>
</row>
<row>
<entry>false</entry>
<entry>plain text</entry>
<entry>plain text</entry>
<entry>plain text</entry>
</row>
<row>
<entry>true</entry>
<entry>masked</entry>
<entry>masked</entry>
<entry>masked</entry>
</row>
</tbody>
</tgroup>
</table>
<para>Examples</para>
<para>Note: In the following examples if related attributed or properties are absent, it means they are not specified in the configure file.</para>
<para>example 1</para>
<programlisting>
&lt;cluster-password>bbc&lt;/cluster-password></programlisting>
<para>This indicates the cluster password is a plain text value ("bbc").</para>
<para>example 2</para>
<programlisting>
&lt;mask-password>true&lt;/mask-password>
&lt;cluster-password>80cf731af62c290&lt;/cluster-password></programlisting>
<para>This indicates the cluster password is a masked value and ActiveMQ will use its built-in decoder to decode it. All other
passwords in the configuration file, Connectors, Acceptors and Bridges, will also use masked passwords.</para>
</section>
</section>
<section> <title>JMS Bridge password masking</title>
<para>The JMS Bridges are configured and deployed as separate beans so they need separate configuration to control the password masking.
A JMS Bridge has two password parameters in its constructor, SourcePassword and TargetPassword. It uses the following two optional
properties to control their masking:</para>
<para><literal>useMaskedPassword</literal> -- If set to "true" the passwords are masked. Default is false.</para>
<para><literal>passwordCodec</literal> -- Class name and its parameters for the Decoder used to decode the masked password. Ignored if
<literal>useMaskedPassword</literal> is false. The format of this property is a full qualified class name optionally followed by key/value pairs,
separated by semi-colons. For example:</para>
<literal>
&lt;property name="useMaskedPassword">true&lt;/property>
</literal><para></para>
<literal>
&lt;property name="passwordCodec">com.foo.FooDecoder;key=value&lt;/property>
</literal>
<para>ActiveMQ will load this property and initialize the class with a parameter map containing the "key"->"value" pair.
If <literal>passwordCodec</literal> is not specified, the built-in decoder is used.</para>
</section>
<section> <title>Masking passwords in ActiveMQ ResourceAdapters and MDB activation configurations</title>
<para>Both ra.xml and MDB activation configuration have a 'password' property that can be masked. They are controlled by the following two
optional Resource Adapter properties in ra.xml:</para>
<para><literal>UseMaskedPassword</literal> -- If setting to "true" the passwords are masked. Default is false.</para>
<para><literal>PasswordCodec</literal> -- Class name and its parameters for the Decoder used to decode the masked password.
Ignored if UseMaskedPassword is false. The format of this property is a full qualified class name optionally followed by key/value pairs.
It is the same format as that for JMS Bridges. Example:</para>
<programlisting>
&lt;config-property>
&lt;config-property-name>UseMaskedPassword&lt;/config-property-name>
&lt;config-property-type>boolean&lt;/config-property-type>
&lt;config-property-value>true&lt;/config-property-value>
&lt;/config-property>
&lt;config-property>
&lt;config-property-name>PasswordCodec&lt;/config-property-name>
&lt;config-property-type>java.lang.String&lt;/config-property-type>
&lt;config-property-value>com.foo.ADecoder;key=helloworld&lt;/config-property-value>
&lt;/config-property></programlisting>
<para>With this configuration, both passwords in ra.xml and all of its MDBs will have to be in masked form.</para>
</section>
<section> <title>Masking passwords in activemq-users.xml</title>
<para>ActiveMQ's built-in security manager uses plain configuration files where the user passwords are specified in plaintext
forms by default. To mask those parameters the following two properties are needed:</para>
<para> <literal>mask-password</literal> -- If set to "true" all the passwords are masked. Default is false.</para>
<para> <literal>password-codec</literal> -- Class name and its parameters for the Decoder used to decode the masked password.
Ignored if <literal>mask-password</literal> is false. The format of this property is a full qualified class name optionally
followed by key/value pairs. It is the same format as that for JMS Bridges. Example:</para>
<programlisting>
&lt;mask-password>true&lt;/mask-password>
&lt;password-codec>org.apache.activemq.utils.DefaultSensitiveStringCodec;key=hello world&lt;/password-codec></programlisting>
<para>When so configured, the ActiveMQ security manager will initialize a DefaultSensitiveStringCodec with the parameters
"key"->"hello world", then use it to decode all the masked passwords in this configuration file.</para>
</section>
<section> <title>Choosing a decoder for password masking</title>
<para>As described in the previous sections, all password masking requires a decoder. A decoder uses an algorithm to
convert a masked password into its original clear text form in order to be used in various security operations. The algorithm
used for decoding must match that for encoding. Otherwise the decoding may not be successful.</para>
<para>For user's convenience ActiveMQ provides a default built-in Decoder. However a user can if they so wish implement their own.</para>
<section><title>The built-in Decoder</title>
<para>Whenever no decoder is specified in the configuration file, the built-in decoder is used. The class name for the built-in
decoder is org.apache.activemq.utils.DefaultSensitiveStringCodec. It has both encoding and decoding capabilities. It uses java.crypto.Cipher
utilities to encrypt (encode) a plaintext password and decrypt a mask string using same algorithm. Using this decoder/encoder is
pretty straightforward. To get a mask for a password, just run the following in command line:</para>
<programlisting>
java org.apache.activemq.utils.DefaultSensitiveStringCodec "your plaintext password"</programlisting>
<para>Make sure the classpath is correct. You'll get something like</para>
<programlisting>
Encoded password: 80cf731af62c290</programlisting>
<para>Just copy "80cf731af62c290" and replace your plaintext password with it.</para>
</section>
<section><title>Using a different decoder</title>
<para>It is possible to use a different decoder rather than the built-in one. Simply make sure the decoder
is in ActiveMQ's classpath and configure the server to use it as follows:</para>
<programlisting>
&lt;password-codec>com.foo.SomeDecoder;key1=value1;key2=value2&lt;/password-codec></programlisting>
<para>If your decoder needs params passed to it you can do this via key/value pairs when configuring.
For instance if your decoder needs say a "key-location" parameter, you can define like so:</para>
<programlisting>
&lt;password-codec>com.foo.NewDecoder;key-location=/some/url/to/keyfile&lt;/password-codec></programlisting>
<para>Then configure your cluster-password like this:</para>
<programlisting>
&lt;mask-password>true&lt;/mask-password>
&lt;cluster-password>masked_password&lt;/cluster-password></programlisting>
<para>When ActiveMQ reads the cluster-password it will initialize the NewDecoder and use it to decode "mask_password".
It also process all passwords using the new defined decoder.</para>
</section>
<section><title>Implementing your own codecs</title>
<para>To use a different decoder than the built-in one, you either pick one from existing libraries or you implement it yourself.
All decoders must implement the <literal>org.apache.activemq.utils.SensitiveDataCodec&lt;T></literal> interface:</para>
<programlisting>
public interface SensitiveDataCodec&lt;T>
{
T decode(Object mask) throws Exception;
void init(Map&lt;String, String> params);
}</programlisting>
<para>This is a generic type interface but normally for a password you just need String type.
So a new decoder would be defined like </para>
<programlisting>
public class MyNewDecoder implements SensitiveDataCodec&lt;String>
{
public String decode(Object mask) throws Exception
{
//decode the mask into clear text password
return "the password";
}
public void init(Map&lt;String, String> params)
{
//initialization done here. It is called right after the decoder has been created.
}
}</programlisting>
<para>Last but not least, once you get your own decoder, please add it to the classpath. Otherwise ActiveMQ will
fail to load it!</para>
</section>
</section>
</section>
</section>
</chapter>

View File

@ -0,0 +1,462 @@
Configuring the Transport
=========================
ActiveMQ has a fully pluggable and highly flexible transport layer and
defines its own Service Provider Interface (SPI) to make plugging in a
new transport provider relatively straightforward.
In this chapter we'll describe the concepts required for understanding
ActiveMQ transports and where and how they're configured.
Understanding Acceptors
=======================
One of the most important concepts in ActiveMQ transports is the
*acceptor*. Let's dive straight in and take a look at an acceptor
defined in xml in the configuration file `activemq-configuration.xml`.
<acceptors>
<acceptor name="netty">
<factory-class>
org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory
</factory-class>
<param key="port" value="5446"/>
</acceptor>
</acceptors>
Acceptors are always defined inside an `acceptors` element. There can be
one or more acceptors defined in the `acceptors` element. There's no
upper limit to the number of acceptors per server.
Each acceptor defines a way in which connections can be made to the
ActiveMQ server.
In the above example we're defining an acceptor that uses
[Netty](http://jboss.org/netty) to listen for connections at port
`5446`.
The `acceptor` element contains a sub-element `factory-class`, this
element defines the factory used to create acceptor instances. In this
case we're using Netty to listen for connections so we use the Netty
implementation of an `AcceptorFactory` to do this. Basically, the
`factory-class` element determines which pluggable transport we're going
to use to do the actual listening.
The `acceptor` element can also be configured with zero or more `param`
sub-elements. Each `param` element defines a key-value pair. These
key-value pairs are used to configure the specific transport, the set of
valid key-value pairs depends on the specific transport be used and are
passed straight through to the underlying transport.
Examples of key-value pairs for a particular transport would be, say, to
configure the IP address to bind to, or the port to listen at.
Note that unlike versions before 2.4 an Acceptor can now support
multiple protocols. By default this will be all available protocols but
can be limited by either the now deprecated `protocol` param or by
setting a comma seperated list to the newly added `protocols` parameter.
Understanding Connectors
========================
Whereas acceptors are used on the server to define how we accept
connections, connectors are used by a client to define how it connects
to a server.
Let's look at a connector defined in our `activemq-configuration.xml`
file:
<connectors>
<connector name="netty">
<factory-class>
org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory
</factory-class>
<param key="port" value="5446"/>
</connector>
</connectors>
Connectors can be defined inside a `connectors` element. There can be
one or more connectors defined in the `connectors` element. There's no
upper limit to the number of connectors per server.
You make ask yourself, if connectors are used by the *client* to make
connections then why are they defined on the *server*? There are a
couple of reasons for this:
- Sometimes the server acts as a client itself when it connects to
another server, for example when one server is bridged to another,
or when a server takes part in a cluster. In this cases the server
needs to know how to connect to other servers. That's defined by
*connectors*.
- If you're using JMS and you're using JNDI on the client to look up
your JMS connection factory instances then when creating the
`ActiveMQConnectionFactory` it needs to know what server that
connection factory will create connections to.
That's defined by the `java.naming.provider.url` element in the JNDI
context environment, e.g. `jndi.properties`. Behind the scenes, the
`org.apache.activemq.jndi.ActiveMQInitialContextFactory` uses the
`java.naming.provider.url` to construct the transport. Here's a
simple example:
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://myhost:5445
Configuring the transport directly from the client side.
========================================================
How do we configure a core `ClientSessionFactory` with the information
that it needs to connect with a server?
Connectors are also used indirectly when directly configuring a core
`ClientSessionFactory` to directly talk to a server. Although in this
case there's no need to define such a connector in the server side
configuration, instead we just create the parameters and tell the
`ClientSessionFactory` which connector factory to use.
Here's an example of creating a `ClientSessionFactory` which will
connect directly to the acceptor we defined earlier in this chapter, it
uses the standard Netty TCP transport and will try and connect on port
5446 to localhost (default):
Map<String, Object> connectionParams = new HashMap<String, Object>();
connectionParams.put(org.apache.activemq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME,
5446);
TransportConfiguration transportConfiguration =
new TransportConfiguration(
"org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory",
connectionParams);
ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(transportConfiguration);
ClientSessionFactory sessionFactory = locator.createClientSessionFactory();
ClientSession session = sessionFactory.createSession(...);
etc
Similarly, if you're using JMS, you can configure the JMS connection
factory directly on the client side without having to define a connector
on the server side or define a connection factory in `activemq-jms.xml`:
Map<String, Object> connectionParams = new HashMap<String, Object>();
connectionParams.put(org.apache.activemq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, 5446);
TransportConfiguration transportConfiguration =
new TransportConfiguration(
"org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory",
connectionParams);
ConnectionFactory connectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);
Connection jmsConnection = connectionFactory.createConnection();
etc
Configuring the Netty transport
===============================
Out of the box, ActiveMQ currently uses
[Netty](http://www.jboss.org/netty/), a high performance low level
network library.
Our Netty transport can be configured in several different ways; to use
old (blocking) Java IO, or NIO (non-blocking), also to use
straightforward TCP sockets, SSL, or to tunnel over HTTP or HTTPS..
We believe this caters for the vast majority of transport requirements.
Single Port Support
-------------------
As of version 2.4 ActiveMQ now supports using a single port for all
protocols, ActiveMQ will automatically detect which protocol is being
used CORE, AMQP, STOMP or OPENWIRE and use the appropriate ActiveMQ
handler. It will also detect whether protocols such as HTTP or Web
Sockets are being used and also use the appropriate decoders
It is possible to limit which protocols are supported by using the
`protocols` parameter on the Acceptor like so:
<param key="protocols" value="CORE,AMQP"/>
> **Note**
>
> The `protocol` parameter is now deprecated
Configuring Netty TCP
---------------------
Netty TCP is a simple unencrypted TCP sockets based transport. Netty TCP
can be configured to use old blocking Java IO or non blocking Java NIO.
We recommend you use the Java NIO on the server side for better
scalability with many concurrent connections. However using Java old IO
can sometimes give you better latency than NIO when you're not so
worried about supporting many thousands of concurrent connections.
If you're running connections across an untrusted network please bear in
mind this transport is unencrypted. You may want to look at the SSL or
HTTPS configurations.
With the Netty TCP transport all connections are initiated from the
client side. I.e. the server does not initiate any connections to the
client. This works well with firewall policies that typically only allow
connections to be initiated in one direction.
All the valid Netty transport keys are defined in the class
`org.apache.activemq.core.remoting.impl.netty.TransportConstants`. Most
parameters can be used either with acceptors or connectors, some only
work with acceptors. The following parameters can be used to configure
Netty for simple TCP:
- `use-nio`. If this is `true` then Java non blocking NIO will be
used. If set to `false` then old blocking Java IO will be used.
If you require the server to handle many concurrent connections, we
highly recommend that you use non blocking Java NIO. Java NIO does
not maintain a thread per connection so can scale to many more
concurrent connections than with old blocking IO. If you don't
require the server to handle many concurrent connections, you might
get slightly better performance by using old (blocking) IO. The
default value for this property is `false` on the server side and
`false` on the client side.
- `host`. This specifies the host name or IP address to connect to
(when configuring a connector) or to listen on (when configuring an
acceptor). The default value for this property is `localhost`. When
configuring acceptors, multiple hosts or IP addresses can be
specified by separating them with commas. It is also possible to
specify `0.0.0.0` to accept connection from all the host's network
interfaces. It's not valid to specify multiple addresses when
specifying the host for a connector; a connector makes a connection
to one specific address.
> **Note**
>
> Don't forget to specify a host name or IP address! If you want
> your server able to accept connections from other nodes you must
> specify a hostname or IP address at which the acceptor will bind
> and listen for incoming connections. The default is localhost
> which of course is not accessible from remote nodes!
- `port`. This specified the port to connect to (when configuring a
connector) or to listen on (when configuring an acceptor). The
default value for this property is `5445`.
- `tcp-no-delay`. If this is `true` then [Nagle's
algorithm](http://en.wikipedia.org/wiki/Nagle%27s_algorithm) will be
disabled. This is a [Java (client) socket
option](http://docs.oracle.com/javase/7/docs/technotes/guides/net/socketOpt.html).
The default value for this property is `true`.
- `tcp-send-buffer-size`. This parameter determines the size of the
TCP send buffer in bytes. The default value for this property is
`32768` bytes (32KiB).
TCP buffer sizes should be tuned according to the bandwidth and
latency of your network. Here's a good link that explains the theory
behind [this](http://www-didc.lbl.gov/TCP-tuning/).
In summary TCP send/receive buffer sizes should be calculated as:
buffer_size = bandwidth * RTT.
Where bandwidth is in *bytes per second* and network round trip time
(RTT) is in seconds. RTT can be easily measured using the `ping`
utility.
For fast networks you may want to increase the buffer sizes from the
defaults.
- `tcp-receive-buffer-size`. This parameter determines the size of the
TCP receive buffer in bytes. The default value for this property is
`32768` bytes (32KiB).
- `batch-delay`. Before writing packets to the transport, ActiveMQ can
be configured to batch up writes for a maximum of `batch-delay`
milliseconds. This can increase overall throughput for very small
messages. It does so at the expense of an increase in average
latency for message transfer. The default value for this property is
`0` ms.
- `direct-deliver`. When a message arrives on the server and is
delivered to waiting consumers, by default, the delivery is done on
the same thread as that on which the message arrived. This gives
good latency in environments with relatively small messages and a
small number of consumers, but at the cost of overall throughput and
scalability - especially on multi-core machines. If you want the
lowest latency and a possible reduction in throughput then you can
use the default value for `direct-deliver` (i.e. true). If you are
willing to take some small extra hit on latency but want the highest
throughput set `direct-deliver` to `false
`.
- `nio-remoting-threads`. When configured to use NIO, ActiveMQ will,
by default, use a number of threads equal to three times the number
of cores (or hyper-threads) as reported by
`Runtime.getRuntime().availableProcessors()` for processing incoming
packets. If you want to override this value, you can set the number
of threads by specifying this parameter. The default value for this
parameter is `-1` which means use the value from
`Runtime.getRuntime().availableProcessors()` \* 3.
- `local-address`. When configured a Netty Connector it is possible to
specify which local address the client will use when connecting to
the remote address. This is typically used in the Application Server
or when running Embedded to control which address is used for
outbound connections. If the local-address is not set then the
connector will use any local address available
- `local-port`. When configured a Netty Connector it is possible to
specify which local port the client will use when connecting to the
remote address. This is typically used in the Application Server or
when running Embedded to control which port is used for outbound
connections. If the local-port default is used, which is 0, then the
connector will let the system pick up an ephemeral port. valid ports
are 0 to 65535
Configuring Netty SSL
---------------------
Netty SSL is similar to the Netty TCP transport but it provides
additional security by encrypting TCP connections using the Secure
Sockets Layer SSL
Please see the examples for a full working example of using Netty SSL.
Netty SSL uses all the same properties as Netty TCP but adds the
following additional properties:
- `ssl-enabled`
Must be `true` to enable SSL. Default is `false`.
- `key-store-path`
When used on an `acceptor` this is the path to the SSL key store on
the server which holds the server's certificates (whether
self-signed or signed by an authority).
When used on a `connector` this is the path to the client-side SSL
key store which holds the client certificates. This is only relevant
for a `connector` if you are using 2-way SSL (i.e. mutual
authentication). Although this value is configured on the server, it
is downloaded and used by the client. If the client needs to use a
different path from that set on the server then it can override the
server-side setting by either using the customary
"javax.net.ssl.keyStore" system property or the ActiveMQ-specific
"org.apache.activemq.ssl.keyStore" system property. The
ActiveMQ-specific system property is useful if another component on
client is already making use of the standard, Java system property.
- `key-store-password`
When used on an `acceptor` this is the password for the server-side
keystore.
When used on a `connector` this is the password for the client-side
keystore. This is only relevant for a `connector` if you are using
2-way SSL (i.e. mutual authentication). Although this value can be
configured on the server, it is downloaded and used by the client.
If the client needs to use a different password from that set on the
server then it can override the server-side setting by either using
the customary "javax.net.ssl.keyStorePassword" system property or
the ActiveMQ-specific "org.apache.activemq.ssl.keyStorePassword"
system property. The ActiveMQ-specific system property is useful if
another component on client is already making use of the standard,
Java system property.
- `trust-store-path`
When used on an `acceptor` this is the path to the server-side SSL
key store that holds the keys of all the clients that the server
trusts. This is only relevant for an `acceptor` if you are using
2-way SSL (i.e. mutual authentication).
When used on a `connector` this is the path to the client-side SSL
key store which holds the public keys of all the servers that the
client trusts. Although this value can be configured on the server,
it is downloaded and used by the client. If the client needs to use
a different path from that set on the server then it can override
the server-side setting by either using the customary
"javax.net.ssl.trustStore" system property or the ActiveMQ-specific
"org.apache.activemq.ssl.trustStore" system property. The
ActiveMQ-specific system property is useful if another component on
client is already making use of the standard, Java system property.
- `trust-store-password`
When used on an `acceptor` this is the password for the server-side
trust store. This is only relevant for an `acceptor` if you are
using 2-way SSL (i.e. mutual authentication).
When used on a `connector` this is the password for the client-side
truststore. Although this value can be configured on the server, it
is downloaded and used by the client. If the client needs to use a
different password from that set on the server then it can override
the server-side setting by either using the customary
"javax.net.ssl.trustStorePassword" system property or the
ActiveMQ-specific "org.apache.activemq.ssl.trustStorePassword"
system property. The ActiveMQ-specific system property is useful if
another component on client is already making use of the standard,
Java system property.
- `enabled-cipher-suites`
Whether used on an `acceptor` or `connector` this is a comma
separated list of cipher suites used for SSL communication. The
default value is `null` which means the JVM's default will be used.
- `enabled-protocols`
Whether used on an `acceptor` or `connector` this is a comma
separated list of protocols used for SSL communication. The default
value is `null` which means the JVM's default will be used.
- `need-client-auth`
This property is only for an `acceptor`. It tells a client
connecting to this acceptor that 2-way SSL is required. Valid values
are `true` or `false`. Default is `false`.
Configuring Netty HTTP
----------------------
Netty HTTP tunnels packets over the HTTP protocol. It can be useful in
scenarios where firewalls only allow HTTP traffic to pass.
Please see the examples for a full working example of using Netty HTTP.
Netty HTTP uses the same properties as Netty TCP but adds the following
additional properties:
- `http-enabled`. This is now no longer needed as of version 2.4. With
single port support ActiveMQ will now automatically detect if http
is being used and configure itself.
- `http-client-idle-time`. How long a client can be idle before
sending an empty http request to keep the connection alive
- `http-client-idle-scan-period`. How often, in milliseconds, to scan
for idle clients
- `http-response-time`. How long the server can wait before sending an
empty http response to keep the connection alive
- `http-server-scan-period`. How often, in milliseconds, to scan for
clients needing responses
- `http-requires-session-id`. If true the client will wait after the
first call to receive a session id. Used the http connector is
connecting to servlet acceptor (not recommended)
Configuring Netty Servlet
-------------------------
As of 2.4 ActiveMQ Servlet support will be provided via Undertow in
Wildfly

View File

@ -1,443 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="configuring-transports">
<title>Configuring the Transport</title>
<para>ActiveMQ has a fully pluggable and highly flexible transport layer and defines its own
Service Provider Interface (SPI) to make plugging in a new transport provider relatively
straightforward.</para>
<para>In this chapter we'll describe the concepts required for understanding ActiveMQ transports
and where and how they're configured.</para>
<section id="configuring-transports.acceptors">
<title>Understanding Acceptors</title>
<para>One of the most important concepts in ActiveMQ transports is the
<emphasis>acceptor</emphasis>. Let's dive straight in and take a look at an acceptor
defined in xml in the configuration file <literal
>activemq-configuration.xml</literal>.</para>
<programlisting>
&lt;acceptors>
&lt;acceptor name="netty">
&lt;factory-class>
org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory
&lt;/factory-class>
&lt;param key="port" value="5446"/>
&lt;/acceptor>
&lt;/acceptors></programlisting>
<para>Acceptors are always defined inside an <literal>acceptors</literal> element. There can
be one or more acceptors defined in the <literal>acceptors</literal> element. There's no
upper limit to the number of acceptors per server.</para>
<para>Each acceptor defines a way in which connections can be made to the ActiveMQ
server.</para>
<para>In the above example we're defining an acceptor that uses <ulink
url="http://jboss.org/netty">Netty</ulink> to listen for connections at port
<literal>5446</literal>. </para>
<para>The <literal>acceptor</literal> element contains a sub-element <literal
>factory-class</literal>, this element defines the factory used to create acceptor
instances. In this case we're using Netty to listen for connections so we use the Netty
implementation of an <literal>AcceptorFactory</literal> to do this. Basically, the
<literal>factory-class</literal> element determines which pluggable transport we're
going to use to do the actual listening.</para>
<para>The <literal>acceptor</literal> element can also be configured with zero or more
<literal>param</literal> sub-elements. Each <literal>param</literal> element defines
a key-value pair. These key-value pairs are used to configure the specific transport,
the set of valid key-value pairs depends on the specific transport be used and are
passed straight through to the underlying transport.</para>
<para>Examples of key-value pairs for a particular transport would be, say, to configure the
IP address to bind to, or the port to listen at.</para>
<para>Note that unlike versions before 2.4 an Acceptor can now support multiple protocols. By default this will
be all available protocols but can be limited by either the now deprecated <literal>protocol</literal> param or
by setting a comma seperated list to the newly added <literal>protocols</literal> parameter.</para>
</section>
<section id="configuring-transports.connectors">
<title>Understanding Connectors</title>
<para>Whereas acceptors are used on the server to define how we accept connections,
connectors are used by a client to define how it connects to a server.</para>
<para>Let's look at a connector defined in our <literal>activemq-configuration.xml</literal>
file:</para>
<programlisting>
&lt;connectors>
&lt;connector name="netty">
&lt;factory-class>
org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory
&lt;/factory-class>
&lt;param key="port" value="5446"/>
&lt;/connector>
&lt;/connectors></programlisting>
<para>Connectors can be defined inside a <literal>connectors</literal> element. There can be
one or more connectors defined in the <literal>connectors</literal> element. There's no
upper limit to the number of connectors per server.</para>
<para>You make ask yourself, if connectors are used by the <emphasis>client</emphasis> to
make connections then why are they defined on the <emphasis>server</emphasis>? There are
a couple of reasons for this:</para>
<itemizedlist>
<listitem>
<para>Sometimes the server acts as a client itself when it connects to another
server, for example when one server is bridged to another, or when a server
takes part in a cluster. In this cases the server needs to know how to connect
to other servers. That's defined by <emphasis>connectors</emphasis>.</para>
</listitem>
<listitem>
<para>If you're using JMS and you're using JNDI on the client to look up your JMS connection factory
instances then when creating the <literal>ActiveMQConnectionFactory</literal> it needs to know what
server that connection factory will create connections to.</para>
<para>That's defined by the <literal>java.naming.provider.url</literal> element in the JNDI context
environment, e.g. <literal>jndi.properties</literal>. Behind the scenes, the
<literal>org.apache.activemq.jndi.ActiveMQInitialContextFactory</literal> uses the
<literal>java.naming.provider.url</literal> to construct the transport. Here's a simple example:</para>
<programlisting>
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://myhost:5445</programlisting>
</listitem>
</itemizedlist>
</section>
<section id="configuring-transports.client.side">
<title>Configuring the transport directly from the client side.</title>
<para>How do we configure a core <literal>ClientSessionFactory</literal> with the
information that it needs to connect with a server?</para>
<para>Connectors are also used indirectly when directly configuring a core <literal
>ClientSessionFactory</literal> to directly talk to a server. Although in this case
there's no need to define such a connector in the server side configuration, instead we
just create the parameters and tell the <literal>ClientSessionFactory</literal> which
connector factory to use.</para>
<para>Here's an example of creating a <literal>ClientSessionFactory</literal> which will
connect directly to the acceptor we defined earlier in this chapter, it uses the
standard Netty TCP transport and will try and connect on port 5446 to localhost
(default):</para>
<programlisting>
Map&lt;String, Object> connectionParams = new HashMap&lt;String, Object>();
connectionParams.put(org.apache.activemq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME,
5446);
TransportConfiguration transportConfiguration =
new TransportConfiguration(
"org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory",
connectionParams);
ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(transportConfiguration);
ClientSessionFactory sessionFactory = locator.createClientSessionFactory();
ClientSession session = sessionFactory.createSession(...);
etc</programlisting>
<para>Similarly, if you're using JMS, you can configure the JMS connection factory directly
on the client side without having to define a connector on the server side or define a
connection factory in <literal>activemq-jms.xml</literal>:</para>
<programlisting>
Map&lt;String, Object> connectionParams = new HashMap&lt;String, Object>();
connectionParams.put(org.apache.activemq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, 5446);
TransportConfiguration transportConfiguration =
new TransportConfiguration(
"org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory",
connectionParams);
ConnectionFactory connectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);
Connection jmsConnection = connectionFactory.createConnection();
etc</programlisting>
</section>
<section id="configuring-transports.netty">
<title>Configuring the Netty transport</title>
<para>Out of the box, ActiveMQ currently uses <ulink url="http://www.jboss.org/netty/"
>Netty</ulink>, a high performance low level network library.</para>
<para>Our Netty transport can be configured in several different ways; to use old (blocking)
Java IO, or NIO (non-blocking), also to use straightforward TCP sockets, SSL, or to
tunnel over HTTP or HTTPS..</para>
<para>We believe this caters for the vast majority of transport requirements.</para>
<section id="configuring-transports.single-port">
<title>Single Port Support</title>
<para>As of version 2.4 ActiveMQ now supports using a single port for all protocols, ActiveMQ will automatically
detect which protocol is being used CORE, AMQP, STOMP or OPENWIRE and use the appropriate ActiveMQ handler. It will also detect
whether protocols such as HTTP or Web Sockets are being used and also use the appropriate decoders</para>
<para>It is possible to limit which protocols are supported by using the <literal>protocols</literal> parameter
on the Acceptor like so:</para>
<programlisting>
&lt;param key="protocols" value="CORE,AMQP"/>
</programlisting>
<note><para>The <literal>protocol</literal> parameter is now deprecated</para></note>
</section>
<section>
<title>Configuring Netty TCP</title>
<para>Netty TCP is a simple unencrypted TCP sockets based transport. Netty TCP can be
configured to use old blocking Java IO or non blocking Java NIO. We recommend you
use the Java NIO on the server side for better scalability with many concurrent
connections. However using Java old IO can sometimes give you better latency than
NIO when you're not so worried about supporting many thousands of concurrent
connections. </para>
<para>If you're running connections across an untrusted network please bear in mind this
transport is unencrypted. You may want to look at the SSL or HTTPS
configurations.</para>
<para>With the Netty TCP transport all connections are initiated from the client side.
I.e. the server does not initiate any connections to the client. This works well
with firewall policies that typically only allow connections to be initiated in one
direction.</para>
<para>All the valid Netty transport keys are defined in the class <literal
>org.apache.activemq.core.remoting.impl.netty.TransportConstants</literal>. Most
parameters can be used either with acceptors or connectors, some only work with
acceptors. The following parameters can be used to configure Netty for simple
TCP:</para>
<itemizedlist>
<listitem>
<para><literal>use-nio</literal>. If this is <literal>true</literal> then Java
non blocking NIO will be used. If set to <literal>false</literal> then old
blocking Java IO will be used.</para>
<para>If you require the server to handle many concurrent connections, we highly
recommend that you use non blocking Java NIO. Java NIO does not maintain a
thread per connection so can scale to many more concurrent connections than
with old blocking IO. If you don't require the server to handle many
concurrent connections, you might get slightly better performance by using
old (blocking) IO. The default value for this property is <literal
>false</literal> on the server side and <literal>false</literal> on the
client side.</para>
</listitem>
<listitem>
<para><literal>host</literal>. This specifies the host name or IP address to
connect to (when configuring a connector) or to listen on (when configuring
an acceptor). The default value for this property is <literal
>localhost</literal>. When configuring acceptors, multiple hosts or IP
addresses can be specified by separating them with commas. It is also
possible to specify <code>0.0.0.0</code> to accept connection from all the
host's network interfaces. It's not valid to specify multiple addresses when
specifying the host for a connector; a connector makes a connection to one
specific address.</para>
<note>
<para>Don't forget to specify a host name or IP address! If you want your
server able to accept connections from other nodes you must specify a
hostname or IP address at which the acceptor will bind and listen for
incoming connections. The default is localhost which of course is not
accessible from remote nodes!</para>
</note>
</listitem>
<listitem>
<para><literal>port</literal>. This specified the port to connect to (when
configuring a connector) or to listen on (when configuring an acceptor). The
default value for this property is <literal>5445</literal>.</para>
</listitem>
<listitem>
<para><literal>tcp-no-delay</literal>. If this is <literal>true</literal> then
<ulink url="http://en.wikipedia.org/wiki/Nagle%27s_algorithm">Nagle's
algorithm</ulink> will be disabled. This is a
<ulink url="http://docs.oracle.com/javase/7/docs/technotes/guides/net/socketOpt.html">Java (client) socket option</ulink>. The default value for this property is <literal>true</literal>.</para>
</listitem>
<listitem>
<para><literal>tcp-send-buffer-size</literal>. This parameter determines the
size of the TCP send buffer in bytes. The default value for this property is
<literal>32768</literal> bytes (32KiB).</para>
<para>TCP buffer sizes should be tuned according to the bandwidth and latency of
your network. Here's a good link that explains the theory behind <ulink
url="http://www-didc.lbl.gov/TCP-tuning/">this</ulink>.</para>
<para>In summary TCP send/receive buffer sizes should be calculated as:</para>
<programlisting>
buffer_size = bandwidth * RTT.</programlisting>
<para>Where bandwidth is in <emphasis>bytes per second</emphasis> and network
round trip time (RTT) is in seconds. RTT can be easily measured using the
<literal>ping</literal> utility.</para>
<para>For fast networks you may want to increase the buffer sizes from the
defaults.</para>
</listitem>
<listitem>
<para><literal>tcp-receive-buffer-size</literal>. This parameter determines the
size of the TCP receive buffer in bytes. The default value for this property
is <literal>32768</literal> bytes (32KiB).</para>
</listitem>
<listitem>
<para><literal>batch-delay</literal>. Before writing packets to the transport,
ActiveMQ can be configured to batch up writes for a maximum of <literal
>batch-delay</literal> milliseconds. This can increase overall
throughput for very small messages. It does so at the expense of an increase
in average latency for message transfer. The default value for this property
is <literal>0</literal> ms.</para>
</listitem>
<listitem>
<para><literal>direct-deliver</literal>. When a message arrives on the server
and is delivered to waiting consumers, by default, the delivery is done on
the same thread as that on which the message arrived. This gives good latency
in environments with relatively small messages and a small number of consumers,
but at the cost of overall throughput and scalability - especially on multi-core
machines. If you want the lowest latency and a possible reduction in throughput
then you can use the default value for <literal>direct-deliver</literal> (i.e.
true). If you are willing to take some small extra hit on latency but want the
highest throughput set <literal>direct-deliver</literal> to <literal>false
</literal>.</para>
</listitem>
<listitem>
<para><literal>nio-remoting-threads</literal>. When configured to use NIO,
ActiveMQ will, by default, use a number of threads equal to three times the
number of cores (or hyper-threads) as reported by <literal
>Runtime.getRuntime().availableProcessors()</literal> for processing
incoming packets. If you want to override this value, you can set the number
of threads by specifying this parameter. The default value for this
parameter is <literal>-1</literal> which means use the value from <literal
>Runtime.getRuntime().availableProcessors()</literal> * 3.</para>
</listitem>
<listitem>
<para><literal>local-address</literal>. When configured a Netty Connector it is possible to specify
which local address the client will use when connecting to the remote address. This is typically used
in the Application Server or when running Embedded to control which address is used for outbound
connections. If the local-address is not set then the connector will use any local address available</para>
</listitem>
<listitem>
<para><literal>local-port</literal>. When configured a Netty Connector it is possible to specify
which local port the client will use when connecting to the remote address. This is typically used
in the Application Server or when running Embedded to control which port is used for outbound
connections. If the local-port default is used, which is 0, then the connector will let the
system pick up an ephemeral port. valid ports are 0 to 65535</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Configuring Netty SSL</title>
<para>Netty SSL is similar to the Netty TCP transport but it provides additional
security by encrypting TCP connections using the Secure Sockets Layer SSL</para>
<para>Please see the examples for a full working example of using Netty SSL.</para>
<para>Netty SSL uses all the same properties as Netty TCP but adds the following
additional properties:</para>
<itemizedlist>
<listitem>
<para><literal>ssl-enabled</literal></para>
<para>Must be <literal>true</literal> to enable SSL. Default is <literal>false</literal>.</para>
</listitem>
<listitem>
<para><literal>key-store-path</literal></para>
<para>When used on an <literal>acceptor</literal> this is the path to the SSL key
store on the server which holds the server's certificates (whether self-signed
or signed by an authority).</para>
<para>When used on a <literal>connector</literal> this is the path to the client-side
SSL key store which holds the client certificates. This is only relevant
for a <literal>connector</literal> if you are using 2-way SSL (i.e. mutual
authentication). Although this value is configured on the server, it is
downloaded and used by the client. If the client needs to use a different path
from that set on the server then it can override the server-side setting by either
using the customary "javax.net.ssl.keyStore" system property or the ActiveMQ-specific
"org.apache.activemq.ssl.keyStore" system property. The ActiveMQ-specific system property
is useful if another component on client is already making use of the standard, Java
system property.</para>
</listitem>
<listitem>
<para><literal>key-store-password</literal></para>
<para>When used on an <literal>acceptor</literal> this is the password for the
server-side keystore.</para>
<para>When used on a <literal>connector</literal> this is the password for the
client-side keystore. This is only relevant for a <literal>connector</literal>
if you are using 2-way SSL (i.e. mutual authentication). Although this value can
be configured on the server, it is downloaded and used by the client. If the client
needs to use a different password from that set on the server then it can override
the server-side setting by either using the customary "javax.net.ssl.keyStorePassword"
system property or the ActiveMQ-specific "org.apache.activemq.ssl.keyStorePassword" system
property. The ActiveMQ-specific system property is useful if another component on client
is already making use of the standard, Java system property.</para>
</listitem>
<listitem>
<para><literal>trust-store-path</literal></para>
<para>When used on an <literal>acceptor</literal> this is the path to the server-side
SSL key store that holds the keys of all the clients that the server trusts. This
is only relevant for an <literal>acceptor</literal> if you are using 2-way SSL
(i.e. mutual authentication).</para>
<para>When used on a <literal>connector</literal> this is the path to the client-side
SSL key store which holds the public keys of all the servers that the client
trusts. Although this value can be configured on the server, it is downloaded and
used by the client. If the client needs to use a different path
from that set on the server then it can override the server-side setting by either
using the customary "javax.net.ssl.trustStore" system property or the ActiveMQ-specific
"org.apache.activemq.ssl.trustStore" system property. The ActiveMQ-specific system property
is useful if another component on client is already making use of the standard, Java
system property.</para>
</listitem>
<listitem>
<para><literal>trust-store-password</literal></para>
<para>When used on an <literal>acceptor</literal> this is the password for the
server-side trust store. This is only relevant for an <literal>acceptor</literal>
if you are using 2-way SSL (i.e. mutual authentication).</para>
<para>When used on a <literal>connector</literal> this is the password for the
client-side truststore. Although this value can be configured on the server, it is
downloaded and used by the client. If the client
needs to use a different password from that set on the server then it can override
the server-side setting by either using the customary "javax.net.ssl.trustStorePassword"
system property or the ActiveMQ-specific "org.apache.activemq.ssl.trustStorePassword" system
property. The ActiveMQ-specific system property is useful if another component on client
is already making use of the standard, Java system property.</para>
</listitem>
<listitem>
<para><literal>enabled-cipher-suites</literal></para>
<para>Whether used on an <literal>acceptor</literal> or <literal>connector</literal> this is a
comma separated list of cipher suites used for SSL communication. The default value is
<literal>null</literal> which means the JVM's default will be used.</para>
</listitem>
<listitem>
<para><literal>enabled-protocols</literal></para>
<para>Whether used on an <literal>acceptor</literal> or <literal>connector</literal> this is a
comma separated list of protocols used for SSL communication. The default value is
<literal>null</literal> which means the JVM's default will be used.</para>
</listitem>
<listitem>
<para><literal>need-client-auth</literal></para>
<para>This property is only for an <literal>acceptor</literal>. It tells a client connecting to this
acceptor that 2-way SSL is required. Valid values are <literal>true</literal> or
<literal>false</literal>. Default is <literal>false</literal>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Configuring Netty HTTP</title>
<para>Netty HTTP tunnels packets over the HTTP protocol. It can be useful in scenarios
where firewalls only allow HTTP traffic to pass.</para>
<para>Please see the examples for a full working example of using Netty HTTP.</para>
<para>Netty HTTP uses the same properties as Netty TCP but adds the following additional
properties:</para>
<itemizedlist>
<listitem>
<para><literal>http-enabled</literal>. This is now no longer needed as of version 2.4. With single
port support ActiveMQ will now automatically detect if http is being used and configure itself.</para>
</listitem>
<listitem>
<para><literal>http-client-idle-time</literal>. How long a client can be idle
before sending an empty http request to keep the connection alive</para>
</listitem>
<listitem>
<para><literal>http-client-idle-scan-period</literal>. How often, in
milliseconds, to scan for idle clients</para>
</listitem>
<listitem>
<para><literal>http-response-time</literal>. How long the server can wait before
sending an empty http response to keep the connection alive</para>
</listitem>
<listitem>
<para><literal>http-server-scan-period</literal>. How often, in milliseconds, to
scan for clients needing responses</para>
</listitem>
<listitem>
<para><literal>http-requires-session-id</literal>. If true the client will wait
after the first call to receive a session id. Used the http connector is
connecting to servlet acceptor (not recommended) </para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Configuring Netty Servlet</title>
<para>As of 2.4 ActiveMQ Servlet support will be provided via Undertow in Wildfly</para>
</section>
</section>
</chapter>

View File

@ -0,0 +1,198 @@
Detecting Dead Connections
==========================
In this section we will discuss connection time-to-live (TTL) and
explain how ActiveMQ deals with crashed clients and clients which have
exited without cleanly closing their resources.
Cleaning up Dead Connection Resources on the Server
===================================================
Before a ActiveMQ client application exits it is considered good
practice that it should close its resources in a controlled manner,
using a `finally` block.
Here's an example of a well behaved core client application closing its
session and session factory in a finally block:
ServerLocator locator = null;
ClientSessionFactory sf = null;
ClientSession session = null;
try
{
locator = ActiveMQClient.createServerLocatorWithoutHA(..);
sf = locator.createClientSessionFactory();;
session = sf.createSession(...);
... do some stuff with the session...
}
finally
{
if (session != null)
{
session.close();
}
if (sf != null)
{
sf.close();
}
if(locator != null)
{
locator.close();
}
}
And here's an example of a well behaved JMS client application:
Connection jmsConnection = null;
try
{
ConnectionFactory jmsConnectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(...);
jmsConnection = jmsConnectionFactory.createConnection();
... do some stuff with the connection...
}
finally
{
if (connection != null)
{
connection.close();
}
}
Unfortunately users don't always write well behaved applications, and
sometimes clients just crash so they don't have a chance to clean up
their resources!
If this occurs then it can leave server side resources, like sessions,
hanging on the server. If these were not removed they would cause a
resource leak on the server and over time this result in the server
running out of memory or other resources.
We have to balance the requirement for cleaning up dead client resources
with the fact that sometimes the network between the client and the
server can fail and then come back, allowing the client to reconnect.
ActiveMQ supports client reconnection, so we don't want to clean up
"dead" server side resources too soon or this will prevent any client
from reconnecting, as it won't be able to find its old sessions on the
server.
ActiveMQ makes all of this configurable. For each `ClientSessionFactory`
we define a *connection TTL*. Basically, the TTL determines how long the
server will keep a connection alive in the absence of any data arriving
from the client. The client will automatically send "ping" packets
periodically to prevent the server from closing it down. If the server
doesn't receive any packets on a connection for the connection TTL time,
then it will automatically close all the sessions on the server that
relate to that connection.
If you're using JMS, the connection TTL is defined by the
`ConnectionTTL` attribute on a `ActiveMQConnectionFactory` instance, or
if you're deploying JMS connection factory instances direct into JNDI on
the server side, you can specify it in the xml config, using the
parameter `connection-ttl`.
The default value for connection ttl on an "unreliable" connection (e.g.
a Netty connection) is `60000`ms, i.e. 1 minute. The default value for
connection ttl on a "reliable" connection (e.g. an in-vm connection) is
`-1`. A value of `-1` for `ConnectionTTL` means the server will never
time out the connection on the server side.
If you do not wish clients to be able to specify their own connection
TTL, you can override all values used by a global value set on the
server side. This can be done by specifying the
`connection-ttl-override` attribute in the server side configuration.
The default value for `connection-ttl-override` is `-1` which means "do
not override" (i.e. let clients use their own values).
Closing core sessions or JMS connections that you have failed to close
----------------------------------------------------------------------
As previously discussed, it's important that all core client sessions
and JMS connections are always closed explicitly in a `finally` block
when you are finished using them.
If you fail to do so, ActiveMQ will detect this at garbage collection
time, and log a warning similar to the following in the logs (If you are
using JMS the warning will involve a JMS connection not a client
session):
[Finalizer] 20:14:43,244 WARNING [org.apache.activemq.core.client.impl.DelegatingSession] I'm closing a ClientSession you left open. Please make sure you close all ClientSessions explicitly before let
ting them go out of scope!
[Finalizer] 20:14:43,244 WARNING [org.apache.activemq.core.client.impl.DelegatingSession] The session you didn't close was created here:
java.lang.Exception
at org.apache.activemq.core.client.impl.DelegatingSession.<init>(DelegatingSession.java:83)
at org.acme.yourproject.YourClass (YourClass.java:666)
ActiveMQ will then close the connection / client session for you.
Note that the log will also tell you the exact line of your user code
where you created the JMS connection / client session that you later did
not close. This will enable you to pinpoint the error in your code and
correct it appropriately.
Detecting failure from the client side.
=======================================
In the previous section we discussed how the client sends pings to the
server and how "dead" connection resources are cleaned up by the server.
There's also another reason for pinging, and that's for the *client* to
be able to detect that the server or network has failed.
As long as the client is receiving data from the server it will consider
the connection to be still alive.
If the client does not receive any packets for
`client-failure-check-period` milliseconds then it will consider the
connection failed and will either initiate failover, or call any
`FailureListener` instances (or `ExceptionListener` instances if you are
using JMS) depending on how it has been configured.
If you're using JMS it's defined by the `ClientFailureCheckPeriod`
attribute on a `ActiveMQConnectionFactory` instance, or if you're
deploying JMS connection factory instances direct into JNDI on the
server side, you can specify it in the `activemq-jms.xml ` configuration
file, using the parameter `client-failure-check-period`.
The default value for client failure check period on an "unreliable"
connection (e.g. a Netty connection) is `30000`ms, i.e. 30 seconds. The
default value for client failure check period on a "reliable" connection
(e.g. an in-vm connection) is `-1`. A value of `-1` means the client
will never fail the connection on the client side if no data is received
from the server. Typically this is much lower than connection TTL to
allow clients to reconnect in case of transitory failure.
Configuring Asynchronous Connection Execution
=============================================
Most packets received on the server side are executed on the remoting
thread. These packets represent short-running operations and are always
executed on the remoting thread for performance reasons.
However, by default some kinds of packets are executed using a thread
from a thread pool so that the remoting thread is not tied up for too
long. Please note that processing operations asynchronously on another
thread adds a little more latency. These packets are:
- `org.apache.activemq.core.protocol.core.impl.wireformat.RollbackMessage`
- `org.apache.activemq.core.protocol.core.impl.wireformat.SessionCloseMessage`
- `org.apache.activemq.core.protocol.core.impl.wireformat.SessionCommitMessage`
- `org.apache.activemq.core.protocol.core.impl.wireformat.SessionXACommitMessage`
- `org.apache.activemq.core.protocol.core.impl.wireformat.SessionXAPrepareMessage`
- `org.apache.activemq.core.protocol.core.impl.wireformat.SessionXARollbackMessage`
To disable asynchronous connection execution, set the parameter
`async-connection-execution-enabled` in `activemq-configuration.xml` to
`false` (default value is `true`).

View File

@ -1,202 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="connection-ttl">
<title>Detecting Dead Connections</title>
<para>In this section we will discuss connection time-to-live (TTL) and explain how ActiveMQ
deals with crashed clients and clients which have exited without cleanly closing their
resources.</para>
<section id="dead.connections">
<title>Cleaning up Dead Connection Resources on the Server</title>
<para>Before a ActiveMQ client application exits it is considered good practice that it
should close its resources in a controlled manner, using a <literal>finally</literal>
block.</para>
<para>Here's an example of a well behaved core client application closing its session and
session factory in a finally block:</para>
<programlisting>
ServerLocator locator = null;
ClientSessionFactory sf = null;
ClientSession session = null;
try
{
locator = ActiveMQClient.createServerLocatorWithoutHA(..);
sf = locator.createClientSessionFactory();;
session = sf.createSession(...);
... do some stuff with the session...
}
finally
{
if (session != null)
{
session.close();
}
if (sf != null)
{
sf.close();
}
if(locator != null)
{
locator.close();
}
}</programlisting>
<para>And here's an example of a well behaved JMS client application:</para>
<programlisting>
Connection jmsConnection = null;
try
{
ConnectionFactory jmsConnectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(...);
jmsConnection = jmsConnectionFactory.createConnection();
... do some stuff with the connection...
}
finally
{
if (connection != null)
{
connection.close();
}
}</programlisting>
<para>Unfortunately users don't always write well behaved applications, and sometimes
clients just crash so they don't have a chance to clean up their resources!</para>
<para>If this occurs then it can leave server side resources, like sessions, hanging on the
server. If these were not removed they would cause a resource leak on the server and
over time this result in the server running out of memory or other resources.</para>
<para>We have to balance the requirement for cleaning up dead client resources with the fact
that sometimes the network between the client and the server can fail and then come
back, allowing the client to reconnect. ActiveMQ supports client reconnection, so we
don't want to clean up "dead" server side resources too soon or this will prevent any
client from reconnecting, as it won't be able to find its old sessions on the
server.</para>
<para>ActiveMQ makes all of this configurable. For each <literal
>ClientSessionFactory</literal> we define a <emphasis>connection TTL</emphasis>.
Basically, the TTL determines how long the server will keep a connection alive in the
absence of any data arriving from the client. The client will automatically send "ping"
packets periodically to prevent the server from closing it down. If the server doesn't
receive any packets on a connection for the connection TTL time, then it will
automatically close all the sessions on the server that relate to that
connection.</para>
<para>If you're using JMS, the connection TTL is defined by the <literal
>ConnectionTTL</literal> attribute on a <literal>ActiveMQConnectionFactory</literal>
instance, or if you're deploying JMS connection factory instances direct into JNDI on
the server side, you can specify it in the xml config, using the parameter <literal
>connection-ttl</literal>.</para>
<para>The default value for connection ttl on an "unreliable" connection (e.g. a Netty
connection) is <literal>60000</literal>ms, i.e. 1 minute. The default value for connection
ttl on a "reliable" connection (e.g. an in-vm connection) is <literal>-1</literal>. A
value of <literal>-1</literal> for <literal>ConnectionTTL</literal> means the server
will never time out the connection on the server side.</para>
<para id="connection-ttl.override">If you do not wish clients to be able to specify their own connection TTL, you can
override all values used by a global value set on the server side. This can be done by
specifying the <literal>connection-ttl-override</literal> attribute in the server side
configuration. The default value for <literal>connection-ttl-override</literal> is
<literal>-1</literal> which means "do not override" (i.e. let clients use their own
values).</para>
<section>
<title>Closing core sessions or JMS connections that you have failed to close</title>
<para>As previously discussed, it's important that all core client sessions and JMS
connections are always closed explicitly in a <literal>finally</literal> block when
you are finished using them. </para>
<para>If you fail to do so, ActiveMQ will detect this at garbage collection time, and log
a warning similar to the following in the logs (If you are using JMS the warning
will involve a JMS connection not a client session):</para>
<programlisting>
[Finalizer] 20:14:43,244 WARNING [org.apache.activemq.core.client.impl.DelegatingSession] I'm closing a ClientSession you left open. Please make sure you close all ClientSessions explicitly before let
ting them go out of scope!
[Finalizer] 20:14:43,244 WARNING [org.apache.activemq.core.client.impl.DelegatingSession] The session you didn't close was created here:
java.lang.Exception
at org.apache.activemq.core.client.impl.DelegatingSession.&lt;init>(DelegatingSession.java:83)
at org.acme.yourproject.YourClass (YourClass.java:666)</programlisting>
<para>ActiveMQ will then close the connection / client session for you.</para>
<para>Note that the log will also tell you the exact line of your user code where you
created the JMS connection / client session that you later did not close. This will
enable you to pinpoint the error in your code and correct it appropriately.</para>
</section>
</section>
<section>
<title>Detecting failure from the client side.</title>
<para>In the previous section we discussed how the client sends pings to the server and how
"dead" connection resources are cleaned up by the server. There's also another reason
for pinging, and that's for the <emphasis>client</emphasis> to be able to detect that
the server or network has failed.</para>
<para>As long as the client is receiving data from the server it will consider the
connection to be still alive. </para>
<para>If the client does not receive any packets for <literal
>client-failure-check-period</literal> milliseconds then it will consider the
connection failed and will either initiate failover, or call any <literal
>FailureListener</literal> instances (or <literal>ExceptionListener</literal>
instances if you are using JMS) depending on how it has been configured.</para>
<para>If you're using JMS it's defined by the <literal>ClientFailureCheckPeriod</literal>
attribute on a <literal>ActiveMQConnectionFactory</literal> instance, or if you're
deploying JMS connection factory instances direct into JNDI on the server side, you can
specify it in the <literal>activemq-jms.xml </literal> configuration file, using the
parameter <literal>client-failure-check-period</literal>.</para>
<para>The default value for client failure check period on an "unreliable" connection (e.g.
a Netty connection) is <literal>30000</literal>ms, i.e. 30 seconds. The default value
for client failure check period on a "reliable" connection (e.g. an in-vm connection)
is <literal>-1</literal>. A value of <literal>-1</literal> means the client will never fail the
connection on the client side if no data is received from the server. Typically this is
much lower than connection TTL to allow clients to reconnect in case of transitory
failure.</para>
</section>
<section id="connection-ttl.async-connection-execution">
<title>Configuring Asynchronous Connection Execution</title>
<para>Most packets received on the server side are executed on the remoting thread. These packets
represent short-running operations and are always executed on the remoting thread for
performance reasons.</para>
<para>However, by default some kinds of packets are executed using a thread from a
thread pool so that the remoting thread is not tied up for too long. Please note that
processing operations asynchronously on another thread adds a little more latency. These packets
are:</para>
<itemizedlist>
<listitem>
<para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.RollbackMessage</literal></para>
</listitem>
<listitem>
<para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionCloseMessage</literal></para>
</listitem>
<listitem>
<para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionCommitMessage</literal></para>
</listitem>
<listitem>
<para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionXACommitMessage</literal></para>
</listitem>
<listitem>
<para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionXAPrepareMessage</literal></para>
</listitem>
<listitem>
<para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionXARollbackMessage</literal></para>
</listitem>
</itemizedlist>
<para>To disable asynchronous connection execution, set the parameter
<literal>async-connection-execution-enabled</literal> in
<literal>activemq-configuration.xml</literal> to <literal>false</literal> (default value is
<literal>true</literal>).</para>
</section>
</chapter>

View File

@ -0,0 +1,225 @@
Core Bridges
============
The function of a bridge is to consume messages from a source queue, and
forward them to a target address, typically on a different ActiveMQ
server.
The source and target servers do not have to be in the same cluster
which makes bridging suitable for reliably sending messages from one
cluster to another, for instance across a WAN, or internet and where the
connection may be unreliable.
The bridge has built in resilience to failure so if the target server
connection is lost, e.g. due to network failure, the bridge will retry
connecting to the target until it comes back online. When it comes back
online it will resume operation as normal.
In summary, bridges are a way to reliably connect two separate ActiveMQ
servers together. With a core bridge both source and target servers must
be ActiveMQ servers.
Bridges can be configured to provide *once and only once* delivery
guarantees even in the event of the failure of the source or the target
server. They do this by using duplicate detection (described in ?).
> **Note**
>
> Although they have similar function, don't confuse core bridges with
> JMS bridges!
>
> Core bridges are for linking a ActiveMQ node with another ActiveMQ
> node and do not use the JMS API. A JMS Bridge is used for linking any
> two JMS 1.1 compliant JMS providers. So, a JMS Bridge could be used
> for bridging to or from different JMS compliant messaging system. It's
> always preferable to use a core bridge if you can. Core bridges use
> duplicate detection to provide *once and only once* guarantees. To
> provide the same guarantee using a JMS bridge you would have to use XA
> which has a higher overhead and is more complex to configure.
Configuring Bridges
===================
Bridges are configured in `activemq-configuration.xml`. Let's kick off
with an example (this is actually from the bridge example):
<bridge name="my-bridge">
<queue-name>jms.queue.sausage-factory</queue-name>
<forwarding-address>jms.queue.mincing-machine</forwarding-address>
<filter-string="name='aardvark'"/>
<transformer-class-name>
org.apache.activemq.jms.example.HatColourChangeTransformer
</transformer-class-name>
<retry-interval>1000</retry-interval>
<ha>true</ha>
<retry-interval-multiplier>1.0</retry-interval-multiplier>
<initial-connect-attempts>-1</initial-connect-attempts>
<reconnect-attempts>-1</reconnect-attempts>
<failover-on-server-shutdown>false</failover-on-server-shutdown>
<use-duplicate-detection>true</use-duplicate-detection>
<confirmation-window-size>10000000</confirmation-window-size>
<user>foouser</user>
<password>foopassword</password>
<static-connectors>
<connector-ref>remote-connector</connector-ref>
</static-connectors>
<!-- alternative to static-connectors
<discovery-group-ref discovery-group-name="bridge-discovery-group"/>
-->
</bridge>
In the above example we have shown all the parameters its possible to
configure for a bridge. In practice you might use many of the defaults
so it won't be necessary to specify them all explicitly.
Let's take a look at all the parameters in turn:
- `name` attribute. All bridges must have a unique name in the server.
- `queue-name`. This is the unique name of the local queue that the
bridge consumes from, it's a mandatory parameter.
The queue must already exist by the time the bridge is instantiated
at start-up.
> **Note**
>
> If you're using JMS then normally the JMS configuration
> `activemq-jms.xml` is loaded after the core configuration file
> `activemq-configuration.xml` is loaded. If your bridge is
> consuming from a JMS queue then you'll need to make sure the JMS
> queue is also deployed as a core queue in the core configuration.
> Take a look at the bridge example for an example of how this is
> done.
- `forwarding-address`. This is the address on the target server that
the message will be forwarded to. If a forwarding address is not
specified, then the original address of the message will be
retained.
- `filter-string`. An optional filter string can be supplied. If
specified then only messages which match the filter expression
specified in the filter string will be forwarded. The filter string
follows the ActiveMQ filter expression syntax described in ?.
- `transformer-class-name`. An optional transformer-class-name can be
specified. This is the name of a user-defined class which implements
the `org.apache.activemq.core.server.cluster.Transformer` interface.
If this is specified then the transformer's `transform()` method
will be invoked with the message before it is forwarded. This gives
you the opportunity to transform the message's header or body before
forwarding it.
- `ha`. This optional parameter determines whether or not this bridge
should support high availability. True means it will connect to any
available server in a cluster and support failover. The default
value is `false`.
- `retry-interval`. This optional parameter determines the period in
milliseconds between subsequent reconnection attempts, if the
connection to the target server has failed. The default value is
`2000`milliseconds.
- `retry-interval-multiplier`. This optional parameter determines
determines a multiplier to apply to the time since the last retry to
compute the time to the next retry.
This allows you to implement an *exponential backoff* between retry
attempts.
Let's take an example:
If we set `retry-interval`to `1000` ms and we set
`retry-interval-multiplier` to `2.0`, then, if the first reconnect
attempt fails, we will wait `1000` ms then `2000` ms then `4000` ms
between subsequent reconnection attempts.
The default value is `1.0` meaning each reconnect attempt is spaced
at equal intervals.
- `initial-connect-attempts`. This optional parameter determines the
total number of initial connect attempts the bridge will make before
giving up and shutting down. A value of `-1` signifies an unlimited
number of attempts. The default value is `-1`.
- `reconnect-attempts`. This optional parameter determines the total
number of reconnect attempts the bridge will make before giving up
and shutting down. A value of `-1` signifies an unlimited number of
attempts. The default value is `-1`.
- `failover-on-server-shutdown`. This optional parameter determines
whether the bridge will attempt to failover onto a backup server (if
specified) when the target server is cleanly shutdown rather than
crashed.
The bridge connector can specify both a live and a backup server, if
it specifies a backup server and this parameter is set to `true`
then if the target server is *cleanly* shutdown the bridge
connection will attempt to failover onto its backup. If the bridge
connector has no backup server configured then this parameter has no
effect.
Sometimes you want a bridge configured with a live and a backup
target server, but you don't want to failover to the backup if the
live server is simply taken down temporarily for maintenance, this
is when this parameter comes in handy.
The default value for this parameter is `false`.
- `use-duplicate-detection`. This optional parameter determines
whether the bridge will automatically insert a duplicate id property
into each message that it forwards.
Doing so, allows the target server to perform duplicate detection on
messages it receives from the source server. If the connection fails
or server crashes, then, when the bridge resumes it will resend
unacknowledged messages. This might result in duplicate messages
being sent to the target server. By enabling duplicate detection
allows these duplicates to be screened out and ignored.
This allows the bridge to provide a *once and only once* delivery
guarantee without using heavyweight methods such as XA (see ? for
more information).
The default value for this parameter is `true`.
- `confirmation-window-size`. This optional parameter determines the
`confirmation-window-size` to use for the connection used to forward
messages to the target node. This attribute is described in section
?
> **Warning**
>
> When using the bridge to forward messages to an address which uses
> the `BLOCK` `address-full-policy` from a queue which has a
> `max-size-bytes` set it's important that
> `confirmation-window-size` is less than or equal to
> `max-size-bytes` to prevent the flow of messages from ceasing.
- `user`. This optional parameter determines the user name to use when
creating the bridge connection to the remote server. If it is not
specified the default cluster user specified by `cluster-user` in
`activemq-configuration.xml` will be used.
- `password`. This optional parameter determines the password to use
when creating the bridge connection to the remote server. If it is
not specified the default cluster password specified by
`cluster-password` in `activemq-configuration.xml` will be used.
- `static-connectors` or `discovery-group-ref`. Pick either of these
options to connect the bridge to the target server.
The `static-connectors` is a list of `connector-ref` elements
pointing to `connector` elements defined elsewhere. A *connector*
encapsulates knowledge of what transport to use (TCP, SSL, HTTP etc)
as well as the server connection parameters (host, port etc). For
more information about what connectors are and how to configure
them, please see ?.
The `discovery-group-ref` element has one attribute -
`discovery-group-name`. This attribute points to a `discovery-group`
defined elsewhere. For more information about what discovery-groups
are and how to configure them, please see ?.

View File

@ -1,241 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="core-bridges">
<title>Core Bridges</title>
<para>The function of a bridge is to consume messages from a source queue, and forward them to a
target address, typically on a different ActiveMQ server.</para>
<para>The source and target servers do not have to be in the same cluster which makes bridging
suitable for reliably sending messages from one cluster to another, for instance across a
WAN, or internet and where the connection may be unreliable.</para>
<para>The bridge has built in resilience to failure so if the target server connection is lost,
e.g. due to network failure, the bridge will retry connecting to the target until it comes
back online. When it comes back online it will resume operation as normal.</para>
<para>In summary, bridges are a way to reliably connect two separate ActiveMQ servers together.
With a core bridge both source and target servers must be ActiveMQ servers.</para>
<para>Bridges can be configured to provide <emphasis>once and only once</emphasis> delivery
guarantees even in the event of the failure of the source or the target server. They do this
by using duplicate detection (described in <xref linkend="duplicate-detection"/>).</para>
<note>
<para>Although they have similar function, don't confuse core bridges with JMS
bridges!</para>
<para>Core bridges are for linking a ActiveMQ node with another ActiveMQ node and do not use
the JMS API. A JMS Bridge is used for linking any two JMS 1.1 compliant JMS providers.
So, a JMS Bridge could be used for bridging to or from different JMS compliant messaging
system. It's always preferable to use a core bridge if you can. Core bridges use
duplicate detection to provide <emphasis>once and only once</emphasis> guarantees. To
provide the same guarantee using a JMS bridge you would have to use XA which has a
higher overhead and is more complex to configure.</para>
</note>
<section>
<title>Configuring Bridges</title>
<para>Bridges are configured in <literal>activemq-configuration.xml</literal>. Let's kick off
with an example (this is actually from the bridge example):</para>
<programlisting>
&lt;bridge name="my-bridge">
&lt;queue-name>jms.queue.sausage-factory&lt;/queue-name>
&lt;forwarding-address>jms.queue.mincing-machine&lt;/forwarding-address>
&lt;filter-string="name='aardvark'"/>
&lt;transformer-class-name>
org.apache.activemq.jms.example.HatColourChangeTransformer
&lt;/transformer-class-name>
&lt;retry-interval>1000&lt;/retry-interval>
&lt;ha>true&lt;/ha>
&lt;retry-interval-multiplier>1.0&lt;/retry-interval-multiplier>
&lt;initial-connect-attempts>-1&lt;/initial-connect-attempts>
&lt;reconnect-attempts>-1&lt;/reconnect-attempts>
&lt;failover-on-server-shutdown>false&lt;/failover-on-server-shutdown>
&lt;use-duplicate-detection>true&lt;/use-duplicate-detection>
&lt;confirmation-window-size>10000000&lt;/confirmation-window-size>
&lt;user>foouser&lt;/user>
&lt;password>foopassword&lt;/password>
&lt;static-connectors>
&lt;connector-ref>remote-connector&lt;/connector-ref>
&lt;/static-connectors>
&lt;!-- alternative to static-connectors
&lt;discovery-group-ref discovery-group-name="bridge-discovery-group"/>
-->
&lt;/bridge></programlisting>
<para>In the above example we have shown all the parameters its possible to configure for a
bridge. In practice you might use many of the defaults so it won't be necessary to
specify them all explicitly.</para>
<para>Let's take a look at all the parameters in turn:</para>
<itemizedlist>
<listitem>
<para><literal>name</literal> attribute. All bridges must have a unique name in the
server.</para>
</listitem>
<listitem>
<para><literal>queue-name</literal>. This is the unique name of the local queue that
the bridge consumes from, it's a mandatory parameter.</para>
<para>The queue must already exist by the time the bridge is instantiated at
start-up.</para>
<note>
<para>If you're using JMS then normally the JMS configuration <literal
>activemq-jms.xml</literal> is loaded after the core configuration file
<literal>activemq-configuration.xml</literal> is loaded. If your bridge
is consuming from a JMS queue then you'll need to make sure the JMS queue is
also deployed as a core queue in the core configuration. Take a look at the
bridge example for an example of how this is done.</para>
</note>
</listitem>
<listitem>
<para><literal>forwarding-address</literal>. This is the address on the target
server that the message will be forwarded to. If a forwarding address is not
specified, then the original address of the message will be retained.</para>
</listitem>
<listitem>
<para><literal>filter-string</literal>. An optional filter string can be supplied.
If specified then only messages which match the filter expression specified in
the filter string will be forwarded. The filter string follows the ActiveMQ
filter expression syntax described in <xref linkend="filter-expressions"
/>.</para>
</listitem>
<listitem>
<para><literal>transformer-class-name</literal>. An optional transformer-class-name
can be specified. This is the name of a user-defined class which implements the
<literal>org.apache.activemq.core.server.cluster.Transformer</literal>
interface.</para>
<para>If this is specified then the transformer's <literal>transform()</literal>
method will be invoked with the message before it is forwarded. This gives you
the opportunity to transform the message's header or body before forwarding
it.</para>
</listitem>
<listitem>
<para><literal>ha</literal>. This optional parameter determines whether or not this
bridge should support high availability. True means it will connect to any available
server in a cluster and support failover. The default value is <literal
>false</literal>.</para>
</listitem>
<listitem>
<para><literal>retry-interval</literal>. This optional parameter determines the
period in milliseconds between subsequent reconnection attempts, if the
connection to the target server has failed. The default value is <literal
>2000</literal>milliseconds.</para>
</listitem>
<listitem>
<para><literal>retry-interval-multiplier</literal>. This optional parameter
determines determines a multiplier to apply to the time since the last retry to
compute the time to the next retry.</para>
<para>This allows you to implement an <emphasis>exponential backoff</emphasis>
between retry attempts.</para>
<para>Let's take an example:</para>
<para>If we set <literal>retry-interval</literal>to <literal>1000</literal> ms and
we set <literal>retry-interval-multiplier</literal> to <literal>2.0</literal>,
then, if the first reconnect attempt fails, we will wait <literal>1000</literal>
ms then <literal>2000</literal> ms then <literal>4000</literal> ms between
subsequent reconnection attempts.</para>
<para>The default value is <literal>1.0</literal> meaning each reconnect attempt is
spaced at equal intervals.</para>
</listitem>
<listitem>
<para><literal>initial-connect-attempts</literal>. This optional parameter determines the
total number of initial connect attempts the bridge will make before giving up and
shutting down. A value of <literal>-1</literal> signifies an unlimited number of
attempts. The default value is <literal>-1</literal>.</para>
</listitem>
<listitem>
<para><literal>reconnect-attempts</literal>. This optional parameter determines the
total number of reconnect attempts the bridge will make before giving up and
shutting down. A value of <literal>-1</literal> signifies an unlimited number of
attempts. The default value is <literal>-1</literal>.</para>
</listitem>
<listitem>
<para><literal>failover-on-server-shutdown</literal>. This optional parameter
determines whether the bridge will attempt to failover onto a backup server (if
specified) when the target server is cleanly shutdown rather than
crashed.</para>
<para>The bridge connector can specify both a live and a backup server, if it
specifies a backup server and this parameter is set to <literal>true</literal>
then if the target server is <emphasis>cleanly</emphasis> shutdown the bridge
connection will attempt to failover onto its backup. If the bridge connector has
no backup server configured then this parameter has no effect. </para>
<para>Sometimes you want a bridge configured with a live and a backup target server,
but you don't want to failover to the backup if the live server is simply taken
down temporarily for maintenance, this is when this parameter comes in
handy.</para>
<para>The default value for this parameter is <literal>false</literal>.</para>
</listitem>
<listitem>
<para><literal>use-duplicate-detection</literal>. This optional parameter determines
whether the bridge will automatically insert a duplicate id property into each
message that it forwards.</para>
<para>Doing so, allows the target server to perform duplicate detection on messages
it receives from the source server. If the connection fails or server crashes,
then, when the bridge resumes it will resend unacknowledged messages. This might
result in duplicate messages being sent to the target server. By enabling
duplicate detection allows these duplicates to be screened out and
ignored.</para>
<para>This allows the bridge to provide a <emphasis>once and only once</emphasis>
delivery guarantee without using heavyweight methods such as XA (see <xref
linkend="duplicate-detection"/> for more information).</para>
<para>The default value for this parameter is <literal>true</literal>.</para>
</listitem>
<listitem>
<para><literal>confirmation-window-size</literal>. This optional parameter
determines the <literal>confirmation-window-size</literal> to use for the
connection used to forward messages to the target node. This attribute is
described in section <xref linkend="client-reconnection"/></para>
<warning><para>When using the bridge to forward messages to an address which uses
the <literal>BLOCK</literal> <literal>address-full-policy</literal> from a
queue which has a <literal>max-size-bytes</literal> set it's important that
<literal>confirmation-window-size</literal> is less than or equal to
<literal>max-size-bytes</literal> to prevent the flow of messages from
ceasing.</para>
</warning>
</listitem>
<listitem>
<para><literal>user</literal>. This optional parameter determines the user name to
use when creating the bridge connection to the remote server. If it is not
specified the default cluster user specified by <literal>cluster-user</literal>
in <literal>activemq-configuration.xml</literal> will be used. </para>
</listitem>
<listitem>
<para><literal>password</literal>. This optional parameter determines the password
to use when creating the bridge connection to the remote server. If it is not
specified the default cluster password specified by <literal
>cluster-password</literal> in <literal>activemq-configuration.xml</literal>
will be used. </para>
</listitem>
<listitem>
<para><literal>static-connectors</literal> or <literal>discovery-group-ref</literal>.
Pick either of these options to connect the bridge to the target server.
</para>
<para> The <literal>static-connectors</literal> is a list of <literal>connector-ref</literal>
elements pointing to <literal>connector</literal> elements defined elsewhere.
A <emphasis>connector</emphasis> encapsulates knowledge of what transport to
use (TCP, SSL, HTTP etc) as well as the server connection parameters (host, port
etc). For more information about what connectors are and how to configure them,
please see <xref linkend="configuring-transports"/>.
</para>
<para>The <literal>discovery-group-ref</literal> element has one attribute -
<literal>discovery-group-name</literal>. This attribute points to a
<literal>discovery-group</literal> defined elsewhere. For more information about
what discovery-groups are and how to configure them, please see
<xref linkend="clusters.discovery-groups"/>.
</para>
</listitem>
</itemizedlist>
</section>
</chapter>

View File

@ -0,0 +1,114 @@
Diverting and Splitting Message Flows
=====================================
ActiveMQ allows you to configure objects called *diverts* with some
simple server configuration.
Diverts allow you to transparently divert messages routed to one address
to some other address, without making any changes to any client
application logic.
Diverts can be *exclusive*, meaning that the message is diverted to the
new address, and does not go to the old address at all, or they can be
*non-exclusive* which means the message continues to go the old address,
and a *copy* of it is also sent to the new address. Non-exclusive
diverts can therefore be used for *splitting* message flows, e.g. there
may be a requirement to monitor every order sent to an order queue.
Diverts can also be configured to have an optional message filter. If
specified then only messages that match the filter will be diverted.
Diverts can also be configured to apply a `Transformer`. If specified,
all diverted messages will have the opportunity of being transformed by
the `Transformer`.
A divert will only divert a message to an address on the *same server*,
however, if you want to divert to an address on a different server, a
common pattern would be to divert to a local store-and-forward queue,
then set up a bridge which consumes from that queue and forwards to an
address on a different server.
Diverts are therefore a very sophisticated concept, which when combined
with bridges can be used to create interesting and complex routings. The
set of diverts on a server can be thought of as a type of routing table
for messages. Combining diverts with bridges allows you to create a
distributed network of reliable routing connections between multiple
geographically distributed servers, creating your global messaging mesh.
Diverts are defined as xml in the `activemq-configuration.xml` file.
There can be zero or more diverts in the file.
Please see ? for a full working example showing you how to configure and
use diverts.
Let's take a look at some divert examples:
Exclusive Divert
================
Let's take a look at an exclusive divert. An exclusive divert diverts
all matching messages that are routed to the old address to the new
address. Matching messages do not get routed to the old address.
Here's some example xml configuration for an exclusive divert, it's
taken from the divert example:
<divert name="prices-divert">
<address>jms.topic.priceUpdates</address>
<forwarding-address>jms.queue.priceForwarding</forwarding-address>
<filter string="office='New York'"/>
<transformer-class-name>
org.apache.activemq.jms.example.AddForwardingTimeTransformer
</transformer-class-name>
<exclusive>true</exclusive>
</divert>
We define a divert called '`prices-divert`' that will divert any
messages sent to the address '`jms.topic.priceUpdates`' (this
corresponds to any messages sent to a JMS Topic called '`priceUpdates`')
to another local address '`jms.queue.priceForwarding`' (this corresponds
to a local JMS queue called '`priceForwarding`'
We also specify a message filter string so only messages with the
message property `office` with value `New York` will get diverted, all
other messages will continue to be routed to the normal address. The
filter string is optional, if not specified then all messages will be
considered matched.
In this example a transformer class is specified. Again this is
optional, and if specified the transformer will be executed for each
matching message. This allows you to change the messages body or
properties before it is diverted. In this example the transformer simply
adds a header that records the time the divert happened.
This example is actually diverting messages to a local store and forward
queue, which is configured with a bridge which forwards the message to
an address on another ActiveMQ server. Please see the example for more
details.
Non-exclusive Divert
====================
Now we'll take a look at a non-exclusive divert. Non exclusive diverts
are the same as exclusive diverts, but they only forward a *copy* of the
message to the new address. The original message continues to the old
address
You can therefore think of non-exclusive diverts as *splitting* a
message flow.
Non exclusive diverts can be configured in the same way as exclusive
diverts with an optional filter and transformer, here's an example
non-exclusive divert, again from the divert example:
<divert name="order-divert">
<address>jms.queue.orders</address>
<forwarding-address>jms.topic.spyTopic</forwarding-address>
<exclusive>false</exclusive>
</divert>
The above divert example takes a copy of every message sent to the
address '`jms.queue.orders`' (Which corresponds to a JMS Queue called
'`orders`') and sends it to a local address called
'`jms.topic.SpyTopic`' (which corresponds to a JMS Topic called
'`SpyTopic`').

View File

@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="diverts">
<title>Diverting and Splitting Message Flows</title>
<para>ActiveMQ allows you to configure objects called <emphasis>diverts</emphasis> with
some simple server configuration.</para>
<para>Diverts allow you to transparently divert messages routed to one address to some other
address, without making any changes to any client application logic.</para>
<para>Diverts can be <emphasis>exclusive</emphasis>, meaning that the message is diverted
to the new address, and does not go to the old address at all, or they can be
<emphasis>non-exclusive</emphasis> which means the message continues to go the old
address, and a <emphasis>copy</emphasis> of it is also sent to the new address.
Non-exclusive diverts can therefore be used for <emphasis>splitting</emphasis> message
flows, e.g. there may be a requirement to monitor every order sent to an order queue.</para>
<para>Diverts can also be configured to have an optional message filter. If specified then only
messages that match the filter will be diverted.</para>
<para>Diverts can also be configured to apply a <literal>Transformer</literal>. If specified,
all diverted messages will have the opportunity of being transformed by the <literal
>Transformer</literal>.</para>
<para>A divert will only divert a message to an address on the <emphasis>same server</emphasis>,
however, if you want to divert to an address on a different server, a common pattern would
be to divert to a local store-and-forward queue, then set up a bridge which consumes from
that queue and forwards to an address on a different server.</para>
<para>Diverts are therefore a very sophisticated concept, which when combined with bridges can
be used to create interesting and complex routings. The set of diverts on a server can be
thought of as a type of routing table for messages. Combining diverts with bridges allows
you to create a distributed network of reliable routing connections between multiple
geographically distributed servers, creating your global messaging mesh.</para>
<para>Diverts are defined as xml in the <literal>activemq-configuration.xml</literal> file. There can
be zero or more diverts in the file.</para>
<para>Please see <xref linkend="divert-example" /> for a full working
example showing you how to configure and use diverts.</para>
<para>Let's take a look at some divert examples:</para>
<section>
<title>Exclusive Divert</title>
<para>Let's take a look at an exclusive divert. An exclusive divert diverts all matching
messages that are routed to the old address to the new address. Matching messages do not
get routed to the old address.</para>
<para>Here's some example xml configuration for an exclusive divert, it's taken from the
divert example:</para>
<programlisting>
&lt;divert name="prices-divert">
&lt;address>jms.topic.priceUpdates&lt;/address>
&lt;forwarding-address>jms.queue.priceForwarding&lt;/forwarding-address>
&lt;filter string="office='New York'"/>
&lt;transformer-class-name>
org.apache.activemq.jms.example.AddForwardingTimeTransformer
&lt;/transformer-class-name>
&lt;exclusive>true&lt;/exclusive>
&lt;/divert></programlisting>
<para>We define a divert called '<literal>prices-divert</literal>' that will divert any
messages sent to the address '<literal>jms.topic.priceUpdates</literal>' (this
corresponds to any messages sent to a JMS Topic called '<literal
>priceUpdates</literal>') to another local address '<literal
>jms.queue.priceForwarding</literal>' (this corresponds to a local JMS queue called
'<literal>priceForwarding</literal>'</para>
<para>We also specify a message filter string so only messages with the message property
<literal>office</literal> with value <literal>New York</literal> will get diverted,
all other messages will continue to be routed to the normal address. The filter string
is optional, if not specified then all messages will be considered matched.</para>
<para>In this example a transformer class is specified. Again this is optional, and if
specified the transformer will be executed for each matching message. This allows you to
change the messages body or properties before it is diverted. In this example the
transformer simply adds a header that records the time the divert happened.</para>
<para>This example is actually diverting messages to a local store and forward queue, which
is configured with a bridge which forwards the message to an address on another ActiveMQ
server. Please see the example for more details.</para>
</section>
<section>
<title>Non-exclusive Divert</title>
<para>Now we'll take a look at a non-exclusive divert. Non exclusive diverts are the same as
exclusive diverts, but they only forward a <emphasis>copy</emphasis> of the message to
the new address. The original message continues to the old address</para>
<para>You can therefore think of non-exclusive diverts as <emphasis>splitting</emphasis> a
message flow.</para>
<para>Non exclusive diverts can be configured in the same way as exclusive diverts with an
optional filter and transformer, here's an example non-exclusive divert, again from the
divert example:</para>
<programlisting>
&lt;divert name="order-divert">
&lt;address>jms.queue.orders&lt;/address>
&lt;forwarding-address>jms.topic.spyTopic&lt;/forwarding-address>
&lt;exclusive>false&lt;/exclusive>
&lt;/divert></programlisting>
<para>The above divert example takes a copy of every message sent to the address '<literal
>jms.queue.orders</literal>' (Which corresponds to a JMS Queue called '<literal
>orders</literal>') and sends it to a local address called '<literal
>jms.topic.SpyTopic</literal>' (which corresponds to a JMS Topic called '<literal
>SpyTopic</literal>').</para>
</section>
</chapter>

View File

@ -0,0 +1,161 @@
Duplicate Message Detection
===========================
ActiveMQ includes powerful automatic duplicate message detection,
filtering out duplicate messages without you having to code your own
fiddly duplicate detection logic at the application level. This chapter
will explain what duplicate detection is, how ActiveMQ uses it and how
and where to configure it.
When sending messages from a client to a server, or indeed from a server
to another server, if the target server or connection fails sometime
after sending the message, but before the sender receives a response
that the send (or commit) was processed successfully then the sender
cannot know for sure if the message was sent successfully to the
address.
If the target server or connection failed after the send was received
and processed but before the response was sent back then the message
will have been sent to the address successfully, but if the target
server or connection failed before the send was received and finished
processing then it will not have been sent to the address successfully.
From the senders point of view it's not possible to distinguish these
two cases.
When the server recovers this leaves the client in a difficult
situation. It knows the target server failed, but it does not know if
the last message reached its destination ok. If it decides to resend the
last message, then that could result in a duplicate message being sent
to the address. If each message was an order or a trade then this could
result in the order being fulfilled twice or the trade being double
booked. This is clearly not a desirable situation.
Sending the message(s) in a transaction does not help out either. If the
server or connection fails while the transaction commit is being
processed it is also indeterminate whether the transaction was
successfully committed or not!
To solve these issues ActiveMQ provides automatic duplicate messages
detection for messages sent to addresses.
Using Duplicate Detection for Message Sending
=============================================
Enabling duplicate message detection for sent messages is simple: you
just need to set a special property on the message to a unique value.
You can create the value however you like, as long as it is unique. When
the target server receives the message it will check if that property is
set, if it is, then it will check in its in memory cache if it has
already received a message with that value of the header. If it has
received a message with the same value before then it will ignore the
message.
> **Note**
>
> Using duplicate detection to move messages between nodes can give you
> the same *once and only once* delivery guarantees as if you were using
> an XA transaction to consume messages from source and send them to the
> target, but with less overhead and much easier configuration than
> using XA.
If you're sending messages in a transaction then you don't have to set
the property for *every* message you send in that transaction, you only
need to set it once in the transaction. If the server detects a
duplicate message for any message in the transaction, then it will
ignore the entire transaction.
The name of the property that you set is given by the value of
`org.apache.activemq.api.core.Message.HDR_DUPLICATE_DETECTION_ID`, which
is `_HQ_DUPL_ID`
The value of the property can be of type `byte[]` or `SimpleString` if
you're using the core API. If you're using JMS it must be a `String`,
and its value should be unique. An easy way of generating a unique id is
by generating a UUID.
Here's an example of setting the property using the core API:
...
ClientMessage message = session.createMessage(true);
SimpleString myUniqueID = "This is my unique id"; // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID, myUniqueID);
...
And here's an example using the JMS API:
...
Message jmsMessage = session.createMessage();
String myUniqueID = "This is my unique id"; // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID);
...
Configuring the Duplicate ID Cache
==================================
The server maintains caches of received values of the
`org.apache.activemq.core.message.impl.HDR_DUPLICATE_DETECTION_ID`
property sent to each address. Each address has its own distinct cache.
The cache is a circular fixed size cache. If the cache has a maximum
size of `n` elements, then the `n + 1`th id stored will overwrite the
`0`th element in the cache.
The maximum size of the cache is configured by the parameter
`id-cache-size` in `activemq-configuration.xml`, the default value is
`2000` elements.
The caches can also be configured to persist to disk or not. This is
configured by the parameter `persist-id-cache`, also in
`activemq-configuration.xml`. If this is set to `true` then each id will
be persisted to permanent storage as they are received. The default
value for this parameter is `true`.
> **Note**
>
> When choosing a size of the duplicate id cache be sure to set it to a
> larger enough size so if you resend messages all the previously sent
> ones are in the cache not having been overwritten.
Duplicate Detection and Bridges
===============================
Core bridges can be configured to automatically add a unique duplicate
id value (if there isn't already one in the message) before forwarding
the message to it's target. This ensures that if the target server
crashes or the connection is interrupted and the bridge resends the
message, then if it has already been received by the target server, it
will be ignored.
To configure a core bridge to add the duplicate id header, simply set
the `use-duplicate-detection` to `true` when configuring a bridge in
`activemq-configuration.xml`.
The default value for this parameter is `true`.
For more information on core bridges and how to configure them, please
see ?.
Duplicate Detection and Cluster Connections
===========================================
Cluster connections internally use core bridges to move messages
reliable between nodes of the cluster. Consequently they can also be
configured to insert the duplicate id header for each message they move
using their internal bridges.
To configure a cluster connection to add the duplicate id header, simply
set the `use-duplicate-detection` to `true` when configuring a cluster
connection in `activemq-configuration.xml`.
The default value for this parameter is `true`.
For more information on cluster connections and how to configure them,
please see ?.

View File

@ -1,148 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="duplicate-detection">
<title>Duplicate Message Detection</title>
<para>ActiveMQ includes powerful automatic duplicate message detection, filtering out
duplicate messages without you having to code your own fiddly duplicate detection logic at
the application level. This chapter will explain what duplicate detection is, how ActiveMQ
uses it and how and where to configure it.</para>
<para>When sending messages from a client to a server, or indeed from a server to another
server, if the target server or connection fails sometime after sending the message, but
before the sender receives a response that the send (or commit) was processed successfully
then the sender cannot know for sure if the message was sent successfully to the
address.</para>
<para>If the target server or connection failed after the send was received and processed but
before the response was sent back then the message will have been sent to the address
successfully, but if the target server or connection failed before the send was received and
finished processing then it will not have been sent to the address successfully. From the
senders point of view it's not possible to distinguish these two cases.</para>
<para>When the server recovers this leaves the client in a difficult situation. It knows the
target server failed, but it does not know if the last message reached its destination ok.
If it decides to resend the last message, then that could result in a duplicate message
being sent to the address. If each message was an order or a trade then this could result in
the order being fulfilled twice or the trade being double booked. This is clearly not a
desirable situation.</para>
<para>Sending the message(s) in a transaction does not help out either. If the server or
connection fails while the transaction commit is being processed it is also indeterminate
whether the transaction was successfully committed or not!</para>
<para>To solve these issues ActiveMQ provides automatic duplicate messages detection for
messages sent to addresses.</para>
<section>
<title>Using Duplicate Detection for Message Sending</title>
<para>Enabling duplicate message detection for sent messages is simple: you just need to set
a special property on the message to a unique value. You can create the value however
you like, as long as it is unique. When the target server receives the message it will
check if that property is set, if it is, then it will check in its in memory cache if it
has already received a message with that value of the header. If it has received a
message with the same value before then it will ignore the message.</para>
<note>
<para>Using duplicate detection to move messages between nodes can give you the same
<emphasis>once and only once</emphasis> delivery guarantees as if you were using
an XA transaction to consume messages from source and send them to the target, but
with less overhead and much easier configuration than using XA.</para>
</note>
<para>If you're sending messages in a transaction then you don't have to set the property
for <emphasis>every</emphasis> message you send in that transaction, you only need to
set it once in the transaction. If the server detects a duplicate message for any
message in the transaction, then it will ignore the entire transaction.</para>
<para>The name of the property that you set is given by the value of <literal
>org.apache.activemq.api.core.Message.HDR_DUPLICATE_DETECTION_ID</literal>, which
is <literal>_HQ_DUPL_ID</literal></para>
<para>The value of the property can be of type <literal>byte[]</literal> or <literal
>SimpleString</literal> if you're using the core API. If you're using JMS it must be
a <literal>String</literal>, and its value should be unique. An easy way of generating
a unique id is by generating a UUID.</para>
<para>Here's an example of setting the property using the core API:</para>
<programlisting>
...
ClientMessage message = session.createMessage(true);
SimpleString myUniqueID = "This is my unique id"; // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID, myUniqueID);
...</programlisting>
<para>And here's an example using the JMS API:</para>
<programlisting>
...
Message jmsMessage = session.createMessage();
String myUniqueID = "This is my unique id"; // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID);
...</programlisting>
</section>
<section id="duplicate.id.cache">
<title>Configuring the Duplicate ID Cache</title>
<para>The server maintains caches of received values of the <literal
>org.apache.activemq.core.message.impl.HDR_DUPLICATE_DETECTION_ID</literal> property
sent to each address. Each address has its own distinct cache.</para>
<para>The cache is a circular fixed size cache. If the cache has a maximum size of <literal
>n</literal> elements, then the <literal>n + 1</literal>th id stored will overwrite
the <literal>0</literal>th element in the cache.</para>
<para>The maximum size of the cache is configured by the parameter <literal
>id-cache-size</literal> in <literal>activemq-configuration.xml</literal>, the default
value is <literal>2000</literal> elements.</para>
<para>The caches can also be configured to persist to disk or not. This is configured by the
parameter <literal>persist-id-cache</literal>, also in <literal
>activemq-configuration.xml</literal>. If this is set to <literal>true</literal> then
each id will be persisted to permanent storage as they are received. The default value
for this parameter is <literal>true</literal>.</para>
<note>
<para>When choosing a size of the duplicate id cache be sure to set it to a larger
enough size so if you resend messages all the previously sent ones are in the cache
not having been overwritten.</para>
</note>
</section>
<section>
<title>Duplicate Detection and Bridges</title>
<para>Core bridges can be configured to automatically add a unique duplicate id value (if there
isn't already one in the message) before forwarding the message to it's target. This
ensures that if the target server crashes or the connection is interrupted and the
bridge resends the message, then if it has already been received by the target server,
it will be ignored.</para>
<para>To configure a core bridge to add the duplicate id header, simply set the <parameter
>use-duplicate-detection</parameter> to <literal>true</literal> when configuring a
bridge in <literal>activemq-configuration.xml</literal>.</para>
<para>The default value for this parameter is <literal>true</literal>.</para>
<para>For more information on core bridges and how to configure them, please see
<xref linkend="core-bridges" />.</para>
</section>
<section>
<title>Duplicate Detection and Cluster Connections</title>
<para>Cluster connections internally use core bridges to move messages reliable between
nodes of the cluster. Consequently they can also be configured to insert the duplicate
id header for each message they move using their internal bridges.</para>
<para>To configure a cluster connection to add the duplicate id header, simply set the
<parameter>use-duplicate-detection</parameter> to <literal>true</literal> when
configuring a cluster connection in <literal>activemq-configuration.xml</literal>.</para>
<para>The default value for this parameter is <literal>true</literal>.</para>
<para>For more information on cluster connections and how to configure them, please see <xref
linkend="clusters"/>.</para>
</section>
</chapter>

View File

@ -0,0 +1,225 @@
Embedding ActiveMQ
==================
ActiveMQ is designed as set of simple Plain Old Java Objects (POJOs).
This means ActiveMQ can be instantiated and run in any dependency
injection framework such as JBoss Microcontainer, Spring or Google
Guice. It also means that if you have an application that could use
messaging functionality internally, then it can *directly instantiate*
ActiveMQ clients and servers in its own application code to perform that
functionality. We call this *embedding* ActiveMQ.
Examples of applications that might want to do this include any
application that needs very high performance, transactional, persistent
messaging but doesn't want the hassle of writing it all from scratch.
Embedding ActiveMQ can be done in very few easy steps. Instantiate the
configuration object, instantiate the server, start it, and you have a
ActiveMQ running in your virtual machine. It's as simple and easy as
that.
Simple Config File Embedding
============================
The simplest way to embed ActiveMQ is to use the embedded wrapper
classes and configure ActiveMQ through its configuration files. There
are two different helper classes for this depending on whether your
using the ActiveMQ Core API or JMS.
Core API Only
-------------
For instantiating a core ActiveMQ Server only, the steps are pretty
simple. The example requires that you have defined a configuration file
`activemq-configuration.xml` in your classpath:
import org.apache.activemq.core.server.embedded.EmbeddedActiveMQ;
...
EmbeddedActiveMQ embedded = new EmbeddedActiveMQ();
embedded.start();
ClientSessionFactory nettyFactory = ActiveMQClient.createClientSessionFactory(
new TransportConfiguration(
InVMConnectorFactory.class.getName()));
ClientSession session = factory.createSession();
session.createQueue("example", "example", true);
ClientProducer producer = session.createProducer("example");
ClientMessage message = session.createMessage(true);
message.getBody().writeString("Hello");
producer.send(message);
session.start();
ClientConsumer consumer = session.createConsumer("example");
ClientMessage msgReceived = consumer.receive();
System.out.println("message = " + msgReceived.getBody().readString());
session.close();
The `EmbeddedActiveMQ` class has a few additional setter methods that
allow you to specify a different config file name as well as other
properties. See the javadocs for this class for more details.
JMS API
-------
JMS embedding is simple as well. This example requires that you have
defined the config files `activemq-configuration.xml`,
`activemq-jms.xml`, and a `activemq-users.xml` if you have security
enabled. Let's also assume that a queue and connection factory has been
defined in the `activemq-jms.xml` config file.
import org.apache.activemq.jms.server.embedded.EmbeddedJMS;
...
EmbeddedJMS jms = new EmbeddedJMS();
jms.start();
// This assumes we have configured activemq-jms.xml with the appropriate config information
ConnectionFactory connectionFactory = jms.lookup("ConnectionFactory");
Destination destination = jms.lookup("/example/queue");
... regular JMS code ...
By default, the `EmbeddedJMS` class will store component entries defined
within your `activemq-jms.xml` file in an internal concurrent hash map.
The `EmbeddedJMS.lookup()` method returns components stored in this map.
If you want to use JNDI, call the `EmbeddedJMS.setContext()` method with
the root JNDI context you want your components bound into. See the
javadocs for this class for more details on other config options.
POJO instantiation - Embedding Programmatically
===============================================
You can follow this step-by-step guide to programmatically embed the
core, non-JMS ActiveMQ Server instance:
Create the configuration object - this contains configuration
information for a ActiveMQ instance. The setter methods of this class
allow you to programmatically set configuration options as describe in
the ? section.
The acceptors are configured through `ConfigurationImpl`. Just add the
`NettyAcceptorFactory` on the transports the same way you would through
the main configuration file.
import org.apache.activemq.core.config.Configuration;
import org.apache.activemq.core.config.impl.ConfigurationImpl;
...
Configuration config = new ConfigurationImpl();
HashSet<TransportConfiguration> transports = new HashSet<TransportConfiguration>();
transports.add(new TransportConfiguration(NettyAcceptorFactory.class.getName()));
transports.add(new TransportConfiguration(InVMAcceptorFactory.class.getName()));
config.setAcceptorConfigurations(transports);
You need to instantiate an instance of
`org.apache.activemq.api.core.server.embedded.EmbeddedActiveMQ` and add
the configuration object to it.
import org.apache.activemq.api.core.server.ActiveMQ;
import org.apache.activemq.core.server.embedded.EmbeddedActiveMQ;
...
EmbeddedActiveMQ server = new EmbeddedActiveMQ();
server.setConfiguration(config);
server.start();
You also have the option of instantiating `ActiveMQServerImpl` directly:
ActiveMQServer server = new ActiveMQServerImpl(config);
server.start();
For JMS POJO instantiation, you work with the EmbeddedJMS class instead
as described earlier. First you define the configuration
programmatically for your ConnectionFactory and Destination objects,
then set the JmsConfiguration property of the EmbeddedJMS class. Here is
an example of this:
// Step 1. Create ActiveMQ core configuration, and set the properties accordingly
Configuration configuration = new ConfigurationImpl();
configuration.setPersistenceEnabled(false);
configuration.setSecurityEnabled(false);
configuration.getAcceptorConfigurations().add(new TransportConfiguration(NettyAcceptorFactory.class.getName()));
// Step 2. Create the JMS configuration
JMSConfiguration jmsConfig = new JMSConfigurationImpl();
// Step 3. Configure the JMS ConnectionFactory
TransportConfiguration connectorConfig = new TransportConfiguration(NettyConnectorFactory.class.getName());
ConnectionFactoryConfiguration cfConfig = new ConnectionFactoryConfigurationImpl("cf", connectorConfig, "/cf");
jmsConfig.getConnectionFactoryConfigurations().add(cfConfig);
// Step 4. Configure the JMS Queue
JMSQueueConfiguration queueConfig = new JMSQueueConfigurationImpl("queue1", null, false, "/queue/queue1");
jmsConfig.getQueueConfigurations().add(queueConfig);
// Step 5. Start the JMS Server using the ActiveMQ core server and the JMS configuration
EmbeddedJMS jmsServer = new EmbeddedJMS();
jmsServer.setConfiguration(configuration);
jmsServer.setJmsConfiguration(jmsConfig);
jmsServer.start();
Please see ? for an example which shows how to setup and run ActiveMQ
embedded with JMS.
Dependency Frameworks
=====================
You may also choose to use a dependency injection framework such as
JBoss Micro Container or Spring Framework. See ? for more details on
Spring and ActiveMQ, but here's how you would do things with the JBoss
Micro Container.
ActiveMQ standalone uses JBoss Micro Container as the injection
framework. `ActiveMQBootstrapServer` and `activemq-beans.xml` which are
part of the ActiveMQ distribution provide a very complete implementation
of what's needed to bootstrap the server using JBoss Micro Container.
When using JBoss Micro Container, you need to provide an XML file
declaring the `ActiveMQServer` and `Configuration` object, you can also
inject a security manager and a MBean server if you want, but those are
optional.
A very basic XML Bean declaration for the JBoss Micro Container would
be:
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="urn:jboss:bean-deployer:2.0">
<!-- The core configuration -->
<bean name="Configuration"
class="org.apache.activemq.core.config.impl.FileConfiguration">
</bean>
<!-- The core server -->
<bean name="ActiveMQServer"
class="org.apache.activemq.core.server.impl.ActiveMQServerImpl">
<constructor>
<parameter>
<inject bean="Configuration"/>
</parameter>
</constructor>
</bean>
</deployment>
`ActiveMQBootstrapServer` provides an easy encapsulation of JBoss Micro
Container.
ActiveMQBootstrapServer bootStrap = new ActiveMQBootstrapServer(new String[] {"activemq-beans.xml"});
bootStrap.run();

View File

@ -1,270 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3CR3//EN"
"../../../lib/docbook-support/support/docbook-dtd/docbookx.dtd"> -->
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="embedding-activemq">
<title>Embedding ActiveMQ</title>
<para>ActiveMQ is designed as set of simple Plain Old Java Objects (POJOs).
This means ActiveMQ can be instantiated and run in any dependency injection
framework such as JBoss Microcontainer, Spring or Google Guice. It also
means that if you have an application that could use messaging functionality
internally, then it can <emphasis>directly instantiate</emphasis> ActiveMQ
clients and servers in its own application code to perform that
functionality. We call this <emphasis>embedding</emphasis> ActiveMQ.</para>
<para>Examples of applications that might want to do this include any
application that needs very high performance, transactional, persistent
messaging but doesn't want the hassle of writing it all from scratch.</para>
<para>Embedding ActiveMQ can be done in very few easy steps. Instantiate the
configuration object, instantiate the server, start it, and you have a
ActiveMQ running in your virtual machine. It's as simple and easy as
that.</para>
<section>
<title>Simple Config File Embedding</title>
<para>The simplest way to embed ActiveMQ is to use the embedded wrapper
classes and configure ActiveMQ through its configuration files. There are
two different helper classes for this depending on whether your using the
ActiveMQ Core API or JMS.</para>
<section>
<title>Core API Only</title>
<para>For instantiating a core ActiveMQ Server only, the steps are pretty
simple. The example requires that you have defined a configuration file
<literal>activemq-configuration.xml</literal> in your
classpath:</para>
<programlisting>
import org.apache.activemq.core.server.embedded.EmbeddedActiveMQ;
...
EmbeddedActiveMQ embedded = new EmbeddedActiveMQ();
embedded.start();
ClientSessionFactory nettyFactory = ActiveMQClient.createClientSessionFactory(
new TransportConfiguration(
InVMConnectorFactory.class.getName()));
ClientSession session = factory.createSession();
session.createQueue("example", "example", true);
ClientProducer producer = session.createProducer("example");
ClientMessage message = session.createMessage(true);
message.getBody().writeString("Hello");
producer.send(message);
session.start();
ClientConsumer consumer = session.createConsumer("example");
ClientMessage msgReceived = consumer.receive();
System.out.println("message = " + msgReceived.getBody().readString());
session.close();</programlisting>
<para>The <literal>EmbeddedActiveMQ</literal> class has a
few additional setter methods that allow you to specify a different
config file name as well as other properties. See the javadocs for this
class for more details.</para>
</section>
<section id="simple.embedded.jms">
<title>JMS API</title>
<para>JMS embedding is simple as well. This example requires that you
have defined the config files
<literal>activemq-configuration.xml</literal>,
<literal>activemq-jms.xml</literal>, and a
<literal>activemq-users.xml</literal> if you have security enabled. Let's
also assume that a queue and connection factory has been defined in the
<literal>activemq-jms.xml</literal> config file.</para>
<programlisting>
import org.apache.activemq.jms.server.embedded.EmbeddedJMS;
...
EmbeddedJMS jms = new EmbeddedJMS();
jms.start();
// This assumes we have configured activemq-jms.xml with the appropriate config information
ConnectionFactory connectionFactory = jms.lookup("ConnectionFactory");
Destination destination = jms.lookup("/example/queue");
... regular JMS code ...</programlisting>
<para>By default, the <literal>EmbeddedJMS</literal>
class will store component entries defined within your
<literal>activemq-jms.xml</literal> file in an internal concurrent hash
map. The <literal>EmbeddedJMS.lookup()</literal> method returns
components stored in this map. If you want to use JNDI, call the
<literal>EmbeddedJMS.setContext()</literal> method with the root JNDI
context you want your components bound into. See the javadocs for this
class for more details on other config options.</para>
</section>
</section>
<section>
<title>POJO instantiation - Embedding Programmatically</title>
<para>You can follow this step-by-step guide to programmatically embed the
core, non-JMS ActiveMQ Server instance:</para>
<para>Create the configuration object - this contains configuration
information for a ActiveMQ instance. The setter methods of this class allow
you to programmatically set configuration options as describe in the <xref
linkend="server.configuration" /> section.</para>
<para>The acceptors are configured through
<literal>ConfigurationImpl</literal>. Just add the
<literal>NettyAcceptorFactory</literal> on the transports the same way you
would through the main configuration file.</para>
<programlisting>
import org.apache.activemq.core.config.Configuration;
import org.apache.activemq.core.config.impl.ConfigurationImpl;
...
Configuration config = new ConfigurationImpl();
HashSet&lt;TransportConfiguration> transports = new HashSet&lt;TransportConfiguration>();
transports.add(new TransportConfiguration(NettyAcceptorFactory.class.getName()));
transports.add(new TransportConfiguration(InVMAcceptorFactory.class.getName()));
config.setAcceptorConfigurations(transports);</programlisting>
<para>You need to instantiate an instance of
<literal>org.apache.activemq.api.core.server.embedded.EmbeddedActiveMQ</literal>
and add the configuration object to it.</para>
<programlisting>
import org.apache.activemq.api.core.server.ActiveMQ;
import org.apache.activemq.core.server.embedded.EmbeddedActiveMQ;
...
EmbeddedActiveMQ server = new EmbeddedActiveMQ();
server.setConfiguration(config);
server.start();</programlisting>
<para>You also have the option of instantiating
<literal>ActiveMQServerImpl</literal> directly:</para>
<programlisting>
ActiveMQServer server = new ActiveMQServerImpl(config);
server.start();</programlisting>
<para>For JMS POJO instantiation, you work with the EmbeddedJMS class
instead as described earlier. First you define the configuration
programmatically for your ConnectionFactory and Destination objects, then
set the JmsConfiguration property of the EmbeddedJMS class. Here is an
example of this:</para>
<programlisting>
// Step 1. Create ActiveMQ core configuration, and set the properties accordingly
Configuration configuration = new ConfigurationImpl();
configuration.setPersistenceEnabled(false);
configuration.setSecurityEnabled(false);
configuration.getAcceptorConfigurations().add(new TransportConfiguration(NettyAcceptorFactory.class.getName()));
// Step 2. Create the JMS configuration
JMSConfiguration jmsConfig = new JMSConfigurationImpl();
// Step 3. Configure the JMS ConnectionFactory
TransportConfiguration connectorConfig = new TransportConfiguration(NettyConnectorFactory.class.getName());
ConnectionFactoryConfiguration cfConfig = new ConnectionFactoryConfigurationImpl("cf", connectorConfig, "/cf");
jmsConfig.getConnectionFactoryConfigurations().add(cfConfig);
// Step 4. Configure the JMS Queue
JMSQueueConfiguration queueConfig = new JMSQueueConfigurationImpl("queue1", null, false, "/queue/queue1");
jmsConfig.getQueueConfigurations().add(queueConfig);
// Step 5. Start the JMS Server using the ActiveMQ core server and the JMS configuration
EmbeddedJMS jmsServer = new EmbeddedJMS();
jmsServer.setConfiguration(configuration);
jmsServer.setJmsConfiguration(jmsConfig);
jmsServer.start();</programlisting>
<para>Please see <xref linkend="examples.embedded.jms" /> for an example which
shows how to setup and run ActiveMQ embedded with JMS.</para>
</section>
<section>
<title>Dependency Frameworks</title>
<para>You may also choose to use a dependency injection framework such as
<trademark>JBoss Micro Container</trademark> or <trademark>Spring
Framework</trademark>. See <xref linkend="spring.integration" /> for more
details on Spring and ActiveMQ, but here's how you would do things with the
JBoss Micro Container.</para>
<para>ActiveMQ standalone uses JBoss Micro Container as the injection
framework. <literal>ActiveMQBootstrapServer</literal> and
<literal>activemq-beans.xml</literal> which are part of the ActiveMQ
distribution provide a very complete implementation of what's needed to
bootstrap the server using JBoss Micro Container.</para>
<para>When using JBoss Micro Container, you need to provide an XML file
declaring the <literal>ActiveMQServer</literal> and
<literal>Configuration</literal> object, you can also inject a security
manager and a MBean server if you want, but those are optional.</para>
<para>A very basic XML Bean declaration for the JBoss Micro Container
would be:</para>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;deployment xmlns="urn:jboss:bean-deployer:2.0">
&lt;!-- The core configuration -->
&lt;bean name="Configuration"
class="org.apache.activemq.core.config.impl.FileConfiguration">
&lt;/bean>
&lt;!-- The core server -->
&lt;bean name="ActiveMQServer"
class="org.apache.activemq.core.server.impl.ActiveMQServerImpl">
&lt;constructor>
&lt;parameter>
&lt;inject bean="Configuration"/>
&lt;/parameter>
&lt;/constructor>
&lt;/bean>
&lt;/deployment></programlisting>
<para><literal>ActiveMQBootstrapServer</literal> provides an easy
encapsulation of JBoss Micro Container.</para>
<programlisting>
ActiveMQBootstrapServer bootStrap = new ActiveMQBootstrapServer(new String[] {"activemq-beans.xml"});
bootStrap.run();</programlisting>
</section>
</chapter>

View File

@ -0,0 +1,826 @@
Examples
========
The ActiveMQ distribution comes with over 70 run out-of-the-box examples
demonstrating many of the features.
The examples are available in the distribution, in the `examples`
directory. Examples are split into JMS and core examples. JMS examples
show how a particular feature can be used by a normal JMS client. Core
examples show how the equivalent feature can be used by a core messaging
client.
A set of Java EE examples are also provided which need WildFly installed
to be able to run.
JMS Examples
============
To run a JMS example, simply `cd` into the appropriate example directory
and type `mvn verify` (For details please read the readme.html in each
example directory).
Here's a listing of the examples with a brief description.
JMS AeroGear
------------
This example shows how you can send a message to a mobile device by
leveraging AeroGears push technology which provides support for
different push notification technologies like Google Cloud Messaging,
Apple's APNs or Mozilla's SimplePush.
Applet
------
This example shows you how to send and receive JMS messages from an
Applet.
Application-Layer Failover
--------------------------
ActiveMQ also supports Application-Layer failover, useful in the case
that replication is not enabled on the server side.
With Application-Layer failover, it's up to the application to register
a JMS `ExceptionListener` with ActiveMQ which will be called by ActiveMQ
in the event that connection failure is detected.
The code in the `ExceptionListener` then recreates the JMS connection,
session, etc on another node and the application can continue.
Application-layer failover is an alternative approach to High
Availability (HA). Application-layer failover differs from automatic
failover in that some client side coding is required in order to
implement this. Also, with Application-layer failover, since the old
session object dies and a new one is created, any uncommitted work in
the old session will be lost, and any unacknowledged messages might be
redelivered.
Core Bridge Example
-------------------
The `bridge` example demonstrates a core bridge deployed on one server,
which consumes messages from a local queue and forwards them to an
address on a second server.
Core bridges are used to create message flows between any two ActiveMQ
servers which are remotely separated. Core bridges are resilient and
will cope with temporary connection failure allowing them to be an ideal
choice for forwarding over unreliable connections, e.g. a WAN.
Browser
-------
The `browser` example shows you how to use a JMS `QueueBrowser` with
ActiveMQ.
Queues are a standard part of JMS, please consult the JMS 1.1
specification for full details.
A `QueueBrowser` is used to look at messages on the queue without
removing them. It can scan the entire content of a queue or only
messages matching a message selector.
Client Kickoff
--------------
The `client-kickoff` example shows how to terminate client connections
given an IP address using the JMX management API.
Client side failover listener
-----------------------------
The `client-side-failoverlistener` example shows how to register a
listener to monitor failover events
Client-Side Load-Balancing
--------------------------
The `client-side-load-balancing` example demonstrates how sessions
created from a single JMS `Connection` can be created to different nodes
of the cluster. In other words it demonstrates how ActiveMQ does
client-side load-balancing of sessions across the cluster.
Clustered Durable Subscription
------------------------------
This example demonstrates a clustered JMS durable subscription
Clustered Grouping
------------------
This is similar to the message grouping example except that it
demonstrates it working over a cluster. Messages sent to different nodes
with the same group id will be sent to the same node and the same
consumer.
Clustered Queue
---------------
The `clustered-queue` example demonstrates a JMS queue deployed on two
different nodes. The two nodes are configured to form a cluster. We then
create a consumer for the queue on each node, and we create a producer
on only one of the nodes. We then send some messages via the producer,
and we verify that both consumers receive the sent messages in a
round-robin fashion.
Clustering with JGroups
-----------------------
The `clustered-jgroups` example demonstrates how to form a two node
cluster using JGroups as its underlying topology discovery technique,
rather than the default UDP broadcasting. We then create a consumer for
the queue on each node, and we create a producer on only one of the
nodes. We then send some messages via the producer, and we verify that
both consumers receive the sent messages in a round-robin fashion.
Clustered Standalone
--------------------
The `clustered-standalone` example demonstrates how to configure and
starts 3 cluster nodes on the same machine to form a cluster. A
subscriber for a JMS topic is created on each node, and we create a
producer on only one of the nodes. We then send some messages via the
producer, and we verify that the 3 subscribers receive all the sent
messages.
Clustered Static Discovery
--------------------------
This example demonstrates how to configure a cluster using a list of
connectors rather than UDP for discovery
Clustered Static Cluster One Way
--------------------------------
This example demonstrates how to set up a cluster where cluster
connections are one way, i.e. server A -\> Server B -\> Server C
Clustered Topic
---------------
The `clustered-topic` example demonstrates a JMS topic deployed on two
different nodes. The two nodes are configured to form a cluster. We then
create a subscriber on the topic on each node, and we create a producer
on only one of the nodes. We then send some messages via the producer,
and we verify that both subscribers receive all the sent messages.
Message Consumer Rate Limiting
------------------------------
With ActiveMQ you can specify a maximum consume rate at which a JMS
MessageConsumer will consume messages. This can be specified when
creating or deploying the connection factory.
If this value is specified then ActiveMQ will ensure that messages are
never consumed at a rate higher than the specified rate. This is a form
of consumer throttling.
Dead Letter
-----------
The `dead-letter` example shows you how to define and deal with dead
letter messages. Messages can be delivered unsuccessfully (e.g. if the
transacted session used to consume them is rolled back).
Such a message goes back to the JMS destination ready to be redelivered.
However, this means it is possible for a message to be delivered again
and again without any success and remain in the destination, clogging
the system.
To prevent this, messaging systems define dead letter messages: after a
specified unsuccessful delivery attempts, the message is removed from
the destination and put instead in a dead letter destination where they
can be consumed for further investigation.
Delayed Redelivery
------------------
The `delayed-redelivery` example demonstrates how ActiveMQ can be
configured to provide a delayed redelivery in the case a message needs
to be redelivered.
Delaying redelivery can often be useful in the case that clients
regularly fail or roll-back. Without a delayed redelivery, the system
can get into a "thrashing" state, with delivery being attempted, the
client rolling back, and delivery being re-attempted in quick
succession, using up valuable CPU and network resources.
Divert
------
ActiveMQ diverts allow messages to be transparently "diverted" or copied
from one address to another with just some simple configuration defined
on the server side.
Durable Subscription
--------------------
The `durable-subscription` example shows you how to use a durable
subscription with ActiveMQ. Durable subscriptions are a standard part of
JMS, please consult the JMS 1.1 specification for full details.
Unlike non-durable subscriptions, the key function of durable
subscriptions is that the messages contained in them persist longer than
the lifetime of the subscriber - i.e. they will accumulate messages sent
to the topic even if there is no active subscriber on them. They will
also survive server restarts or crashes. Note that for the messages to
be persisted, the messages sent to them must be marked as durable
messages.
Embedded
--------
The `embedded` example shows how to embed JMS within your own code using
POJO instantiation and no config files.
Embedded Simple
---------------
The `embedded` example shows how to embed JMS within your own code using
regular ActiveMQ XML files.
Message Expiration
------------------
The `expiry` example shows you how to define and deal with message
expiration. Messages can be retained in the messaging system for a
limited period of time before being removed. JMS specification states
that clients should not receive messages that have been expired (but it
does not guarantee this will not happen).
ActiveMQ can assign an expiry address to a given queue so that when
messages are expired, they are removed from the queue and sent to the
expiry address. These "expired" messages can later be consumed from the
expiry address for further inspection.
ActiveMQ Resource Adapter example
---------------------------------
This examples shows how to build the activemq resource adapters a rar
for deployment in other Application Server's
HTTP Transport
--------------
The `http-transport` example shows you how to configure ActiveMQ to use
the HTTP protocol as its transport layer.
Instantiate JMS Objects Directly
--------------------------------
Usually, JMS Objects such as `ConnectionFactory`, `Queue` and `Topic`
instances are looked up from JNDI before being used by the client code.
This objects are called "administered objects" in JMS terminology.
However, in some cases a JNDI server may not be available or desired. To
come to the rescue ActiveMQ also supports the direct instantiation of
these administered objects on the client side so you don't have to use
JNDI for JMS.
Interceptor
-----------
ActiveMQ allows an application to use an interceptor to hook into the
messaging system. Interceptors allow you to handle various message
events in ActiveMQ.
JAAS
----
The `jaas` example shows you how to configure ActiveMQ to use JAAS for
security. ActiveMQ can leverage JAAS to delegate user authentication and
authorization to existing security infrastructure.
JMS Auto Closable
-----------------
The `jms-auto-closeable` example shows how JMS resources, such as
connections, sessions and consumers, in JMS 2 can be automatically
closed on error.
JMS Completion Listener
-----------------------
The `jms-completion-listener` example shows how to send a message
asynchronously to ActiveMQ and use a CompletionListener to be notified
of the Broker receiving it.
JMS Bridge
----------
The `jms-brige` example shows how to setup a bridge between two
standalone ActiveMQ servers.
JMS Context
-----------
The `jms-context` example shows how to send and receive a message to a
JMS Queue using ActiveMQ by using a JMS Context.
A JMSContext is part of JMS 2.0 and combines the JMS Connection and
Session Objects into a simple Interface.
JMS Shared Consumer
-------------------
The `jms-shared-consumer` example shows you how can use shared consumers
to share a subscription on a topic. In JMS 1.1 this was not allowed and
so caused a scalability issue. In JMS 2 this restriction has been lifted
so you can share the load across different threads and connections.
JMX Management
--------------
The `jmx` example shows how to manage ActiveMQ using JMX.
Large Message
-------------
The `large-message` example shows you how to send and receive very large
messages with ActiveMQ. ActiveMQ supports the sending and receiving of
huge messages, much larger than can fit in available RAM on the client
or server. Effectively the only limit to message size is the amount of
disk space you have on the server.
Large messages are persisted on the server so they can survive a server
restart. In other words ActiveMQ doesn't just do a simple socket stream
from the sender to the consumer.
Last-Value Queue
----------------
The `last-value-queue` example shows you how to define and deal with
last-value queues. Last-value queues are special queues which discard
any messages when a newer message with the same value for a well-defined
last-value property is put in the queue. In other words, a last-value
queue only retains the last value.
A typical example for last-value queue is for stock prices, where you
are only interested by the latest price for a particular stock.
Management
----------
The `management` example shows how to manage ActiveMQ using JMS Messages
to invoke management operations on the server.
Management Notification
-----------------------
The `management-notification` example shows how to receive management
notifications from ActiveMQ using JMS messages. ActiveMQ servers emit
management notifications when events of interest occur (consumers are
created or closed, addresses are created or deleted, security
authentication fails, etc.).
Message Counter
---------------
The `message-counters` example shows you how to use message counters to
obtain message information for a JMS queue.
Message Group
-------------
The `message-group` example shows you how to configure and use message
groups with ActiveMQ. Message groups allow you to pin messages so they
are only consumed by a single consumer. Message groups are sets of
messages that has the following characteristics:
- Messages in a message group share the same group id, i.e. they have
same JMSXGroupID string property values
- The consumer that receives the first message of a group will receive
all the messages that belongs to the group
Message Group
-------------
The `message-group2` example shows you how to configure and use message
groups with ActiveMQ via a connection factory.
Message Priority
----------------
Message Priority can be used to influence the delivery order for
messages.
It can be retrieved by the message's standard header field 'JMSPriority'
as defined in JMS specification version 1.1.
The value is of type integer, ranging from 0 (the lowest) to 9 (the
highest). When messages are being delivered, their priorities will
effect their order of delivery. Messages of higher priorities will
likely be delivered before those of lower priorities.
Messages of equal priorities are delivered in the natural order of their
arrival at their destinations. Please consult the JMS 1.1 specification
for full details.
Multiple Failover
-----------------
This example demonstrates how to set up a live server with multiple
backups
Multiple Failover Failback
--------------------------
This example demonstrates how to set up a live server with multiple
backups but forcing failover back to the original live server
No Consumer Buffering
---------------------
By default, ActiveMQ consumers buffer messages from the server in a
client side buffer before you actually receive them on the client side.
This improves performance since otherwise every time you called
receive() or had processed the last message in a
`MessageListener onMessage()` method, the ActiveMQ client would have to
go the server to request the next message, which would then get sent to
the client side, if one was available.
This would involve a network round trip for every message and reduce
performance. Therefore, by default, ActiveMQ pre-fetches messages into a
buffer on each consumer.
In some case buffering is not desirable, and ActiveMQ allows it to be
switched off. This example demonstrates that.
Non-Transaction Failover With Server Data Replication
-----------------------------------------------------
The `non-transaction-failover` example demonstrates two servers coupled
as a live-backup pair for high availability (HA), and a client using a
*non-transacted* JMS session failing over from live to backup when the
live server is crashed.
ActiveMQ implements failover of client connections between live and
backup servers. This is implemented by the replication of state between
live and backup nodes. When replication is configured and a live node
crashes, the client connections can carry and continue to send and
consume messages. When non-transacted sessions are used, once and only
once message delivery is not guaranteed and it is possible that some
messages will be lost or delivered twice.
OpenWire
--------
The `Openwire` example shows how to configure a ActiveMQ server to
communicate with an ActiveMQ JMS client that uses open-wire protocol.
Paging
------
The `paging` example shows how ActiveMQ can support huge queues even
when the server is running in limited RAM. It does this by transparently
*paging* messages to disk, and *depaging* them when they are required.
Pre-Acknowledge
---------------
Standard JMS supports three acknowledgement modes:`
AUTO_ACKNOWLEDGE`, `CLIENT_ACKNOWLEDGE`, and
`DUPS_OK_ACKNOWLEDGE`. For a full description on these modes please
consult the JMS specification, or any JMS tutorial.
All of these standard modes involve sending acknowledgements from the
client to the server. However in some cases, you really don't mind
losing messages in event of failure, so it would make sense to
acknowledge the message on the server before delivering it to the
client. This example demonstrates how ActiveMQ allows this with an extra
acknowledgement mode.
Message Producer Rate Limiting
------------------------------
The `producer-rte-limit` example demonstrates how, with ActiveMQ, you
can specify a maximum send rate at which a JMS message producer will
send messages.
Proton Qpid
-----------
ActiveMQ can be configured to accept requests from any AMQP client that
supports the 1.0 version of the protocol. This `proton-j` example shows
a simply qpid java 1.0 client example.
Proton Ruby
-----------
ActiveMQ can be configured to accept requests from any AMQP client that
supports the 1.0 version of the protocol. This example shows a simply
proton ruby client that sends and receives messages
Queue
-----
A simple example demonstrating a JMS queue.
Message Redistribution
----------------------
The `queue-message-redistribution` example demonstrates message
redistribution between queues with the same name deployed in different
nodes of a cluster.
Queue Requestor
---------------
A simple example demonstrating a JMS queue requestor.
Queue with Message Selector
---------------------------
The `queue-selector` example shows you how to selectively consume
messages using message selectors with queue consumers.
Reattach Node example
---------------------
The `Reattach Node` example shows how a client can try to reconnect to
the same server instead of failing the connection immediately and
notifying any user ExceptionListener objects. ActiveMQ can be configured
to automatically retry the connection, and reattach to the server when
it becomes available again across the network.
Replicated Failback example
---------------------------
An example showing how failback works when using replication, In this
example a live server will replicate all its Journal to a backup server
as it updates it. When the live server crashes the backup takes over
from the live server and the client reconnects and carries on from where
it left off.
Replicated Failback static example
----------------------------------
An example showing how failback works when using replication, but this
time with static connectors
Replicated multiple failover example
------------------------------------
An example showing how to configure multiple backups when using
replication
Replicated Failover transaction example
---------------------------------------
An example showing how failover works with a transaction when using
replication
Request-Reply example
---------------------
A simple example showing the JMS request-response pattern.
Rest example
------------
An example showing how to use the ActiveMQ Rest API
Scheduled Message
-----------------
The `scheduled-message` example shows you how to send a scheduled
message to a JMS Queue with ActiveMQ. Scheduled messages won't get
delivered until a specified time in the future.
Security
--------
The `security` example shows you how configure and use role based queue
security with ActiveMQ.
Send Acknowledgements
---------------------
The `send-acknowledgements` example shows you how to use ActiveMQ's
advanced *asynchronous send acknowledgements* feature to obtain
acknowledgement from the server that sends have been received and
processed in a separate stream to the sent messages.
Spring Integration
------------------
This example shows how to use embedded JMS using ActiveMQ's Spring
integration.
SSL Transport
-------------
The `ssl-enabled` shows you how to configure SSL with ActiveMQ to send
and receive message.
Static Message Selector
-----------------------
The `static-selector` example shows you how to configure a ActiveMQ core
queue with static message selectors (filters).
Static Message Selector Using JMS
---------------------------------
The `static-selector-jms` example shows you how to configure a ActiveMQ
queue with static message selectors (filters) using JMS.
Stomp
-----
The `stomp` example shows you how to configure a ActiveMQ server to send
and receive Stomp messages.
Stomp1.1
--------
The `stomp` example shows you how to configure a ActiveMQ server to send
and receive Stomp messages via a Stomp 1.1 connection.
Stomp1.2
--------
The `stomp` example shows you how to configure a ActiveMQ server to send
and receive Stomp messages via a Stomp 1.2 connection.
Stomp Over Web Sockets
----------------------
The `stomp-websockets` example shows you how to configure a ActiveMQ
server to send and receive Stomp messages directly from Web browsers
(provided they support Web Sockets).
Symmetric Cluster
-----------------
The `symmetric-cluster` example demonstrates a symmetric cluster set-up
with ActiveMQ.
ActiveMQ has extremely flexible clustering which allows you to set-up
servers in many different topologies. The most common topology that
you'll perhaps be familiar with if you are used to application server
clustering is a symmetric cluster.
With a symmetric cluster, the cluster is homogeneous, i.e. each node is
configured the same as every other node, and every node is connected to
every other node in the cluster.
Temporary Queue
---------------
A simple example demonstrating how to use a JMS temporary queue.
Topic
-----
A simple example demonstrating a JMS topic.
Topic Hierarchy
---------------
ActiveMQ supports topic hierarchies. With a topic hierarchy you can
register a subscriber with a wild-card and that subscriber will receive
any messages sent to an address that matches the wild card.
Topic Selector 1
----------------
The `topic-selector-example1` example shows you how to send message to a
JMS Topic, and subscribe them using selectors with ActiveMQ.
Topic Selector 2
----------------
The `topic-selector-example2` example shows you how to selectively
consume messages using message selectors with topic consumers.
Transaction Failover
--------------------
The `transaction-failover` example demonstrates two servers coupled as a
live-backup pair for high availability (HA), and a client using a
transacted JMS session failing over from live to backup when the live
server is crashed.
ActiveMQ implements failover of client connections between live and
backup servers. This is implemented by the sharing of a journal between
the servers. When a live node crashes, the client connections can carry
and continue to send and consume messages. When transacted sessions are
used, once and only once message delivery is guaranteed.
Failover Without Transactions
-----------------------------
The `stop-server-failover` example demonstrates failover of the JMS
connection from one node to another when the live server crashes using a
JMS non-transacted session.
Transactional Session
---------------------
The `transactional` example shows you how to use a transactional Session
with ActiveMQ.
XA Heuristic
------------
The `xa-heuristic` example shows you how to make an XA heuristic
decision through ActiveMQ Management Interface. A heuristic decision is
a unilateral decision to commit or rollback an XA transaction branch
after it has been prepared.
XA Receive
----------
The `xa-receive` example shows you how message receiving behaves in an
XA transaction in ActiveMQ.
XA Send
-------
The `xa-send` example shows you how message sending behaves in an XA
transaction in ActiveMQ.
XA with Transaction Manager
---------------------------
The `xa-with-jta` example shows you how to use JTA interfaces to control
transactions with ActiveMQ.
Core API Examples
=================
To run a core example, simply `cd` into the appropriate example
directory and type `ant`
Embedded
--------
The `embedded` example shows how to embed the ActiveMQ server within
your own code.
Java EE Examples
================
Most of the Java EE examples can be run the following way. Simply
navigate into the appropriate example directory and type `mvn verify`.
This will use Arquillian to run the Application Server and deploy the
application. Note that you must have WildFly installed and the
JBOSS\_HOME environment variable set. Please refer to the examples
documentation for further instructions.
> **Note**
>
> When running the Java EE examples you may see warning messages in the
> WildFly log about incompatible client and server versions. This is
> normal if a newer version of the ActiveMQ project is being used with a
> version of WildFly that ships an older version of ActiveMQ. These
> examples should still complete without any functional errors.
EJB/JMS Transaction
-------------------
An example that shows using an EJB and JMS together within a
transaction.
Resource Adapter Configuration
------------------------------
This example demonstrates how to configure several properties on the
ActiveMQ JCA resource adaptor.
Resource Adapter Remote Server Configuration
--------------------------------------------
This example demonstrates how to configure the ActiveMQ resource adapter
to talk to a remote ActiveMQ server
JMS Bridge
----------
An example demonstrating the use of the ActiveMQ JMS bridge.
MDB (Message Driven Bean)
-------------------------
A simple set of examples of message driven beans, including failover
examples.
Servlet Transport
-----------------
An example of how to use the ActiveMQ servlet transport.
Servlet SSL Transport
---------------------
An example of how to use the ActiveMQ servlet transport over SSL.
XA Recovery
-----------
An example of how XA recovery works within the JBoss Application server
using ActiveMQ.

View File

@ -1,693 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="examples">
<title>Examples</title>
<para>The ActiveMQ distribution comes with over 70 run out-of-the-box examples demonstrating many
of the features.</para>
<para>The examples are available in the distribution, in the <literal>examples</literal>
directory. Examples are split into JMS and core examples. JMS examples show how a particular
feature can be used by a normal JMS client. Core examples show how the equivalent feature
can be used by a core messaging client.</para>
<para>A set of Java EE examples are also provided which need WildFly
installed to be able to run.</para>
<section>
<title>JMS Examples</title>
<para>To run a JMS example, simply <literal>cd</literal> into the appropriate example
directory and type <literal>mvn verify</literal> (For details please read the readme.html
in each example directory).</para>
<para>Here's a listing of the examples with a brief description.</para>
<section id="examples.aerogear">
<title>JMS AeroGear</title>
<para>This example shows how you can send a message to a mobile device by leveraging
AeroGears push technology which provides support for different push notification technologies
like Google Cloud Messaging, Apple's APNs or Mozilla's SimplePush.</para>
</section>
<section id="examples.applet">
<title>Applet</title>
<para>This example shows you how to send and receive JMS messages from an Applet.</para>
</section>
<section id="application-level-failover">
<title>Application-Layer Failover</title>
<para>ActiveMQ also supports Application-Layer failover, useful in the case that
replication is not enabled on the server side.</para>
<para>With Application-Layer failover, it's up to the application to register a JMS
<literal>ExceptionListener</literal> with ActiveMQ which will be called by
ActiveMQ in the event that connection failure is detected.</para>
<para>The code in the <literal>ExceptionListener</literal> then recreates the JMS
connection, session, etc on another node and the application can continue.</para>
<para>Application-layer failover is an alternative approach to High Availability (HA).
Application-layer failover differs from automatic failover in that some client side
coding is required in order to implement this. Also, with Application-layer
failover, since the old session object dies and a new one is created, any
uncommitted work in the old session will be lost, and any unacknowledged messages
might be redelivered.</para>
</section>
<section id="examples.bridge">
<title>Core Bridge Example</title>
<para>The <literal>bridge</literal> example demonstrates a core bridge deployed on one
server, which consumes messages from a local queue and forwards them to an address
on a second server.</para>
<para>Core bridges are used to create message flows between any two ActiveMQ servers
which are remotely separated. Core bridges are resilient and will cope with
temporary connection failure allowing them to be an ideal choice for forwarding over
unreliable connections, e.g. a WAN.</para>
</section>
<section id="examples.browsers">
<title>Browser</title>
<para>The <literal>browser</literal> example shows you how to use a JMS <literal
>QueueBrowser</literal> with ActiveMQ.</para>
<para>Queues are a standard part of JMS, please consult the JMS 1.1 specification for
full details.</para>
<para> A <literal>QueueBrowser</literal> is used to look at messages on the queue
without removing them. It can scan the entire content of a queue or only messages
matching a message selector.</para>
</section>
<section>
<title>Client Kickoff</title>
<para>The <literal>client-kickoff</literal> example shows how to terminate client
connections given an IP address using the JMX management API.</para>
</section>
<section>
<title>Client side failover listener</title>
<para>The <literal>client-side-failoverlistener</literal> example shows how to register a listener to monitor
failover events</para>
</section>
<section>
<title>Client-Side Load-Balancing</title>
<para>The <literal>client-side-load-balancing</literal> example demonstrates how
sessions created from a single JMS <literal>Connection</literal> can
be created to different nodes of the cluster. In other words it demonstrates how
ActiveMQ does client-side load-balancing of sessions across the cluster.</para>
</section>
<section id="examples.clustered.durable">
<title>Clustered Durable Subscription</title>
<para>This example demonstrates a clustered JMS durable subscription</para>
</section>
<section id="examples.clustered.grouping">
<title>Clustered Grouping</title>
<para>This is similar to the message grouping example except that it demonstrates it
working over a cluster. Messages sent to different nodes with the same group id will
be sent to the same node and the same consumer.</para>
</section>
<section id="examples.clustered.queue">
<title>Clustered Queue</title>
<para>The <literal>clustered-queue</literal> example demonstrates a JMS queue deployed
on two different nodes. The two nodes are configured to form a cluster. We then
create a consumer for the queue on each node, and we create a producer on only one
of the nodes. We then send some messages via the producer, and we verify that both
consumers receive the sent messages in a round-robin fashion.</para>
</section>
<section id="examples.clustered.jgroups">
<title>Clustering with JGroups</title>
<para>The <literal>clustered-jgroups</literal> example demonstrates how to form a two
node cluster using JGroups as its underlying topology discovery technique, rather than
the default UDP broadcasting. We then create a consumer for the queue on each node,
and we create a producer on only one of the nodes. We then send some messages via the
producer, and we verify that both consumers receive the sent messages in a round-robin fashion.</para>
</section>
<section id="examples.clustered.standalone">
<title>Clustered Standalone</title>
<para>The <literal>clustered-standalone</literal> example demonstrates how to configure
and starts 3 cluster nodes on the same machine to form a cluster. A subscriber for a
JMS topic is created on each node, and we create a producer on only one of the
nodes. We then send some messages via the producer, and we verify that the 3
subscribers receive all the sent messages.</para>
</section>
<section id="examples.clustered.static.discovery">
<title>Clustered Static Discovery</title>
<para>This example demonstrates how to configure a cluster using a list of connectors rather
than UDP for discovery</para>
</section>
<section id="examples.clustered.static.oneway">
<title>Clustered Static Cluster One Way</title>
<para>This example demonstrates how to set up a cluster where cluster connections are one way,
i.e. server A -> Server B -> Server C</para>
</section>
<section>
<title>Clustered Topic</title>
<para>The <literal>clustered-topic</literal> example demonstrates a JMS topic deployed
on two different nodes. The two nodes are configured to form a cluster. We then
create a subscriber on the topic on each node, and we create a producer on only one
of the nodes. We then send some messages via the producer, and we verify that both
subscribers receive all the sent messages.</para>
</section>
<section id="examples.consumer-rate-limit">
<title>Message Consumer Rate Limiting</title>
<para>With ActiveMQ you can specify a maximum consume rate at which a JMS MessageConsumer
will consume messages. This can be specified when creating or deploying the
connection factory.</para>
<para>If this value is specified then ActiveMQ will ensure that messages are never
consumed at a rate higher than the specified rate. This is a form of consumer
throttling.</para>
</section>
<section id="examples.dead-letter">
<title>Dead Letter</title>
<para>The <literal>dead-letter</literal> example shows you how to define and deal with
dead letter messages. Messages can be delivered unsuccessfully (e.g. if the
transacted session used to consume them is rolled back). </para>
<para>Such a message goes back to the JMS destination ready to be redelivered. However,
this means it is possible for a message to be delivered again and again without any
success and remain in the destination, clogging the system.</para>
<para>To prevent this, messaging systems define dead letter messages: after a specified
unsuccessful delivery attempts, the message is removed from the destination and put
instead in a dead letter destination where they can be consumed for further
investigation.</para>
</section>
<section id="examples.delayed-redelivery">
<title>Delayed Redelivery</title>
<para>The <literal>delayed-redelivery</literal> example demonstrates how ActiveMQ can be
configured to provide a delayed redelivery in the case a message needs to be
redelivered.</para>
<para>Delaying redelivery can often be useful in the case that clients regularly fail or
roll-back. Without a delayed redelivery, the system can get into a "thrashing"
state, with delivery being attempted, the client rolling back, and delivery being
re-attempted in quick succession, using up valuable CPU and network
resources.</para>
</section>
<section id="divert-example">
<title>Divert</title>
<para>ActiveMQ diverts allow messages to be transparently "diverted" or copied from one
address to another with just some simple configuration defined on the server
side.</para>
</section>
<section>
<title>Durable Subscription</title>
<para>The <literal>durable-subscription</literal> example shows you how to use a durable
subscription with ActiveMQ. Durable subscriptions are a standard part of JMS, please
consult the JMS 1.1 specification for full details.</para>
<para>Unlike non-durable subscriptions, the key function of durable subscriptions is
that the messages contained in them persist longer than the lifetime of the
subscriber - i.e. they will accumulate messages sent to the topic even if there is
no active subscriber on them. They will also survive server restarts or crashes.
Note that for the messages to be persisted, the messages sent to them must be marked
as durable messages. </para>
</section>
<section id="examples.embedded.jms">
<title>Embedded</title>
<para>The <literal>embedded</literal> example shows how to embed JMS
within your own code using POJO instantiation and no config files.</para>
</section>
<section id="examples.embedded.jms.simple">
<title>Embedded Simple</title>
<para>The <literal>embedded</literal> example shows how to embed JMS within your own code using regular ActiveMQ XML files.</para>
</section>
<section id="examples.expiry">
<title>Message Expiration</title>
<para>The <literal>expiry</literal> example shows you how to define and deal with
message expiration. Messages can be retained in the messaging system for a limited
period of time before being removed. JMS specification states that clients should
not receive messages that have been expired (but it does not guarantee this will not
happen).</para>
<para>ActiveMQ can assign an expiry address to a given queue so that when messages
are expired, they are removed from the queue and sent to the expiry address.
These "expired" messages can later be consumed from the expiry address for
further inspection.</para>
</section>
<section id="examples.activemq-ra-rar">
<title>ActiveMQ Resource Adapter example</title>
<para>This examples shows how to build the activemq resource adapters a rar for deployment in other Application
Server's</para>
</section>
<section>
<title>HTTP Transport</title>
<para>The <literal>http-transport</literal> example shows you how to configure ActiveMQ
to use the HTTP protocol as its transport layer.</para>
</section>
<section>
<title>Instantiate JMS Objects Directly</title>
<para>Usually, JMS Objects such as <literal>ConnectionFactory</literal>, <literal
>Queue</literal> and <literal>Topic</literal> instances are looked up from JNDI
before being used by the client code. This objects are called "administered objects"
in JMS terminology.</para>
<para>However, in some cases a JNDI server may not be available or desired. To come to
the rescue ActiveMQ also supports the direct instantiation of these administered
objects on the client side so you don't have to use JNDI for JMS.</para>
</section>
<section id="examples.interceptor">
<title>Interceptor</title>
<para>ActiveMQ allows an application to use an interceptor to hook into the messaging
system. Interceptors allow you to handle various message events in ActiveMQ.</para>
</section>
<section id="examples.jaas">
<title>JAAS</title>
<para>The <literal>jaas</literal> example shows you how to configure ActiveMQ to use JAAS
for security. ActiveMQ can leverage JAAS to delegate user authentication and
authorization to existing security infrastructure.</para>
</section>
<section id="examples.jms.auto-closeable">
<title>JMS Auto Closable</title>
<para>The <literal>jms-auto-closeable</literal> example shows how JMS resources, such
as connections, sessions and consumers, in JMS 2 can be automatically closed on error.</para>
</section>
<section id="examples.jms.completion-listener">
<title>JMS Completion Listener</title>
<para>The <literal>jms-completion-listener</literal> example shows how to send a message
asynchronously to ActiveMQ and use a CompletionListener to be notified of the Broker
receiving it.</para>
</section>
<section id="examples.jms.jms-bridge">
<title>JMS Bridge</title>
<para>The <literal>jms-brige</literal> example shows how to setup a bridge
between two standalone ActiveMQ servers.</para>
</section>
<section id="examples.jms.jms-context">
<title>JMS Context</title>
<para>The <literal>jms-context</literal> example shows how to send and receive a message
to a JMS Queue using ActiveMQ by using a JMS Context.</para>
<para>A JMSContext is part of JMS 2.0 and combines the JMS Connection and Session Objects
into a simple Interface.</para>
</section>
<section id="examples.jms.jms-shared-consumer">
<title>JMS Shared Consumer</title>
<para>The <literal>jms-shared-consumer</literal> example shows you how can use shared
consumers to share a subscription on a topic. In JMS 1.1 this was not allowed and so caused
a scalability issue. In JMS 2 this restriction has been lifted so you can share the load
across different threads and connections.</para>
</section>
<section id="examples.jmx">
<title>JMX Management</title>
<para>The <literal>jmx</literal> example shows how to manage ActiveMQ using JMX.</para>
</section>
<section id="examples.large-message">
<title>Large Message</title>
<para>The <literal>large-message</literal> example shows you how to send and receive
very large messages with ActiveMQ. ActiveMQ supports the sending and receiving of huge
messages, much larger than can fit in available RAM on the client or server.
Effectively the only limit to message size is the amount of disk space you have on
the server.</para>
<para>Large messages are persisted on the server so they can survive a server restart.
In other words ActiveMQ doesn't just do a simple socket stream from the sender to the
consumer.</para>
</section>
<section id="examples.last-value-queue">
<title>Last-Value Queue</title>
<para>The <literal>last-value-queue</literal> example shows you how to define and deal
with last-value queues. Last-value queues are special queues which discard any
messages when a newer message with the same value for a well-defined last-value
property is put in the queue. In other words, a last-value queue only retains the
last value.</para>
<para>A typical example for last-value queue is for stock prices, where you are only
interested by the latest price for a particular stock.</para>
</section>
<section id="examples.management">
<title>Management</title>
<para>The <literal>management</literal> example shows how to manage ActiveMQ using JMS
Messages to invoke management operations on the server.</para>
</section>
<section id="examples.management-notifications">
<title>Management Notification</title>
<para>The <literal>management-notification</literal> example shows how to receive
management notifications from ActiveMQ using JMS messages. ActiveMQ servers emit
management notifications when events of interest occur (consumers are created or
closed, addresses are created or deleted, security authentication fails,
etc.).</para>
</section>
<section id="examples.message-counters">
<title>Message Counter</title>
<para>The <literal>message-counters</literal> example shows you how to use message
counters to obtain message information for a JMS queue.</para>
</section>
<section id="examples.message-group">
<title>Message Group</title>
<para>The <literal>message-group</literal> example shows you how to configure and use
message groups with ActiveMQ. Message groups allow you to pin messages so they are
only consumed by a single consumer. Message groups are sets of messages that has the
following characteristics:</para>
<para>
<itemizedlist>
<listitem>
<para>Messages in a message group share the same group id, i.e. they have
same JMSXGroupID string property values</para>
</listitem>
<listitem>
<para>The consumer that receives the first message of a group will receive
all the messages that belongs to the group</para>
</listitem>
</itemizedlist>
</para>
</section>
<section id="examples.message-group2">
<title>Message Group</title>
<para>The <literal>message-group2</literal> example shows you how to configure and use
message groups with ActiveMQ via a connection factory.</para>
</section>
<section id="examples.message-priority">
<title>Message Priority</title>
<para>Message Priority can be used to influence the delivery order for messages.</para>
<para>It can be retrieved by the message's standard header field 'JMSPriority' as
defined in JMS specification version 1.1. </para>
<para>The value is of type integer, ranging from 0 (the lowest) to 9 (the highest). When
messages are being delivered, their priorities will effect their order of delivery.
Messages of higher priorities will likely be delivered before those of lower
priorities. </para>
<para>Messages of equal priorities are delivered in the natural order of their arrival
at their destinations. Please consult the JMS 1.1 specification for full
details.</para>
</section>
<section id="examples.multiple.failover">
<title>Multiple Failover</title>
<para>This example demonstrates how to set up a live server with multiple backups</para>
</section>
<section id="examples.multiple.failover.failback">
<title>Multiple Failover Failback</title>
<para>This example demonstrates how to set up a live server with multiple backups but
forcing failover back to the original live server</para>
</section>
<section id="examples.no-consumer-buffering">
<title>No Consumer Buffering</title>
<para>By default, ActiveMQ consumers buffer messages from the server in a client side
buffer before you actually receive them on the client side. This improves
performance since otherwise every time you called receive() or had processed the
last message in a <literal>MessageListener onMessage()</literal> method, the ActiveMQ
client would have to go the server to request the next message, which would then get
sent to the client side, if one was available.</para>
<para>This would involve a network round trip for every message and reduce performance.
Therefore, by default, ActiveMQ pre-fetches messages into a buffer on each
consumer.</para>
<para>In some case buffering is not desirable, and ActiveMQ allows it to be switched off.
This example demonstrates that.</para>
</section>
<section id="examples.non-transaction-failover">
<title>Non-Transaction Failover With Server Data Replication</title>
<para>The <literal>non-transaction-failover</literal> example demonstrates two servers coupled
as a live-backup pair for high availability (HA), and a client using a <emphasis>non-transacted
</emphasis> JMS session failing over from live to backup when the live server is
crashed.</para>
<para>ActiveMQ implements failover of client connections between
live and backup servers. This is implemented by the replication of state between
live and backup nodes. When replication is configured and a live node crashes, the
client connections can carry and continue to send and consume messages. When non-transacted
sessions are used, once and only once message delivery is not guaranteed and it is possible
that some messages will be lost or delivered twice.</para>
</section>
<section id="examples.openwire">
<title>OpenWire</title>
<para>The <literal>Openwire</literal> example shows how to configure a ActiveMQ
server to communicate with an ActiveMQ JMS client that uses open-wire protocol.</para>
</section>
<section id="examples.paging">
<title>Paging</title>
<para>The <literal>paging</literal> example shows how ActiveMQ can support huge queues
even when the server is running in limited RAM. It does this by transparently
<emphasis>paging</emphasis> messages to disk, and <emphasis>depaging</emphasis>
them when they are required.</para>
</section>
<section id="examples.pre-acknowledge">
<title>Pre-Acknowledge</title>
<para>Standard JMS supports three acknowledgement modes:<literal>
AUTO_ACKNOWLEDGE</literal>, <literal>CLIENT_ACKNOWLEDGE</literal>, and <literal
>DUPS_OK_ACKNOWLEDGE</literal>. For a full description on these modes please
consult the JMS specification, or any JMS tutorial.</para>
<para>All of these standard modes involve sending acknowledgements from the client to
the server. However in some cases, you really don't mind losing messages in event of
failure, so it would make sense to acknowledge the message on the server before
delivering it to the client. This example demonstrates how ActiveMQ allows this with
an extra acknowledgement mode.</para>
</section>
<section id="producer-rate-limiting-example">
<title>Message Producer Rate Limiting</title>
<para>The <literal>producer-rte-limit</literal> example demonstrates how, with ActiveMQ,
you can specify a maximum send rate at which a JMS message producer will send
messages.</para>
</section>
<section id="examples.proton-qpid">
<title>Proton Qpid</title>
<para>ActiveMQ can be configured to accept requests from any AMQP client that supports the
1.0 version of the protocol. This <literal>proton-j</literal> example shows a simply
qpid java 1.0 client example.</para>
</section>
<section id="examples.proton-ruby">
<title>Proton Ruby</title>
<para>ActiveMQ can be configured to accept requests from any AMQP client that supports the
1.0 version of the protocol. This example shows a simply proton ruby client
that sends and receives messages</para>
</section>
<section id="examples.queue">
<title>Queue</title>
<para>A simple example demonstrating a JMS queue.</para>
</section>
<section id="examples.message-redistribution">
<title>Message Redistribution</title>
<para>The <literal>queue-message-redistribution</literal> example demonstrates message
redistribution between queues with the same name deployed in different nodes of a
cluster.</para>
</section>
<section id="examples.queue-requestor">
<title>Queue Requestor</title>
<para>A simple example demonstrating a JMS queue requestor.</para>
</section>
<section id="examples.queue-message-selector">
<title>Queue with Message Selector</title>
<para>The <literal>queue-selector</literal> example shows you how to selectively consume
messages using message selectors with queue consumers.</para>
</section>
<section id="examples.reattach-node">
<title>Reattach Node example</title>
<para>The <literal>Reattach Node</literal> example shows how a client can try to reconnect to
the same server instead of failing the connection immediately and
notifying any user ExceptionListener objects. ActiveMQ can be configured to automatically
retry the connection, and reattach to the server when it becomes available again across
the network.</para>
</section>
<section id="examples.replicated-failback">
<title>Replicated Failback example</title>
<para>An example showing how failback works when using replication, In this example a live server will replicate
all its Journal to a backup server as it updates it. When the live server crashes the backup takes over
from the live server and the client reconnects and carries on from where it left off.</para>
</section>
<section id="examples.replicated-failback-static">
<title>Replicated Failback static example</title>
<para>An example showing how failback works when using replication, but this time with static connectors</para>
</section>
<section id="examples.replicated-multiple-failover">
<title>Replicated multiple failover example</title>
<para>An example showing how to configure multiple backups when using replication</para>
</section>
<section id="examples.replicated-failover-transaction">
<title>Replicated Failover transaction example</title>
<para>An example showing how failover works with a transaction when using replication</para>
</section>
<section id="examples.request-reply">
<title>Request-Reply example</title>
<para>A simple example showing the JMS request-response pattern.</para>
</section>
<section id="examples.rest">
<title>Rest example</title>
<para>An example showing how to use the ActiveMQ Rest API</para>
</section>
<section id="examples.scheduled-message">
<title>Scheduled Message</title>
<para>The <literal>scheduled-message</literal> example shows you how to send a scheduled
message to a JMS Queue with ActiveMQ. Scheduled messages won't get delivered until a
specified time in the future.</para>
</section>
<section id="examples.security">
<title>Security</title>
<para>The <literal>security</literal> example shows you how configure and use role based
queue security with ActiveMQ.</para>
</section>
<section id="asynchronous-send-acknowledgements-example">
<title>Send Acknowledgements</title>
<para>The <literal>send-acknowledgements</literal> example shows you how to use
ActiveMQ's advanced <emphasis>asynchronous send acknowledgements</emphasis> feature
to obtain acknowledgement from the server that sends have been received and
processed in a separate stream to the sent messages. </para>
</section>
<section id="examples.jms.spring.integration">
<title>Spring Integration</title>
<para>This example shows how to use embedded JMS using ActiveMQ's Spring integration.</para>
</section>
<section id="examples.ssl-transport">
<title>SSL Transport</title>
<para>The <literal>ssl-enabled</literal> shows you how to configure SSL with ActiveMQ to
send and receive message.</para>
</section>
<section id="examples.static-message-selector">
<title>Static Message Selector</title>
<para>The <literal>static-selector</literal> example shows you how to configure a
ActiveMQ core queue with static message selectors (filters).</para>
</section>
<section id="examples.static-message-selector-jms">
<title>Static Message Selector Using JMS</title>
<para>The <literal>static-selector-jms</literal> example shows you how to configure a
ActiveMQ queue with static message selectors (filters) using JMS.</para>
</section>
<section id="examples.stomp">
<title>Stomp</title>
<para>The <literal>stomp</literal> example shows you how to configure a
ActiveMQ server to send and receive Stomp messages.</para>
</section>
<section id="examples.stomp1.1">
<title>Stomp1.1</title>
<para>The <literal>stomp</literal> example shows you how to configure a
ActiveMQ server to send and receive Stomp messages via a Stomp 1.1 connection.</para>
</section>
<section id="examples.stomp1.2">
<title>Stomp1.2</title>
<para>The <literal>stomp</literal> example shows you how to configure a
ActiveMQ server to send and receive Stomp messages via a Stomp 1.2 connection.</para>
</section>
<section id="examples.stomp-web-socket">
<title>Stomp Over Web Sockets</title>
<para>The <literal>stomp-websockets</literal> example shows you how to configure a
ActiveMQ server to send and receive Stomp messages directly from Web browsers (provided
they support Web Sockets).</para>
</section>
<section id="examples.symmetric-cluster">
<title>Symmetric Cluster</title>
<para>The <literal>symmetric-cluster</literal> example demonstrates a symmetric cluster
set-up with ActiveMQ.</para>
<para>ActiveMQ has extremely flexible clustering which allows you to set-up servers in
many different topologies. The most common topology that you'll perhaps be familiar
with if you are used to application server clustering is a symmetric cluster.</para>
<para>With a symmetric cluster, the cluster is homogeneous, i.e. each node is configured
the same as every other node, and every node is connected to every other node in the
cluster.</para>
</section>
<section id="examples.temporary-queue">
<title>Temporary Queue</title>
<para>A simple example demonstrating how to use a JMS temporary queue.</para>
</section>
<section id="examples.topic">
<title>Topic</title>
<para>A simple example demonstrating a JMS topic.</para>
</section>
<section id="topic-hierarchy-example">
<title>Topic Hierarchy</title>
<para>ActiveMQ supports topic hierarchies. With a topic hierarchy you can register a
subscriber with a wild-card and that subscriber will receive any messages sent to an
address that matches the wild card.</para>
</section>
<section id="examples.topic-selector-1">
<title>Topic Selector 1</title>
<para>The <literal>topic-selector-example1</literal> example shows you how to send
message to a JMS Topic, and subscribe them using selectors with ActiveMQ.</para>
</section>
<section id="examples.topic-selector-2">
<title>Topic Selector 2</title>
<para>The <literal>topic-selector-example2</literal> example shows you how to
selectively consume messages using message selectors with topic consumers.</para>
</section>
<section id="examples.transaction-failover">
<title>Transaction Failover</title>
<para>The <literal>transaction-failover</literal> example demonstrates two servers coupled
as a live-backup pair for high availability (HA), and a client using a transacted JMS
session failing over from live to backup when the live server is
crashed.</para>
<para>ActiveMQ implements failover of client connections between
live and backup servers. This is implemented by the sharing of a journal between the
servers. When a live node crashes, the
client connections can carry and continue to send and consume messages. When transacted
sessions are used, once and only once message delivery is guaranteed.</para>
</section>
<section id="examples.no-transaction-failover">
<title>Failover Without Transactions</title>
<para>The <literal>stop-server-failover</literal> example demonstrates failover of the
JMS connection from one node to another when the live server crashes using a JMS
non-transacted session.</para>
</section>
<section id="examples.transactional-session">
<title>Transactional Session</title>
<para>The <literal>transactional</literal> example shows you how to use a transactional
Session with ActiveMQ.</para>
</section>
<section>
<title>XA Heuristic</title>
<para>The <literal>xa-heuristic</literal> example shows you how to make an XA heuristic
decision through ActiveMQ Management Interface. A heuristic decision is a unilateral
decision to commit or rollback an XA transaction branch after it has been
prepared.</para>
</section>
<section>
<title>XA Receive</title>
<para>The <literal>xa-receive</literal> example shows you how message receiving behaves
in an XA transaction in ActiveMQ.</para>
</section>
<section>
<title>XA Send</title>
<para>The <literal>xa-send</literal> example shows you how message sending behaves in an
XA transaction in ActiveMQ.</para>
</section>
<section>
<title>XA with Transaction Manager</title>
<para>The <literal>xa-with-jta</literal> example shows you how to use JTA interfaces to
control transactions with ActiveMQ.</para>
</section>
</section>
<section>
<title>Core API Examples</title>
<para>To run a core example, simply <literal>cd</literal> into the appropriate example
directory and type <literal>ant</literal></para>
<section id="examples.embedded">
<title>Embedded</title>
<para>The <literal>embedded</literal> example shows how to embed the ActiveMQ server
within your own code.</para>
</section>
</section>
<section>
<title>Java EE Examples</title>
<para>Most of the Java EE examples can be run the following way. Simply navigate into the
appropriate example directory and type <literal>mvn verify</literal>. This will use Arquillian to run the Application
Server and deploy the application. Note that you must have WildFly installed and the JBOSS_HOME environment
variable set. Please refer to the examples documentation for further instructions.</para>
<note>
<para>When running the Java EE examples you may see warning messages in the WildFly log about incompatible client and
server versions. This is normal if a newer version of the ActiveMQ project is being used with a version of WildFly that
ships an older version of ActiveMQ. These examples should still complete without any functional errors.</para>
</note>
<section>
<title>EJB/JMS Transaction</title>
<para>An example that shows using an EJB and JMS together within a transaction.</para>
</section>
<section>
<title>Resource Adapter Configuration</title>
<para>This example demonstrates how to configure several properties on the ActiveMQ JCA
resource adaptor.</para>
</section>
<section>
<title>Resource Adapter Remote Server Configuration</title>
<para>This example demonstrates how to configure the ActiveMQ resource adapter to talk to a remote ActiveMQ server</para>
</section>
<section id="examples.javaee.jms-bridge">
<title>JMS Bridge</title>
<para>An example demonstrating the use of the ActiveMQ JMS bridge.</para>
</section>
<section>
<title>MDB (Message Driven Bean)</title>
<para>A simple set of examples of message driven beans, including failover examples.</para>
</section>
<section>
<title>Servlet Transport</title>
<para>An example of how to use the ActiveMQ servlet transport.</para>
</section>
<section>
<title>Servlet SSL Transport</title>
<para>An example of how to use the ActiveMQ servlet transport over SSL.</para>
</section>
<section id="xa-recovery-example">
<title>XA Recovery</title>
<para>An example of how XA recovery works within the JBoss Application server using
ActiveMQ.</para>
</section>
</section>
</chapter>

View File

@ -0,0 +1,52 @@
Filter Expressions
==================
ActiveMQ provides a powerful filter language based on a subset of the
SQL 92 expression syntax.
It is the same as the syntax used for JMS selectors, but the predefined
identifiers are different. For documentation on JMS selector syntax
please the JMS javadoc for
[javax.jms.Message](http://docs.oracle.com/javaee/6/api/javax/jms/Message.html).
Filter expressions are used in several places in ActiveMQ
- Predefined Queues. When pre-defining a queue, either in
`activemq-configuration.xml` or `activemq-jms.xml` a filter
expression can be defined for a queue. Only messages that match the
filter expression will enter the queue.
- Core bridges can be defined with an optional filter expression, only
matching messages will be bridged (see ?).
- Diverts can be defined with an optional filter expression, only
matching messages will be diverted (see ?).
- Filter are also used programmatically when creating consumers,
queues and in several places as described in ?.
There are some differences between JMS selector expressions and ActiveMQ
core filter expressions. Whereas JMS selector expressions operate on a
JMS message, ActiveMQ core filter expressions operate on a core message.
The following identifiers can be used in a core filter expressions to
refer to attributes of the core message in an expression:
- `HQPriority`. To refer to the priority of a message. Message
priorities are integers with valid values from `0 - 9`. `0` is the
lowest priority and `9` is the highest. E.g.
`HQPriority = 3 AND animal = 'aardvark'`
- `HQExpiration`. To refer to the expiration time of a message. The
value is a long integer.
- `HQDurable`. To refer to whether a message is durable or not. The
value is a string with valid values: `DURABLE` or `NON_DURABLE`.
- `HQTimestamp`. The timestamp of when the message was created. The
value is a long integer.
- `HQSize`. The size of a message in bytes. The value is an integer.
Any other identifiers used in core filter expressions will be assumed to
be properties of the message.

View File

@ -1,86 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="filter-expressions">
<title>Filter Expressions</title>
<para>ActiveMQ provides a powerful filter language based on a subset of the SQL 92
expression syntax.</para>
<para>It is the same as the syntax used for JMS selectors, but the predefined identifiers are
different. For documentation on JMS selector syntax please the JMS javadoc for <ulink
url="http://docs.oracle.com/javaee/6/api/javax/jms/Message.html"
>javax.jms.Message</ulink>.</para>
<para>Filter expressions are used in several places in ActiveMQ</para>
<itemizedlist>
<listitem>
<para>Predefined Queues. When pre-defining a queue, either in <literal
>activemq-configuration.xml</literal> or <literal>activemq-jms.xml</literal> a filter
expression can be defined for a queue. Only messages that match the filter
expression will enter the queue.</para>
</listitem>
<listitem>
<para>Core bridges can be defined with an optional filter expression, only matching
messages will be bridged (see <xref linkend="core-bridges"/>).</para>
</listitem>
<listitem>
<para>Diverts can be defined with an optional filter expression, only matching messages
will be diverted (see <xref linkend="diverts" />).</para>
</listitem>
<listitem>
<para>Filter are also used programmatically when creating consumers, queues and in
several places as described in <xref linkend="management"/>.</para>
</listitem>
</itemizedlist>
<para>There are some differences between JMS selector expressions and ActiveMQ core
filter expressions. Whereas JMS selector expressions operate on a JMS message, ActiveMQ
core filter expressions operate on a core message.</para>
<para>The following identifiers can be used in a core filter expressions to refer to attributes
of the core message in an expression:</para>
<itemizedlist>
<listitem>
<para><literal>HQPriority</literal>. To refer to the priority of a message. Message
priorities are integers with valid values from <literal>0 - 9</literal>. <literal
>0</literal> is the lowest priority and <literal>9</literal> is the highest.
E.g. <literal>HQPriority = 3 AND animal = 'aardvark'</literal></para>
</listitem>
<listitem>
<para><literal>HQExpiration</literal>. To refer to the expiration time of a message.
The value is a long integer.</para>
</listitem>
<listitem>
<para><literal>HQDurable</literal>. To refer to whether a message is durable or not.
The value is a string with valid values: <literal>DURABLE</literal> or <literal
>NON_DURABLE</literal>.</para>
</listitem>
<listitem>
<para><literal>HQTimestamp</literal>. The timestamp of when the message was created.
The value is a long integer.</para>
</listitem>
<listitem>
<para><literal>HQSize</literal>. The size of a message in bytes. The value is an
integer.</para>
</listitem>
</itemizedlist>
<para>Any other identifiers used in core filter expressions will be assumed to be properties of
the message.</para>
</chapter>

View File

@ -0,0 +1,304 @@
Flow Control
============
Flow control is used to limit the flow of data between a client and
server, or a server and another server in order to prevent the client or
server being overwhelmed with data.
Consumer Flow Control
=====================
This controls the flow of data between the server and the client as the
client consumes messages. For performance reasons clients normally
buffer messages before delivering to the consumer via the `receive()`
method or asynchronously via a message listener. If the consumer cannot
process messages as fast as they are being delivered and stored in the
internal buffer, then you could end up with a situation where messages
would keep building up possibly causing out of memory on the client if
they cannot be processed in time.
Window-Based Flow Control
-------------------------
By default, ActiveMQ consumers buffer messages from the server in a
client side buffer before the client consumes them. This improves
performance: otherwise every time the client consumes a message,
ActiveMQ would have to go the server to request the next message. In
turn, this message would then get sent to the client side, if one was
available.
A network round trip would be involved for *every* message and
considerably reduce performance.
To prevent this, ActiveMQ pre-fetches messages into a buffer on each
consumer. The total maximum size of messages (in bytes) that will be
buffered on each consumer is determined by the `consumer-window-size`
parameter.
By default, the `consumer-window-size` is set to 1 MiB (1024 \* 1024
bytes).
The value can be:
- `-1` for an *unbounded* buffer
- `0` to not buffer any messages. See ? for working example of a
consumer with no buffering.
- `>0` for a buffer with the given maximum size in bytes.
Setting the consumer window size can considerably improve performance
depending on the messaging use case. As an example, let's consider the
two extremes:
Fast consumers
: Fast consumers can process messages as fast as they consume them (or
even faster)
To allow fast consumers, set the `consumer-window-size` to -1. This
will allow *unbounded* message buffering on the client side.
Use this setting with caution: it can overflow the client memory if
the consumer is not able to process messages as fast as it receives
them.
Slow consumers
: Slow consumers takes significant time to process each message and it
is desirable to prevent buffering messages on the client side so
that they can be delivered to another consumer instead.
Consider a situation where a queue has 2 consumers; 1 of which is
very slow. Messages are delivered in a round robin fashion to both
consumers, the fast consumer processes all of its messages very
quickly until its buffer is empty. At this point there are still
messages awaiting to be processed in the buffer of the slow consumer
thus preventing them being processed by the fast consumer. The fast
consumer is therefore sitting idle when it could be processing the
other messages.
To allow slow consumers, set the `consumer-window-size` to 0 (for no
buffer at all). This will prevent the slow consumer from buffering
any messages on the client side. Messages will remain on the server
side ready to be consumed by other consumers.
Setting this to 0 can give deterministic distribution between
multiple consumers on a queue.
Most of the consumers cannot be clearly identified as fast or slow
consumers but are in-between. In that case, setting the value of
`consumer-window-size` to optimize performance depends on the messaging
use case and requires benchmarks to find the optimal value, but a value
of 1MiB is fine in most cases.
### Using Core API
If ActiveMQ Core API is used, the consumer window size is specified by
`ServerLocator.setConsumerWindowSize()` method and some of the
`ClientSession.createConsumer()` methods.
### Using JMS
If JNDI is used on the client to instantiate and look up the connection
factory the consumer window size is configured in the JNDI context
environment, e.g. `jndi.properties`. Here's a simple example using the
"ConnectionFactory" connection factory which is available in the context
by default:
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:5445
connection.ConnectionFactory.consumerWindowSize=0
If the connection factory is directly instantiated, the consumer window
size is specified by `ActiveMQConnectionFactory.setConsumerWindowSize()`
method.
Please see ? for an example which shows how to configure ActiveMQ to
prevent consumer buffering when dealing with slow consumers.
Rate limited flow control
-------------------------
It is also possible to control the *rate* at which a consumer can
consume messages. This is a form of throttling and can be used to make
sure that a consumer never consumes messages at a rate faster than the
rate specified.
The rate must be a positive integer to enable this functionality and is
the maximum desired message consumption rate specified in units of
messages per second. Setting this to `-1` disables rate limited flow
control. The default value is `-1`.
Please see ? for a working example of limiting consumer rate.
### Using Core API
If the ActiveMQ core API is being used the rate can be set via the
`ServerLocator.setConsumerMaxRate(int consumerMaxRate)` method or
alternatively via some of the `ClientSession.createConsumer()` methods.
### Using JMS
If JNDI is used to instantiate and look up the connection factory, the
max rate can be configured in the JNDI context environment, e.g.
`jndi.properties`. Here's a simple example using the "ConnectionFactory"
connection factory which is available in the context by default:
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:5445
connection.ConnectionFactory.consumerMaxRate=10
If the connection factory is directly instantiated, the max rate size
can be set via the `ActiveMQConnectionFactory.setConsumerMaxRate(int
consumerMaxRate)` method.
> **Note**
>
> Rate limited flow control can be used in conjunction with window based
> flow control. Rate limited flow control only effects how many messages
> a client can consume in a second and not how many messages are in its
> buffer. So if you had a slow rate limit and a high window based limit
> the clients internal buffer would soon fill up with messages.
Please see ? for an example which shows how to configure ActiveMQ to
prevent consumer buffering when dealing with slow consumers.
Producer flow control
=====================
ActiveMQ also can limit the amount of data sent from a client to a
server to prevent the server being overwhelmed.
Window based flow control
-------------------------
In a similar way to consumer window based flow control, ActiveMQ
producers, by default, can only send messages to an address as long as
they have sufficient credits to do so. The amount of credits required to
send a message is given by the size of the message.
As producers run low on credits they request more from the server, when
the server sends them more credits they can send more messages.
The amount of credits a producer requests in one go is known as the
*window size*.
The window size therefore determines the amount of bytes that can be
in-flight at any one time before more need to be requested - this
prevents the remoting connection from getting overloaded.
### Using Core API
If the ActiveMQ core API is being used, window size can be set via the
`ServerLocator.setProducerWindowSize(int producerWindowSize)` method.
### Using JMS
If JNDI is used to instantiate and look up the connection factory, the
producer window size can be configured in the JNDI context environment,
e.g. `jndi.properties`. Here's a simple example using the
"ConnectionFactory" connection factory which is available in the context
by default:
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:5445
connection.ConnectionFactory.producerWindowSize=10
If the connection factory is directly instantiated, the producer window
size can be set via the
`ActiveMQConnectionFactory.setProducerWindowSize(int
producerWindowSize)` method.
### Blocking producer window based flow control
Normally the server will always give the same number of credits as have
been requested. However, it is also possible to set a maximum size on
any address, and the server will never send more credits than could
cause the address's upper memory limit to be exceeded.
For example, if I have a JMS queue called "myqueue", I could set the
maximum memory size to 10MiB, and the the server will control the number
of credits sent to any producers which are sending any messages to
myqueue such that the total messages in the queue never exceeds 10MiB.
When the address gets full, producers will block on the client side
until more space frees up on the address, i.e. until messages are
consumed from the queue thus freeing up space for more messages to be
sent.
We call this blocking producer flow control, and it's an efficient way
to prevent the server running out of memory due to producers sending
more messages than can be handled at any time.
It is an alternative approach to paging, which does not block producers
but instead pages messages to storage.
To configure an address with a maximum size and tell the server that you
want to block producers for this address if it becomes full, you need to
define an AddressSettings (?) block for the address and specify
`max-size-bytes` and `address-full-policy`
The address block applies to all queues registered to that address. I.e.
the total memory for all queues bound to that address will not exceed
`max-size-bytes`. In the case of JMS topics this means the *total*
memory of all subscriptions in the topic won't exceed max-size-bytes.
Here's an example:
<address-settings>
<address-setting match="jms.queue.exampleQueue">
<max-size-bytes>100000</max-size-bytes>
<address-full-policy>BLOCK</address-full-policy>
</address-setting>
</address-settings>
The above example would set the max size of the JMS queue "exampleQueue"
to be 100000 bytes and would block any producers sending to that address
to prevent that max size being exceeded.
Note the policy must be set to `BLOCK` to enable blocking producer flow
control.
> **Note**
>
> Note that in the default configuration all addresses are set to block
> producers after 10 MiB of message data is in the address. This means
> you cannot send more than 10MiB of message data to an address without
> it being consumed before the producers will be blocked. If you do not
> want this behaviour increase the `max-size-bytes` parameter or change
> the address full message policy.
Rate limited flow control
-------------------------
ActiveMQ also allows the rate a producer can emit message to be limited,
in units of messages per second. By specifying such a rate, ActiveMQ
will ensure that producer never produces messages at a rate higher than
that specified.
The rate must be a positive integer to enable this functionality and is
the maximum desired message consumption rate specified in units of
messages per second. Setting this to `-1` disables rate limited flow
control. The default value is `-1`.
Please see the ? for a working example of limiting producer rate.
### Using Core API
If the ActiveMQ core API is being used the rate can be set via the
`ServerLocator.setProducerMaxRate(int producerMaxRate)` method or
alternatively via some of the `ClientSession.createProducer()` methods.
### Using JMS
If JNDI is used to instantiate and look up the connection factory, the
max rate size can be configured in the JNDI context environment, e.g.
`jndi.properties`. Here's a simple example using the "ConnectionFactory"
connection factory which is available in the context by default:
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:5445
connection.ConnectionFactory.producerMaxRate=10
If the connection factory is directly instantiated, the max rate size
can be set via the `ActiveMQConnectionFactory.setProducerMaxRate(int
producerMaxRate)` method.

View File

@ -1,290 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="flow-control">
<title>Flow Control</title>
<para>Flow control is used to limit the flow of data between a client and server, or a server and
another server in order to prevent the client or server being overwhelmed with data.</para>
<section>
<title>Consumer Flow Control</title>
<para>This controls the flow of data between the server and the client as the client consumes
messages. For performance reasons clients normally buffer messages before delivering to the
consumer via the <literal>receive()</literal> method or asynchronously via a message
listener. If the consumer cannot process messages as fast as they are being delivered and
stored in the internal buffer, then you could end up with a situation where messages would
keep building up possibly causing out of memory on the client if they cannot be processed
in time.</para>
<section id="flow-control.consumer.window">
<title>Window-Based Flow Control</title>
<para>By default, ActiveMQ consumers buffer messages from the server in a client side buffer
before the client consumes them. This improves performance: otherwise every time the
client consumes a message, ActiveMQ would have to go the server to request the next
message. In turn, this message would then get sent to the client side, if one was
available.</para>
<para>A network round trip would be involved for <emphasis>every</emphasis> message and
considerably reduce performance.</para>
<para>To prevent this, ActiveMQ pre-fetches messages into a buffer on each consumer. The
total maximum size of messages (in bytes) that will be buffered on each consumer is
determined by the <literal>consumer-window-size</literal> parameter.</para>
<para>By default, the <literal>consumer-window-size</literal> is set to 1 MiB (1024 * 1024
bytes).</para>
<para>The value can be:</para>
<itemizedlist>
<listitem>
<para><literal>-1</literal> for an <emphasis>unbounded</emphasis> buffer</para>
</listitem>
<listitem>
<para><literal>0</literal> to not buffer any messages. See <xref
linkend="examples.no-consumer-buffering"/> for working example of a consumer
with no buffering.</para>
</listitem>
<listitem>
<para><literal>>0</literal> for a buffer with the given maximum size in
bytes.</para>
</listitem>
</itemizedlist>
<para>Setting the consumer window size can considerably improve performance depending on
the messaging use case. As an example, let's consider the two extremes: </para>
<variablelist>
<varlistentry>
<term>Fast consumers</term>
<listitem>
<para>Fast consumers can process messages as fast as they consume them (or even
faster)</para>
<para>To allow fast consumers, set the <literal>consumer-window-size</literal> to
-1. This will allow <emphasis>unbounded</emphasis> message buffering on the
client side.</para>
<para>Use this setting with caution: it can overflow the client memory if the
consumer is not able to process messages as fast as it receives them.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Slow consumers</term>
<listitem>
<para>Slow consumers takes significant time to process each message and it is
desirable to prevent buffering messages on the client side so that they can be
delivered to another consumer instead.</para>
<para>Consider a situation where a queue has 2 consumers; 1 of which is very slow.
Messages are delivered in a round robin fashion to both consumers, the fast
consumer processes all of its messages very quickly until its buffer is empty.
At this point there are still messages awaiting to be processed in the buffer
of the slow consumer thus preventing them being processed by the fast consumer.
The fast consumer is therefore sitting idle when it could be processing the
other messages. </para>
<para>To allow slow consumers, set the <literal>consumer-window-size</literal> to
0 (for no buffer at all). This will prevent the slow consumer from buffering
any messages on the client side. Messages will remain on the server side ready
to be consumed by other consumers.</para>
<para>Setting this to 0 can give deterministic distribution between multiple
consumers on a queue.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Most of the consumers cannot be clearly identified as fast or slow consumers but are
in-between. In that case, setting the value of <literal>consumer-window-size</literal>
to optimize performance depends on the messaging use case and requires benchmarks to
find the optimal value, but a value of 1MiB is fine in most cases.</para>
<section id="flow-control.core.api">
<title>Using Core API</title>
<para>If ActiveMQ Core API is used, the consumer window size is specified by <literal
>ServerLocator.setConsumerWindowSize()</literal> method and some of the
<literal>ClientSession.createConsumer()</literal> methods.</para>
</section>
<section>
<title>Using JMS</title>
<para>If JNDI is used on the client to instantiate and look up the connection factory the consumer window
size is configured in the JNDI context environment, e.g. <literal>jndi.properties</literal>. Here's a
simple example using the "ConnectionFactory" connection factory which is available in the context by
default:</para>
<programlisting>
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:5445
connection.ConnectionFactory.consumerWindowSize=0</programlisting>
<para>If the connection factory is directly instantiated, the consumer window size is
specified by <literal>ActiveMQConnectionFactory.setConsumerWindowSize()</literal>
method.</para>
<para>Please see <xref linkend="examples.no-consumer-buffering"/> for an example which
shows how to configure ActiveMQ to prevent consumer buffering when dealing with slow
consumers.</para>
</section>
</section>
<section>
<title>Rate limited flow control</title>
<para>It is also possible to control the <emphasis>rate</emphasis> at which a consumer can
consume messages. This is a form of throttling and can be used to make sure that a
consumer never consumes messages at a rate faster than the rate specified. </para>
<para>The rate must be a positive integer to enable this functionality and is the maximum
desired message consumption rate specified in units of messages per second. Setting this
to <literal>-1</literal> disables rate limited flow control. The default value is
<literal>-1</literal>.</para>
<para>Please see <xref linkend="examples.consumer-rate-limit"/> for a working example of
limiting consumer rate.</para>
<section id="flow-control.rate.core.api">
<title>Using Core API</title>
<para>If the ActiveMQ core API is being used the rate can be set via the <literal
>ServerLocator.setConsumerMaxRate(int consumerMaxRate)</literal> method or
alternatively via some of the <literal>ClientSession.createConsumer()</literal>
methods. </para>
</section>
<section>
<title>Using JMS</title>
<para>If JNDI is used to instantiate and look up the connection factory, the max rate can be configured in
the JNDI context environment, e.g. <literal>jndi.properties</literal>. Here's a simple example using the
"ConnectionFactory" connection factory which is available in the context by default:</para>
<programlisting>
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:5445
connection.ConnectionFactory.consumerMaxRate=10</programlisting>
<para>If the connection factory is directly instantiated, the max rate size can be set
via the <literal>ActiveMQConnectionFactory.setConsumerMaxRate(int
consumerMaxRate)</literal> method.</para>
<note>
<para>Rate limited flow control can be used in conjunction with window based flow
control. Rate limited flow control only effects how many messages a client can
consume in a second and not how many messages are in its buffer. So if you had a
slow rate limit and a high window based limit the clients internal buffer would
soon fill up with messages.</para>
</note>
<para>Please see <xref linkend="examples.consumer-rate-limit"/> for an example which
shows how to configure ActiveMQ to prevent consumer buffering when dealing with slow
consumers.</para>
</section>
</section>
</section>
<section>
<title>Producer flow control</title>
<para>ActiveMQ also can limit the amount of data sent from a client to a server to prevent the
server being overwhelmed.</para>
<section>
<title>Window based flow control</title>
<para>In a similar way to consumer window based flow control, ActiveMQ producers, by
default, can only send messages to an address as long as they have sufficient credits to
do so. The amount of credits required to send a message is given by the size of the
message.</para>
<para>As producers run low on credits they request more from the server, when the server
sends them more credits they can send more messages.</para>
<para>The amount of credits a producer requests in one go is known as the <emphasis
role="italic">window size</emphasis>.</para>
<para>The window size therefore determines the amount of bytes that can be in-flight at any
one time before more need to be requested - this prevents the remoting connection from
getting overloaded.</para>
<section>
<title>Using Core API</title>
<para>If the ActiveMQ core API is being used, window size can be set via the <literal
>ServerLocator.setProducerWindowSize(int producerWindowSize)</literal>
method.</para>
</section>
<section>
<title>Using JMS</title>
<para>If JNDI is used to instantiate and look up the connection factory, the producer window size can be
configured in the JNDI context environment, e.g. <literal>jndi.properties</literal>. Here's a simple
example using the "ConnectionFactory" connection factory which is available in the context by default:</para>
<programlisting>
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:5445
connection.ConnectionFactory.producerWindowSize=10</programlisting>
<para>If the connection factory is directly instantiated, the producer window size can
be set via the <literal>ActiveMQConnectionFactory.setProducerWindowSize(int
producerWindowSize)</literal> method.</para>
</section>
<section>
<title>Blocking producer window based flow control</title>
<para>Normally the server will always give the same number of credits as have been
requested. However, it is also possible to set a maximum size on any address, and the
server will never send more credits than could cause the address's upper memory limit
to be exceeded.</para>
<para>For example, if I have a JMS queue called "myqueue", I could set the maximum
memory size to 10MiB, and the the server will control the number of credits sent to
any producers which are sending any messages to myqueue such that the total messages
in the queue never exceeds 10MiB.</para>
<para>When the address gets full, producers will block on the client side until more
space frees up on the address, i.e. until messages are consumed from the queue thus
freeing up space for more messages to be sent.</para>
<para>We call this blocking producer flow control, and it's an efficient way to prevent
the server running out of memory due to producers sending more messages than can be
handled at any time.</para>
<para>It is an alternative approach to paging, which does not block producers but
instead pages messages to storage.</para>
<para>To configure an address with a maximum size and tell the server that you want to
block producers for this address if it becomes full, you need to define an
AddressSettings (<xref linkend="queue-attributes.address-settings"/>) block for the
address and specify <literal>max-size-bytes</literal> and <literal
>address-full-policy</literal></para>
<para>The address block applies to all queues registered to that address. I.e. the total
memory for all queues bound to that address will not exceed <literal
>max-size-bytes</literal>. In the case of JMS topics this means the <emphasis
role="italic">total</emphasis> memory of all subscriptions in the topic won't
exceed max-size-bytes.</para>
<para>Here's an example:</para>
<programlisting>
&lt;address-settings>
&lt;address-setting match="jms.queue.exampleQueue">
&lt;max-size-bytes>100000&lt;/max-size-bytes>
&lt;address-full-policy>BLOCK&lt;/address-full-policy>
&lt;/address-setting>
&lt;/address-settings></programlisting>
<para>The above example would set the max size of the JMS queue "exampleQueue" to be
100000 bytes and would block any producers sending to that address to prevent that
max size being exceeded.</para>
<para>Note the policy must be set to <literal>BLOCK</literal> to enable blocking producer
flow control.</para>
<note><para>Note that in the default configuration all addresses are set to block producers after 10 MiB of message data
is in the address. This means you cannot send more than 10MiB of message data to an address without it being consumed before the producers
will be blocked. If you do not want this behaviour increase the <literal>max-size-bytes</literal> parameter or change the
address full message policy.</para>
</note>
</section>
</section>
<section>
<title>Rate limited flow control</title>
<para>ActiveMQ also allows the rate a producer can emit message to be limited, in units of
messages per second. By specifying such a rate, ActiveMQ will ensure that producer never
produces messages at a rate higher than that specified.</para>
<para>The rate must be a positive integer to enable this functionality and is the maximum
desired message consumption rate specified in units of messages per second. Setting this
to <literal>-1</literal> disables rate limited flow control. The default value is
<literal>-1</literal>.</para>
<para>Please see the <xref linkend="producer-rate-limiting-example"/> for a working example
of limiting producer rate.</para>
<section id="flow-control.producer.rate.core.api">
<title>Using Core API</title>
<para>If the ActiveMQ core API is being used the rate can be set via the <literal
>ServerLocator.setProducerMaxRate(int producerMaxRate)</literal> method or
alternatively via some of the <literal>ClientSession.createProducer()</literal>
methods. </para>
</section>
<section>
<title>Using JMS</title>
<para>If JNDI is used to instantiate and look up the connection factory, the max rate size can be
configured in the JNDI context environment, e.g. <literal>jndi.properties</literal>. Here's a simple
example using the "ConnectionFactory" connection factory which is available in the context by default:</para>
<programlisting>
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:5445
connection.ConnectionFactory.producerMaxRate=10</programlisting>
<para>If the connection factory is directly instantiated, the max rate size can be set
via the <literal>ActiveMQConnectionFactory.setProducerMaxRate(int
producerMaxRate)</literal> method.</para>
</section>
</section>
</section>
</chapter>

892
docs/user-manual/en/ha.md Normal file
View File

@ -0,0 +1,892 @@
High Availability and Failover
==============================
We define high availability as the *ability for the system to continue
functioning after failure of one or more of the servers*.
A part of high availability is *failover* which we define as the
*ability for client connections to migrate from one server to another in
event of server failure so client applications can continue to operate*.
Live - Backup Groups
====================
ActiveMQ allows servers to be linked together as *live - backup* groups
where each live server can have 1 or more backup servers. A backup
server is owned by only one live server. Backup servers are not
operational until failover occurs, however 1 chosen backup, which will
be in passive mode, announces its status and waits to take over the live
servers work
Before failover, only the live server is serving the ActiveMQ clients
while the backup servers remain passive or awaiting to become a backup
server. When a live server crashes or is brought down in the correct
mode, the backup server currently in passive mode will become live and
another backup server will become passive. If a live server restarts
after a failover then it will have priority and be the next server to
become live when the current live server goes down, if the current live
server is configured to allow automatic failback then it will detect the
live server coming back up and automatically stop.
HA Policies
-----------
ActiveMQ supports two different strategies for backing up a server
*shared store* and *replication*. Which is configured via the
`ha-policy` configuration element.
<ha-policy>
<replication/>
</ha-policy>
or
<ha-policy>
<shared-store/>
</ha-policy>
As well as these 2 strategies there is also a 3rd called `live-only`.
This of course means there will be no Backup Strategy and is the default
if none is provided, however this is used to configure `scale-down`
which we will cover in a later chapter.
> **Note**
>
> The `ha-policy` configurations replaces any current HA configuration
> in the root of the `activemq-configuration.xml` configuration. All old
> configuration is now deprecated altho best efforts will be made to
> honour it if configured this way.
> **Note**
>
> Only persistent message data will survive failover. Any non persistent
> message data will not be available after failover.
The `ha-policy` type configures which strategy a cluster should use to
provide the backing up of a servers data. Within this configuration
element is configured how a server should behave within the cluster,
either as a master (live), slave (backup) or colocated (both live and
backup). This would look something like:
<ha-policy>
<replication>
<master/>
</replication>
</ha-policy>
or
<ha-policy>
<shared-store/>
<slave/>
</shared-store/>
</ha-policy>
or
<ha-policy>
<replication>
<colocated/>
</replication>
</ha-policy>
Data Replication
----------------
Support for network-based data replication was added in version 2.3.
When using replication, the live and the backup servers do not share the
same data directories, all data synchronization is done over the
network. Therefore all (persistent) data received by the live server
will be duplicated to the backup.
c
Notice that upon start-up the backup server will first need to
synchronize all existing data from the live server before becoming
capable of replacing the live server should it fail. So unlike when
using shared storage, a replicating backup will not be a fully
operational backup right after start-up, but only after it finishes
synchronizing the data with its live server. The time it will take for
this to happen will depend on the amount of data to be synchronized and
the connection speed.
> **Note**
>
> Synchronization occurs in parallel with current network traffic so
> this won't cause any blocking on current clients.
Replication will create a copy of the data at the backup. One issue to
be aware of is: in case of a successful fail-over, the backup's data
will be newer than the one at the live's storage. If you configure your
live server to perform a ? when restarted, it will synchronize its data
with the backup's. If both servers are shutdown, the administrator will
have to determine which one has the latest data.
The replicating live and backup pair must be part of a cluster. The
Cluster Connection also defines how backup servers will find the remote
live servers to pair with. Refer to ? for details on how this is done,
and how to configure a cluster connection. Notice that:
- Both live and backup servers must be part of the same cluster.
Notice that even a simple live/backup replicating pair will require
a cluster configuration.
- Their cluster user and password must match.
Within a cluster, there are two ways that a backup server will locate a
live server to replicate from, these are:
- `specifying a node group`. You can specify a group of live servers
that a backup server can connect to. This is done by configuring
`group-name` in either the `master` or the `slave` element of the
`activemq-configuration.xml`. A Backup server will only connect to a
live server that shares the same node group name
- `connecting to any live`. This will be the behaviour if `group-name`
is not configured allowing a backup server to connect to any live
server
> **Note**
>
> A `group-name` example: suppose you have 5 live servers and 6 backup
> servers:
>
> - `live1`, `live2`, `live3`: with `group-name=fish`
>
> - `live4`, `live5`: with `group-name=bird`
>
> - `backup1`, `backup2`, `backup3`, `backup4`: with `group-name=fish`
>
> - `backup5`, `backup6`: with `group-name=bird`
>
> After joining the cluster the backups with `group-name=fish` will
> search for live servers with `group-name=fish` to pair with. Since
> there is one backup too many, the `fish` will remain with one spare
> backup.
>
> The 2 backups with `group-name=bird` (`backup5` and `backup6`) will
> pair with live servers `live4` and `live5`.
The backup will search for any live server that it is configured to
connect to. It then tries to replicate with each live server in turn
until it finds a live server that has no current backup configured. If
no live server is available it will wait until the cluster topology
changes and repeats the process.
> **Note**
>
> This is an important distinction from a shared-store backup, if a
> backup starts and does not find a live server, the server will just
> activate and start to serve client requests. In the replication case,
> the backup just keeps waiting for a live server to pair with. Note
> that in replication the backup server does not know whether any data
> it might have is up to date, so it really cannot decide to activate
> automatically. To activate a replicating backup server using the data
> it has, the administrator must change its configuration to make it a
> live server by changing `slave` to `master`.
Much like in the shared-store case, when the live server stops or
crashes, its replicating backup will become active and take over its
duties. Specifically, the backup will become active when it loses
connection to its live server. This can be problematic because this can
also happen because of a temporary network problem. In order to address
this issue, the backup will try to determine whether it still can
connect to the other servers in the cluster. If it can connect to more
than half the servers, it will become active, if more than half the
servers also disappeared with the live, the backup will wait and try
reconnecting with the live. This avoids a split brain situation.
### Configuration
To configure the live and backup servers to be a replicating pair,
configure the live server in ' `activemq-configuration.xml` to have:
<ha-policy>
<replication>
<master/>
</replication>
</ha-policy>
.
<cluster-connections>
<cluster-connection name="my-cluster">
...
</cluster-connection>
</cluster-connections>
The backup server must be similarly configured but as a `slave`
<ha-policy>
<replication>
<slave/>
</replication>
</ha-policy>
### All Replication Configuration
The following table lists all the `ha-policy` configuration elements for
HA strategy Replication for `master`:
name Description
------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`check-for-live-server` Whether to check the cluster for a (live) server using our own server ID when starting up. This option is only necessary for performing 'fail-back' on replicating servers.
`cluster-name` Name of the cluster configuration to use for replication. This setting is only necessary if you configure multiple cluster connections. If configured then the connector configuration of the cluster configuration with this name will be used when connecting to the cluster to discover if a live server is already running, see `check-for-live-server`. If unset then the default cluster connections configuration is used (the first one configured)
`group-name` If set, backup servers will only pair with live servers with matching group-name
The following table lists all the `ha-policy` configuration elements for
HA strategy Replication for `slave`:
name Description
-------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`cluster-name` Name of the cluster configuration to use for replication. This setting is only necessary if you configure multiple cluster connections. If configured then the connector configuration of the cluster configuration with this name will be used when connecting to the cluster to discover if a live server is already running, see `check-for-live-server`. If unset then the default cluster connections configuration is used (the first one configured)
`group-name` If set, backup servers will only pair with live servers with matching group-name
`max-saved-replicated-journals-size` This specifies how many times a replicated backup server can restart after moving its files on start. Once there are this number of backup journal files the server will stop permanently after if fails back.
`allow-failback` Whether a server will automatically stop when a another places a request to take over its place. The use case is when the backup has failed over
`failback-delay` delay to wait before fail-back occurs on (failed over live's) restart
Shared Store
------------
When using a shared store, both live and backup servers share the *same*
entire data directory using a shared file system. This means the paging
directory, journal directory, large messages and binding journal.
When failover occurs and a backup server takes over, it will load the
persistent storage from the shared file system and clients can connect
to it.
This style of high availability differs from data replication in that it
requires a shared file system which is accessible by both the live and
backup nodes. Typically this will be some kind of high performance
Storage Area Network (SAN). We do not recommend you use Network Attached
Storage (NAS), e.g. NFS mounts to store any shared journal (NFS is
slow).
The advantage of shared-store high availability is that no replication
occurs between the live and backup nodes, this means it does not suffer
any performance penalties due to the overhead of replication during
normal operation.
The disadvantage of shared store replication is that it requires a
shared file system, and when the backup server activates it needs to
load the journal from the shared store which can take some time
depending on the amount of data in the store.
If you require the highest performance during normal operation, have
access to a fast SAN and live with a slightly slower failover (depending
on amount of data).
![ActiveMQ ha-shared-store.png](images/ha-shared-store.png)
### Configuration
To configure the live and backup servers to share their store, configure
id via the `ha-policy` configuration in `activemq-configuration.xml`:
<ha-policy>
<shared-store>
<master/>
</shared-store>
</ha-policy>
.
<cluster-connections>
<cluster-connection name="my-cluster">
...
</cluster-connection>
</cluster-connections>
The backup server must also be configured as a backup.
<ha-policy>
<shared-store>
<slave/>
</shared-store>
</ha-policy>
In order for live - backup groups to operate properly with a shared
store, both servers must have configured the location of journal
directory to point to the *same shared location* (as explained in ?)
> **Note**
>
> todo write something about GFS
Also each node, live and backups, will need to have a cluster connection
defined even if not part of a cluster. The Cluster Connection info
defines how backup servers announce there presence to its live server or
any other nodes in the cluster. Refer to ? for details on how this is
done.
Failing Back to live Server
---------------------------
After a live server has failed and a backup taken has taken over its
duties, you may want to restart the live server and have clients fail
back.
In case of "shared disk", simply restart the original live server and
kill the new live server by can do this by killing the process itself.
Alternatively you can set `allow-fail-back` to `true` on the slave
config which will force the backup that has become live to automatically
stop. This configuration would look like:
<ha-policy>
<shared-store>
<slave>
<allow-failback>true</allow-failback>
<failback-delay>5000</failback-delay>
</slave>
</shared-store>
</ha-policy>
The `failback-delay` configures how long the backup must wait after
automatically stopping before it restarts. This is to gives the live
server time to start and obtain its lock.
In replication HA mode you need to set an extra property
`check-for-live-server` to `true` in the `master` configuration. If set
to true, during start-up a live server will first search the cluster for
another server using its nodeID. If it finds one, it will contact this
server and try to "fail-back". Since this is a remote replication
scenario, the "starting live" will have to synchronize its data with the
server running with its ID, once they are in sync, it will request the
other server (which it assumes it is a back that has assumed its duties)
to shutdown for it to take over. This is necessary because otherwise the
live server has no means to know whether there was a fail-over or not,
and if there was if the server that took its duties is still running or
not. To configure this option at your `activemq-configuration.xml`
configuration file as follows:
<ha-policy>
<replication>
<master>
<check-for-live-server>true</check-for-live-server>
<master>
</replication>
</ha-policy>
> **Warning**
>
> Be aware that if you restart a live server while after failover has
> occurred then this value must be set to ``. If not the live server
> will restart and server the same messages that the backup has already
> handled causing duplicates.
It is also possible, in the case of shared store, to cause failover to
occur on normal server shutdown, to enable this set the following
property to true in the `ha-policy` configuration on either the `master`
or `slave` like so:
<ha-policy>
<shared-store>
<master>
<failover-on-shutdown>true</failover-on-shutdown>
</master>
</shared-store>
</ha-policy>
By default this is set to false, if by some chance you have set this to
false but still want to stop the server normally and cause failover then
you can do this by using the management API as explained at ?
You can also force the running live server to shutdown when the old live
server comes back up allowing the original live server to take over
automatically by setting the following property in the
`activemq-configuration.xml` configuration file as follows:
<ha-policy>
<shared-store>
<slave>
<allow-failback>true</allow-failback>
</slave>
</shared-store>
</ha-policy>
### All Shared Store Configuration
The following table lists all the `ha-policy` configuration elements for
HA strategy shared store for `master`:
name Description
------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`failback-delay` If a backup server is detected as being live, via the lock file, then the live server will wait announce itself as a backup and wait this amount of time (in ms) before starting as a live
`failover-on-server-shutdown` If set to true then when this server is stopped normally the backup will become live assuming failover. If false then the backup server will remain passive. Note that if false you want failover to occur the you can use the the management API as explained at ?
The following table lists all the `ha-policy` configuration elements for
HA strategy Shared Store for `slave`:
name Description
------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`failover-on-server-shutdown` In the case of a backup that has become live. then when set to true then when this server is stopped normally the backup will become liveassuming failover. If false then the backup server will remain passive. Note that if false you want failover to occur the you can use the the management API as explained at ?
`allow-failback` Whether a server will automatically stop when a another places a request to take over its place. The use case is when the backup has failed over.
`failback-delay` After failover and the slave has become live, this is set on the new live server. When starting If a backup server is detected as being live, via the lock file, then the live server will wait announce itself as a backup and wait this amount of time (in ms) before starting as a live, however this is unlikely since this backup has just stopped anyway. It is also used as the delay after failback before this backup will restart (if `allow-failback` is set to true.
Colocated Backup Servers
------------------------
It is also possible when running standalone to colocate backup servers
in the same JVM as another live server. Live Servers can be configured
to request another live server in the cluster to start a backup server
in the same JVM either using shared store or replication. The new backup
server will inherit its configuration from the live server creating it
apart from its name, which will be set to `colocated_backup_n` where n
is the number of backups the server has created, and any directories and
its Connectors and Acceptors which are discussed later on in this
chapter. A live server can also be configured to allow requests from
backups and also how many backups a live server can start. this way you
can evenly distribute backups around the cluster. This is configured via
the `ha-policy` element in the `activemq-configuration.xml` file like
so:
<ha-policy>
<replication>
<colocated>
<request-backup>true</request-backup>
<max-backups>1</max-backups>
<backup-request-retries>-1</backup-request-retries>
<backup-request-retry-interval>5000</backup-request-retry-interval>
<master/>
<slave/>
</colocated>
<replication>
</ha-policy>
the above example is configured to use replication, in this case the
`master` and `slave` configurations must match those for normal
replication as in the previous chapter. `shared-store` is also supported
![ActiveMQ ha-colocated.png](images/ha-colocated.png)
### Configuring Connectors and Acceptors
If the HA Policy is colocated then connectors and acceptors will be
inherited from the live server creating it and offset depending on the
setting of `backup-port-offset` configuration element. If this is set to
say 100 (which is the default) and a connector is using port 5445 then
this will be set to 5545 for the first server created, 5645 for the
second and so on.
> **Note**
>
> for INVM connectors and Acceptors the id will have
> `colocated_backup_n` appended, where n is the backup server number.
#### Remote Connectors
It may be that some of the Connectors configured are for external
servers and hence should be excluded from the offset. for instance a
Connector used by the cluster connection to do quorum voting for a
replicated backup server, these can be omitted from being offset by
adding them to the `ha-policy` configuration like so:
<ha-policy>
<replication>
<colocated>
<excludes>
<connector-ref>remote-connector</connector-ref>
</excludes>
.........
</ha-policy>
### Configuring Directories
Directories for the Journal, Large messages and Paging will be set
according to what the HA strategy is. If shared store the the requesting
server will notify the target server of which directories to use. If
replication is configured then directories will be inherited from the
creating server but have the new backups name appended.
The following table lists all the `ha-policy` configuration elements:
name Description
--------------------------------- ---------------------------------------------------------------------------------------
`request-backup` If true then the server will request a backup on another node
`backup-request-retries` How many times the live server will try to request a backup, -1 means for ever.
`backup-request-retry-interval` How long to wait for retries between attempts to request a backup server.
`max-backups` Whether or not this live server will accept backup requests from other live servers.
`backup-port-offset` The offset to use for the Connectors and Acceptors when creating a new backup server.
Scaling Down
============
An alternative to using Live/Backup groups is to configure scaledown.
when configured for scale down a server can copy all its messages and
transaction state to another live server. The advantage of this is that
you dont need full backups to provide some form of HA, however there are
disadvantages with this approach the first being that it only deals with
a server being stopped and not a server crash. The caveat here is if you
configure a backup to scale down.
Another disadvantage is that it is possible to lose message ordering.
This happens in the following scenario, say you have 2 live servers and
messages are distributed evenly between the servers from a single
producer, if one of the servers scales down then the messages sent back
to the other server will be in the queue after the ones already there,
so server 1 could have messages 1,3,5,7,9 and server 2 would have
2,4,6,8,10, if server 2 scales down the order in server 1 would be
1,3,5,7,9,2,4,6,8,10.
![ActiveMQ ha-scaledown.png](images/ha-scaledown.png)
The configuration for a live server to scale down would be something
like:
<ha-policy>
<live-only>
<scale-down>
<connectors>
<connector-ref>server1-connector</connector-ref>
</connectors>
</scale-down>
</live-only>
</ha-policy>
In this instance the server is configured to use a specific connector to
scale down, if a connector is not specified then the first INVM
connector is chosen, this is to make scale down fromm a backup server
easy to configure. It is also possible to use discovery to scale down,
this would look like:
<ha-policy>
<live-only>
<scale-down>
<discovery-group>my-discovery-group</discovery-group>
</scale-down>
</live-only>
</ha-policy>
Scale Down with groups
----------------------
It is also possible to configure servers to only scale down to servers
that belong in the same group. This is done by configuring the group
like so:
<ha-policy>
<live-only>
<scale-down>
...
<group-name>my-group</group-name>
</scale-down>
</live-only>
</ha-policy>
In this scenario only servers that belong to the group `my-group` will
be scaled down to
Scale Down and Backups
----------------------
It is also possible to mix scale down with HA via backup servers. If a
slave is configured to scale down then after failover has occurred,
instead of starting fully the backup server will immediately scale down
to another live server. The most appropriate configuration for this is
using the `colocated` approach. it means as you bring up live server
they will automatically be backed up by server and as live servers are
shutdown, there messages are made available on another live server. A
typical configuration would look like:
<ha-policy>
<replication>
<colocated>
<backup-request-retries>44</backup-request-retries>
<backup-request-retry-interval>33</backup-request-retry-interval>
<max-backups>3</max-backups>
<request-backup>false</request-backup>
<backup-port-offset>33</backup-port-offset>
<master>
<group-name>purple</group-name>
<check-for-live-server>true</check-for-live-server>
<cluster-name>abcdefg</cluster-name>
</master>
<slave>
<group-name>tiddles</group-name>
<max-saved-replicated-journals-size>22</max-saved-replicated-journals-size>
<cluster-name>33rrrrr</cluster-name>
<restart-backup>false</restart-backup>
<scale-down>
<!--a grouping of servers that can be scaled down to-->
<group-name>boo!</group-name>
<!--either a discovery group-->
<discovery-group>wahey</discovery-group>
</scale-down>
</slave>
</colocated>
</replication>
</ha-policy>
Scale Down and Clients
----------------------
When a server is stopping and preparing to scale down it will send a
message to all its clients informing them which server it is scaling
down to before disconnecting them. At this point the client will
reconnect however this will only succeed once the server has completed
scaledown. This is to ensure that any state such as queues or
transactions are there for the client when it reconnects. The normal
reconnect settings apply when the client is reconnecting so these should
be high enough to deal with the time needed to scale down.
Failover Modes
==============
ActiveMQ defines two types of client failover:
- Automatic client failover
- Application-level client failover
ActiveMQ also provides 100% transparent automatic reattachment of
connections to the same server (e.g. in case of transient network
problems). This is similar to failover, except it is reconnecting to the
same server and is discussed in ?
During failover, if the client has consumers on any non persistent or
temporary queues, those queues will be automatically recreated during
failover on the backup node, since the backup node will not have any
knowledge of non persistent queues.
Automatic Client Failover
-------------------------
ActiveMQ clients can be configured to receive knowledge of all live and
backup servers, so that in event of connection failure at the client -
live server connection, the client will detect this and reconnect to the
backup server. The backup server will then automatically recreate any
sessions and consumers that existed on each connection before failover,
thus saving the user from having to hand-code manual reconnection logic.
ActiveMQ clients detect connection failure when it has not received
packets from the server within the time given by
`client-failure-check-period` as explained in section ?. If the client
does not receive data in good time, it will assume the connection has
failed and attempt failover. Also if the socket is closed by the OS,
usually if the server process is killed rather than the machine itself
crashing, then the client will failover straight away.
ActiveMQ clients can be configured to discover the list of live-backup
server groups in a number of different ways. They can be configured
explicitly or probably the most common way of doing this is to use
*server discovery* for the client to automatically discover the list.
For full details on how to configure server discovery, please see ?.
Alternatively, the clients can explicitly connect to a specific server
and download the current servers and backups see ?.
To enable automatic client failover, the client must be configured to
allow non-zero reconnection attempts (as explained in ?).
By default failover will only occur after at least one connection has
been made to the live server. In other words, by default, failover will
not occur if the client fails to make an initial connection to the live
server - in this case it will simply retry connecting to the live server
according to the reconnect-attempts property and fail after this number
of attempts.
### Failing over on the Initial Connection
Since the client does not learn about the full topology until after the
first connection is made there is a window where it does not know about
the backup. If a failure happens at this point the client can only try
reconnecting to the original live server. To configure how many attempts
the client will make you can set the property `initialConnectAttempts`
on the `ClientSessionFactoryImpl` or `ActiveMQConnectionFactory` or
`initial-connect-attempts` in xml. The default for this is `0`, that is
try only once. Once the number of attempts has been made an exception
will be thrown.
For examples of automatic failover with transacted and non-transacted
JMS sessions, please see ? and ?.
### A Note on Server Replication
ActiveMQ does not replicate full server state between live and backup
servers. When the new session is automatically recreated on the backup
it won't have any knowledge of messages already sent or acknowledged in
that session. Any in-flight sends or acknowledgements at the time of
failover might also be lost.
By replicating full server state, theoretically we could provide a 100%
transparent seamless failover, which would avoid any lost messages or
acknowledgements, however this comes at a great cost: replicating the
full server state (including the queues, session, etc.). This would
require replication of the entire server state machine; every operation
on the live server would have to replicated on the replica server(s) in
the exact same global order to ensure a consistent replica state. This
is extremely hard to do in a performant and scalable way, especially
when one considers that multiple threads are changing the live server
state concurrently.
It is possible to provide full state machine replication using
techniques such as *virtual synchrony*, but this does not scale well and
effectively serializes all operations to a single thread, dramatically
reducing concurrency.
Other techniques for multi-threaded active replication exist such as
replicating lock states or replicating thread scheduling but this is
very hard to achieve at a Java level.
Consequently it has decided it was not worth massively reducing
performance and concurrency for the sake of 100% transparent failover.
Even without 100% transparent failover, it is simple to guarantee *once
and only once* delivery, even in the case of failure, by using a
combination of duplicate detection and retrying of transactions. However
this is not 100% transparent to the client code.
### Handling Blocking Calls During Failover
If the client code is in a blocking call to the server, waiting for a
response to continue its execution, when failover occurs, the new
session will not have any knowledge of the call that was in progress.
This call might otherwise hang for ever, waiting for a response that
will never come.
To prevent this, ActiveMQ will unblock any blocking calls that were in
progress at the time of failover by making them throw a
`javax.jms.JMSException` (if using JMS), or a `ActiveMQException` with
error code `ActiveMQException.UNBLOCKED`. It is up to the client code to
catch this exception and retry any operations if desired.
If the method being unblocked is a call to commit(), or prepare(), then
the transaction will be automatically rolled back and ActiveMQ will
throw a `javax.jms.TransactionRolledBackException` (if using JMS), or a
`ActiveMQException` with error code
`ActiveMQException.TRANSACTION_ROLLED_BACK` if using the core API.
### Handling Failover With Transactions
If the session is transactional and messages have already been sent or
acknowledged in the current transaction, then the server cannot be sure
that messages sent or acknowledgements have not been lost during the
failover.
Consequently the transaction will be marked as rollback-only, and any
subsequent attempt to commit it will throw a
`javax.jms.TransactionRolledBackException` (if using JMS), or a
`ActiveMQException` with error code
`ActiveMQException.TRANSACTION_ROLLED_BACK` if using the core API.
> **Warning**
>
> The caveat to this rule is when XA is used either via JMS or through
> the core API. If 2 phase commit is used and prepare has already been
> called then rolling back could cause a `HeuristicMixedException`.
> Because of this the commit will throw a `XAException.XA_RETRY`
> exception. This informs the Transaction Manager that it should retry
> the commit at some later point in time, a side effect of this is that
> any non persistent messages will be lost. To avoid this use persistent
> messages when using XA. With acknowledgements this is not an issue
> since they are flushed to the server before prepare gets called.
It is up to the user to catch the exception, and perform any client side
local rollback code as necessary. There is no need to manually rollback
the session - it is already rolled back. The user can then just retry
the transactional operations again on the same session.
ActiveMQ ships with a fully functioning example demonstrating how to do
this, please see ?
If failover occurs when a commit call is being executed, the server, as
previously described, will unblock the call to prevent a hang, since no
response will come back. In this case it is not easy for the client to
determine whether the transaction commit was actually processed on the
live server before failure occurred.
> **Note**
>
> If XA is being used either via JMS or through the core API then an
> `XAException.XA_RETRY` is thrown. This is to inform Transaction
> Managers that a retry should occur at some point. At some later point
> in time the Transaction Manager will retry the commit. If the original
> commit has not occurred then it will still exist and be committed, if
> it does not exist then it is assumed to have been committed although
> the transaction manager may log a warning.
To remedy this, the client can simply enable duplicate detection (?) in
the transaction, and retry the transaction operations again after the
call is unblocked. If the transaction had indeed been committed on the
live server successfully before failover, then when the transaction is
retried, duplicate detection will ensure that any durable messages
resent in the transaction will be ignored on the server to prevent them
getting sent more than once.
> **Note**
>
> By catching the rollback exceptions and retrying, catching unblocked
> calls and enabling duplicate detection, once and only once delivery
> guarantees for messages can be provided in the case of failure,
> guaranteeing 100% no loss or duplication of messages.
### Handling Failover With Non Transactional Sessions
If the session is non transactional, messages or acknowledgements can be
lost in the event of failover.
If you wish to provide *once and only once* delivery guarantees for non
transacted sessions too, enabled duplicate detection, and catch unblock
exceptions as described in ?
Getting Notified of Connection Failure
--------------------------------------
JMS provides a standard mechanism for getting notified asynchronously of
connection failure: `java.jms.ExceptionListener`. Please consult the JMS
javadoc or any good JMS tutorial for more information on how to use
this.
The ActiveMQ core API also provides a similar feature in the form of the
class `org.apache.activemq.core.client.SessionFailureListener`
Any ExceptionListener or SessionFailureListener instance will always be
called by ActiveMQ on event of connection failure, **irrespective** of
whether the connection was successfully failed over, reconnected or
reattached, however you can find out if reconnect or reattach has
happened by either the `failedOver` flag passed in on the
`connectionFailed` on `SessionfailureListener` or by inspecting the
error code on the `javax.jms.JMSException` which will be one of the
following:
error code Description
------------ ---------------------------------------------------------------------------
FAILOVER Failover has occurred and we have successfully reattached or reconnected.
DISCONNECT No failover has occurred and we are disconnected.
: JMSException error codes
Application-Level Failover
--------------------------
In some cases you may not want automatic client failover, and prefer to
handle any connection failure yourself, and code your own manually
reconnection logic in your own failure handler. We define this as
*application-level* failover, since the failover is handled at the user
application level.
To implement application-level failover, if you're using JMS then you
need to set an `ExceptionListener` class on the JMS connection. The
`ExceptionListener` will be called by ActiveMQ in the event that
connection failure is detected. In your `ExceptionListener`, you would
close your old JMS connections, potentially look up new connection
factory instances from JNDI and creating new connections. In this case
you may well be using
[HA-JNDI](http://www.jboss.org/community/wiki/JBossHAJNDIImpl) to ensure
that the new connection factory is looked up from a different server.
For a working example of application-level failover, please see ?.
If you are using the core API, then the procedure is very similar: you
would set a `FailureListener` on the core `ClientSession` instances.

View File

@ -1,985 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="ha">
<title>High Availability and Failover</title>
<para>We define high availability as the <emphasis>ability for the system to continue
functioning after failure of one or more of the servers</emphasis>.</para>
<para>A part of high availability is <emphasis>failover</emphasis> which we define as the
<emphasis>ability for client connections to migrate from one server to another in event of
server failure so client applications can continue to operate</emphasis>.</para>
<section>
<title>Live - Backup Groups</title>
<para>ActiveMQ allows servers to be linked together as <emphasis>live - backup</emphasis>
groups where each live server can have 1 or more backup servers. A backup server is owned by
only one live server. Backup servers are not operational until failover occurs, however 1
chosen backup, which will be in passive mode, announces its status and waits to take over
the live servers work</para>
<para>Before failover, only the live server is serving the ActiveMQ clients while the backup
servers remain passive or awaiting to become a backup server. When a live server crashes or
is brought down in the correct mode, the backup server currently in passive mode will become
live and another backup server will become passive. If a live server restarts after a
failover then it will have priority and be the next server to become live when the current
live server goes down, if the current live server is configured to allow automatic failback
then it will detect the live server coming back up and automatically stop.</para>
<section id="ha.policies">
<title>HA Policies</title>
<para>ActiveMQ supports two different strategies for backing up a server <emphasis>shared
store</emphasis> and <emphasis>replication</emphasis>. Which is configured via the
<literal>ha-policy</literal> configuration element.</para>
<programlisting>
&lt;ha-policy>
&lt;replication/>
&lt;/ha-policy>
</programlisting>
<para>
or
</para>
<programlisting>
&lt;ha-policy>
&lt;shared-store/>
&lt;/ha-policy>
</programlisting>
<para>
As well as these 2 strategies there is also a 3rd called <literal>live-only</literal>. This of course means there
will be no Backup Strategy and is the default if none is provided, however this is used to configure
<literal>scale-down</literal> which we will cover in a later chapter.
</para>
<note>
<para>
The <literal>ha-policy</literal> configurations replaces any current HA configuration in the root of the
<literal>activemq-configuration.xml</literal> configuration. All old configuration is now deprecated altho
best efforts will be made to honour it if configured this way.
</para>
</note>
<note>
<para>Only persistent message data will survive failover. Any non persistent message
data will not be available after failover.</para>
</note>
<para>The <literal>ha-policy</literal> type configures which strategy a cluster should use to provide the
backing up of a servers data. Within this configuration element is configured how a server should behave
within the cluster, either as a master (live), slave (backup) or colocated (both live and backup). This
would look something like: </para>
<programlisting>
&lt;ha-policy>
&lt;replication>
&lt;master/>
&lt;/replication>
&lt;/ha-policy>
</programlisting>
<para>
or
</para>
<programlisting>
&lt;ha-policy>
&lt;shared-store/>
&lt;slave/>
&lt;/shared-store/>
&lt;/ha-policy>
</programlisting>
<para>
or
</para>
<programlisting>
&lt;ha-policy>
&lt;replication>
&lt;colocated/>
&lt;/replication>
&lt;/ha-policy>
</programlisting>
</section>
<section id="ha.mode.replicated">
<title>Data Replication</title>
<para>Support for network-based data replication was added in version 2.3.</para>
<para>When using replication, the live and the backup servers do not share the same
data directories, all data synchronization is done over the network. Therefore all (persistent)
data received by the live server will be duplicated to the backup.</para>
<graphic fileref="images/ha-replicated-store.png" align="center"/>
<para>Notice that upon start-up the backup server will first need to synchronize all
existing data from the live server before becoming capable of replacing the live
server should it fail. So unlike when using shared storage, a replicating backup will
not be a fully operational backup right after start-up, but only after it finishes
synchronizing the data with its live server. The time it will take for this to happen
will depend on the amount of data to be synchronized and the connection speed.</para>
<note>
<para>Synchronization occurs in parallel with current network traffic so this won't cause any
blocking on current clients.</para>
</note>
<para>Replication will create a copy of the data at the backup. One issue to be aware
of is: in case of a successful fail-over, the backup's data will be newer than
the one at the live's storage. If you configure your live server to perform a
<xref linkend="ha.allow-fail-back">'fail-back'</xref> when restarted, it will synchronize
its data with the backup's. If both servers are shutdown, the administrator will have
to determine which one has the latest data.</para>
<para>The replicating live and backup pair must be part of a cluster. The Cluster
Connection also defines how backup servers will find the remote live servers to pair
with. Refer to <xref linkend="clusters"/> for details on how this is done, and how
to configure a cluster connection. Notice that:</para>
<itemizedlist>
<listitem>
<para>Both live and backup servers must be part of the same cluster. Notice
that even a simple live/backup replicating pair will require a cluster configuration.</para>
</listitem>
<listitem>
<para>Their cluster user and password must match.</para>
</listitem>
</itemizedlist>
<para>Within a cluster, there are two ways that a backup server will locate a live server to replicate
from, these are:</para>
<itemizedlist>
<listitem>
<para><literal>specifying a node group</literal>. You can specify a group of live servers that a backup
server can connect to. This is done by configuring <literal>group-name</literal> in either the <literal>master</literal>
or the <literal>slave</literal> element of the
<literal>activemq-configuration.xml</literal>. A Backup server will only connect to a live server that
shares the same node group name</para>
</listitem>
<listitem>
<para><literal>connecting to any live</literal>. This will be the behaviour if <literal>group-name</literal>
is not configured allowing a backup server to connect to any live server</para>
</listitem>
</itemizedlist>
<note>
<para>A <literal>group-name</literal> example: suppose you have 5 live servers and 6 backup
servers:</para>
<itemizedlist>
<listitem>
<para><literal>live1</literal>, <literal>live2</literal>, <literal>live3</literal>: with
<literal>group-name=fish</literal></para>
</listitem>
<listitem>
<para><literal>live4</literal>, <literal>live5</literal>: with <literal>group-name=bird</literal></para>
</listitem>
<listitem>
<para><literal>backup1</literal>, <literal>backup2</literal>, <literal>backup3</literal>,
<literal>backup4</literal>: with <literal>group-name=fish</literal></para>
</listitem>
<listitem>
<para><literal>backup5</literal>, <literal>backup6</literal>: with
<literal>group-name=bird</literal></para>
</listitem>
</itemizedlist>
<para>After joining the cluster the backups with <literal>group-name=fish</literal> will
search for live servers with <literal>group-name=fish</literal> to pair with. Since there
is one backup too many, the <literal>fish</literal> will remain with one spare backup.</para>
<para>The 2 backups with <literal>group-name=bird</literal> (<literal>backup5</literal> and
<literal>backup6</literal>) will pair with live servers <literal>live4</literal> and
<literal>live5</literal>.</para>
</note>
<para>The backup will search for any live server that it is configured to connect to. It then tries to
replicate with each live server in turn until it finds a live server that has no current backup
configured. If no live server is available it will wait until the cluster topology changes and
repeats the process.</para>
<note>
<para>This is an important distinction from a shared-store backup, if a backup starts and does not find
a live server, the server will just activate and start to serve client requests.
In the replication case, the backup just keeps
waiting for a live server to pair with. Note that in replication the backup server
does not know whether any data it might have is up to date, so it really cannot
decide to activate automatically. To activate a replicating backup server using the data
it has, the administrator must change its configuration to make it a live server by changing
<literal>slave</literal> to <literal>master</literal>.</para>
</note>
<para>Much like in the shared-store case, when the live server stops or crashes,
its replicating backup will become active and take over its duties. Specifically,
the backup will become active when it loses connection to its live server. This can
be problematic because this can also happen because of a temporary network
problem. In order to address this issue, the backup will try to determine whether it
still can connect to the other servers in the cluster. If it can connect to more
than half the servers, it will become active, if more than half the servers also
disappeared with the live, the backup will wait and try reconnecting with the live.
This avoids a split brain situation.</para>
<section>
<title>Configuration</title>
<para>To configure the live and backup servers to be a replicating pair, configure
the live server in ' <literal>activemq-configuration.xml</literal> to have:</para>
<programlisting>
&lt;ha-policy>
&lt;replication>
&lt;master/>
&lt;/replication>
&lt;/ha-policy>
.
&lt;cluster-connections>
&lt;cluster-connection name="my-cluster">
...
&lt;/cluster-connection>
&lt;/cluster-connections>
</programlisting>
<para>The backup server must be similarly configured but as a <literal>slave</literal></para>
<programlisting>
&lt;ha-policy>
&lt;replication>
&lt;slave/>
&lt;/replication>
&lt;/ha-policy></programlisting>
</section>
<section>
<title>All Replication Configuration</title>
<para>The following table lists all the <literal>ha-policy</literal> configuration elements for HA strategy
Replication for <literal>master</literal>:</para>
<table>
<tgroup cols="2">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<thead>
<row>
<entry>name</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>check-for-live-server</literal></entry>
<entry>Whether to check the cluster for a (live) server using our own server ID when starting
up. This option is only necessary for performing 'fail-back' on replicating servers.</entry>
</row>
<row>
<entry><literal>cluster-name</literal></entry>
<entry>Name of the cluster configuration to use for replication. This setting is only necessary if you
configure multiple cluster connections. If configured then the connector configuration of the
cluster configuration with this name will be used when connecting to the cluster to discover
if a live server is already running, see <literal>check-for-live-server</literal>. If unset then
the default cluster connections configuration is used (the first one configured)</entry>
</row>
<row>
<entry><literal>group-name</literal></entry>
<entry>If set, backup servers will only pair with live servers with matching group-name</entry>
</row>
</tbody>
</tgroup>
</table>
<para>The following table lists all the <literal>ha-policy</literal> configuration elements for HA strategy
Replication for <literal>slave</literal>:</para>
<table>
<tgroup cols="2">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<thead>
<row>
<entry>name</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>cluster-name</literal></entry>
<entry>Name of the cluster configuration to use for replication. This setting is only necessary if you
configure multiple cluster connections. If configured then the connector configuration of the
cluster configuration with this name will be used when connecting to the cluster to discover
if a live server is already running, see <literal>check-for-live-server</literal>. If unset then
the default cluster connections configuration is used (the first one configured)</entry>
</row>
<row>
<entry><literal>group-name</literal></entry>
<entry>If set, backup servers will only pair with live servers with matching group-name</entry>
</row>
<row>
<entry><literal>max-saved-replicated-journals-size</literal></entry>
<entry>This specifies how many times a replicated backup server can restart after moving its files on start.
Once there are this number of backup journal files the server will stop permanently after if fails
back.</entry>
</row>
<row>
<entry><literal>allow-failback</literal></entry>
<entry>Whether a server will automatically stop when a another places a request to take over
its place. The use case is when the backup has failed over </entry>
</row>
<row>
<entry><literal>failback-delay</literal></entry>
<entry>delay to wait before fail-back occurs on (failed over live's) restart</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="ha.mode.shared">
<title>Shared Store</title>
<para>When using a shared store, both live and backup servers share the
<emphasis>same</emphasis> entire data directory using a shared file system.
This means the paging directory, journal directory, large messages and binding
journal.</para>
<para>When failover occurs and a backup server takes over, it will load the
persistent storage from the shared file system and clients can connect to
it.</para>
<para>This style of high availability differs from data replication in that it
requires a shared file system which is accessible by both the live and backup
nodes. Typically this will be some kind of high performance Storage Area Network
(SAN). We do not recommend you use Network Attached Storage (NAS), e.g. NFS
mounts to store any shared journal (NFS is slow).</para>
<para>The advantage of shared-store high availability is that no replication occurs
between the live and backup nodes, this means it does not suffer any performance
penalties due to the overhead of replication during normal operation.</para>
<para>The disadvantage of shared store replication is that it requires a shared file
system, and when the backup server activates it needs to load the journal from
the shared store which can take some time depending on the amount of data in the
store.</para>
<para>If you require the highest performance during normal operation, have access to
a fast SAN and live with a slightly slower failover (depending on amount of
data).</para>
<graphic fileref="images/ha-shared-store.png" align="center"/>
<section id="ha/mode.shared.configuration">
<title>Configuration</title>
<para>To configure the live and backup servers to share their store, configure
id via the <literal>ha-policy</literal> configuration in <literal>activemq-configuration.xml</literal>:</para>
<programlisting>
&lt;ha-policy>
&lt;shared-store>
&lt;master/>
&lt;/shared-store>
&lt;/ha-policy>
.
&lt;cluster-connections>
&lt;cluster-connection name="my-cluster">
...
&lt;/cluster-connection>
&lt;/cluster-connections>
</programlisting>
<para>The backup server must also be configured as a backup.</para>
<programlisting>
&lt;ha-policy>
&lt;shared-store>
&lt;slave/>
&lt;/shared-store>
&lt;/ha-policy>
</programlisting>
<para>In order for live - backup groups to operate properly with a shared store,
both servers must have configured the location of journal directory to point
to the <emphasis>same shared location</emphasis> (as explained in
<xref linkend="configuring.message.journal"/>)</para>
<note>
<para>todo write something about GFS</para>
</note>
<para>Also each node, live and backups, will need to have a cluster connection defined even if not
part of a cluster. The Cluster Connection info defines how backup servers announce there presence
to its live server or any other nodes in the cluster. Refer to <xref linkend="clusters"/> for details
on how this is done.</para>
</section>
</section>
<section id="ha.allow-fail-back">
<title>Failing Back to live Server</title>
<para>After a live server has failed and a backup taken has taken over its duties, you may want to
restart the live server and have clients fail back.</para>
<para>In case of "shared disk", simply restart the original live server and kill the new live server by can
do this by killing the process itself. Alternatively you can set <literal>allow-fail-back</literal> to
<literal>true</literal> on the slave config which will force the backup that has become live to automatically
stop. This configuration would look like:</para>
<programlisting>
&lt;ha-policy>
&lt;shared-store>
&lt;slave>
&lt;allow-failback>true&lt;/allow-failback>
&lt;failback-delay>5000&lt;/failback-delay>
&lt;/slave>
&lt;/shared-store>
&lt;/ha-policy>
</programlisting>
<para>The <literal>failback-delay</literal> configures how long the backup must wait after automatically
stopping before it restarts. This is to gives the live server time to start and obtain its lock.</para>
<para id="hq.check-for-live-server">In replication HA mode you need to set an extra property <literal>check-for-live-server</literal>
to <literal>true</literal> in the <literal>master</literal> configuration. If set to true, during start-up
a live server will first search the cluster for another server using its nodeID. If it finds one, it will
contact this server and try to "fail-back". Since this is a remote replication scenario, the "starting live"
will have to synchronize its data with the server running with its ID, once they are in sync, it will
request the other server (which it assumes it is a back that has assumed its duties) to shutdown for it to
take over. This is necessary because otherwise the live server has no means to know whether there was a
fail-over or not, and if there was if the server that took its duties is still running or not.
To configure this option at your <literal>activemq-configuration.xml</literal> configuration file as follows:</para>
<programlisting>
&lt;ha-policy>
&lt;replication>
&lt;master>
&lt;check-for-live-server>true&lt;/check-for-live-server>
&lt;master>
&lt;/replication>
&lt;/ha-policy></programlisting>
<warning>
<para>
Be aware that if you restart a live server while after failover has occurred then this value must be
set to <literal><emphasis role="bold">true</emphasis></literal>. If not the live server will restart and server the same
messages that the backup has already handled causing duplicates.
</para>
</warning>
<para>It is also possible, in the case of shared store, to cause failover to occur on normal server shutdown,
to enable this set the following property to true in the <literal>ha-policy</literal> configuration on either
the <literal>master</literal> or <literal>slave</literal> like so:</para>
<programlisting>
&lt;ha-policy>
&lt;shared-store>
&lt;master>
&lt;failover-on-shutdown>true&lt;/failover-on-shutdown>
&lt;/master>
&lt;/shared-store>
&lt;/ha-policy></programlisting>
<para>By default this is set to false, if by some chance you have set this to false but still
want to stop the server normally and cause failover then you can do this by using the management
API as explained at <xref linkend="management.core.server"/></para>
<para>You can also force the running live server to shutdown when the old live server comes back up allowing
the original live server to take over automatically by setting the following property in the
<literal>activemq-configuration.xml</literal> configuration file as follows:</para>
<programlisting>
&lt;ha-policy>
&lt;shared-store>
&lt;slave>
&lt;allow-failback>true&lt;/allow-failback>
&lt;/slave>
&lt;/shared-store>
&lt;/ha-policy></programlisting>
<section>
<title>All Shared Store Configuration</title>
<para>The following table lists all the <literal>ha-policy</literal> configuration elements for HA strategy
shared store for <literal>master</literal>:</para>
<table>
<tgroup cols="2">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<thead>
<row>
<entry>name</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>failback-delay</literal></entry>
<entry>If a backup server is detected as being live, via the lock file, then the live server
will wait announce itself as a backup and wait this amount of time (in ms) before starting as
a live</entry>
</row>
<row>
<entry><literal>failover-on-server-shutdown</literal></entry>
<entry>If set to true then when this server is stopped normally the backup will become live
assuming failover. If false then the backup server will remain passive. Note that if false you
want failover to occur the you can use the the management API as explained at <xref linkend="management.core.server"/></entry>
</row>
</tbody>
</tgroup>
</table>
<para>The following table lists all the <literal>ha-policy</literal> configuration elements for HA strategy
Shared Store for <literal>slave</literal>:</para>
<table>
<tgroup cols="2">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<thead>
<row>
<entry>name</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>failover-on-server-shutdown</literal></entry>
<entry>In the case of a backup that has become live. then when set to true then when this server
is stopped normally the backup will become liveassuming failover. If false then the backup
server will remain passive. Note that if false you want failover to occur the you can use
the the management API as explained at <xref linkend="management.core.server"/></entry>
</row>
<row>
<entry><literal>allow-failback</literal></entry>
<entry>Whether a server will automatically stop when a another places a request to take over
its place. The use case is when the backup has failed over.</entry>
</row>
<row>
<entry><literal>failback-delay</literal></entry>
<entry>After failover and the slave has become live, this is set on the new live server.
When starting If a backup server is detected as being live, via the lock file, then the live server
will wait announce itself as a backup and wait this amount of time (in ms) before starting as
a live, however this is unlikely since this backup has just stopped anyway. It is also used
as the delay after failback before this backup will restart (if <literal>allow-failback</literal>
is set to true.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="ha.colocated">
<title>Colocated Backup Servers</title>
<para>It is also possible when running standalone to colocate backup servers in the same
JVM as another live server. Live Servers can be configured to request another live server in the cluster
to start a backup server in the same JVM either using shared store or replication. The new backup server
will inherit its configuration from the live server creating it apart from its name, which will be set to
<literal>colocated_backup_n</literal> where n is the number of backups the server has created, and any directories
and its Connectors and Acceptors which are discussed later on in this chapter. A live server can also
be configured to allow requests from backups and also how many backups a live server can start. this way
you can evenly distribute backups around the cluster. This is configured via the <literal>ha-policy</literal>
element in the <literal>activemq-configuration.xml</literal> file like so:</para>
<programlisting>
&lt;ha-policy>
&lt;replication>
&lt;colocated>
&lt;request-backup>true&lt;/request-backup>
&lt;max-backups>1&lt;/max-backups>
&lt;backup-request-retries>-1&lt;/backup-request-retries>
&lt;backup-request-retry-interval>5000&lt;/backup-request-retry-interval>
&lt;master/>
&lt;slave/>
&lt;/colocated>
&lt;replication>
&lt;/ha-policy>
</programlisting>
<para>the above example is configured to use replication, in this case the <literal>master</literal> and
<literal>slave</literal> configurations must match those for normal replication as in the previous chapter.
<literal>shared-store</literal> is also supported</para>
<graphic fileref="images/ha-colocated.png" align="center"/>
<section id="ha.colocated.connectorsandacceptors">
<title>Configuring Connectors and Acceptors</title>
<para>If the HA Policy is colocated then connectors and acceptors will be inherited from the live server
creating it and offset depending on the setting of <literal>backup-port-offset</literal> configuration element.
If this is set to say 100 (which is the default) and a connector is using port 5445 then this will be
set to 5545 for the first server created, 5645 for the second and so on.</para>
<note><para>for INVM connectors and Acceptors the id will have <literal>colocated_backup_n</literal> appended,
where n is the backup server number.</para></note>
<section id="ha.colocated.connectorsandacceptors.remote">
<title>Remote Connectors</title>
<para>It may be that some of the Connectors configured are for external servers and hence should be excluded from the offset.
for instance a Connector used by the cluster connection to do quorum voting for a replicated backup server,
these can be omitted from being offset by adding them to the <literal>ha-policy</literal> configuration like so:</para>
<programlisting>
&lt;ha-policy>
&lt;replication>
&lt;colocated>
&lt;excludes>
&lt;connector-ref>remote-connector&lt;/connector-ref>
&lt;/excludes>
.........
&lt;/ha-policy>
</programlisting>
</section>
</section>
<section id="ha.colocated.directories">
<title>Configuring Directories</title>
<para>Directories for the Journal, Large messages and Paging will be set according to what the HA strategy is.
If shared store the the requesting server will notify the target server of which directories to use. If replication
is configured then directories will be inherited from the creating server but have the new backups name
appended.</para>
</section>
<para>The following table lists all the <literal>ha-policy</literal> configuration elements:</para>
<table>
<tgroup cols="2">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<thead>
<row>
<entry>name</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>request-backup</literal></entry>
<entry>If true then the server will request a backup on another node</entry>
</row>
<row>
<entry><literal>backup-request-retries</literal></entry>
<entry>How many times the live server will try to request a backup, -1 means for ever.</entry>
</row>
<row>
<entry><literal>backup-request-retry-interval</literal></entry>
<entry>How long to wait for retries between attempts to request a backup server.</entry>
</row>
<row>
<entry><literal>max-backups</literal></entry>
<entry>Whether or not this live server will accept backup requests from other live servers.</entry>
</row>
<row>
<entry><literal>backup-port-offset</literal></entry>
<entry>The offset to use for the Connectors and Acceptors when creating a new backup server.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="ha.scaledown">
<title>Scaling Down</title>
<para>An alternative to using Live/Backup groups is to configure scaledown. when configured for scale down a server
can copy all its messages and transaction state to another live server. The advantage of this is that you dont need
full backups to provide some form of HA, however there are disadvantages with this approach the first being that it
only deals with a server being stopped and not a server crash. The caveat here is if you configure a backup to scale down. </para>
<para>Another disadvantage is that it is possible to lose message ordering. This happens in the following scenario,
say you have 2 live servers and messages are distributed evenly between the servers from a single producer, if one
of the servers scales down then the messages sent back to the other server will be in the queue after the ones
already there, so server 1 could have messages 1,3,5,7,9 and server 2 would have 2,4,6,8,10, if server 2 scales
down the order in server 1 would be 1,3,5,7,9,2,4,6,8,10.</para>
<graphic fileref="images/ha-scaledown.png" align="center"/>
<para>The configuration for a live server to scale down would be something like:</para>
<programlisting>
&lt;ha-policy>
&lt;live-only>
&lt;scale-down>
&lt;connectors>
&lt;connector-ref>server1-connector&lt;/connector-ref>
&lt;/connectors>
&lt;/scale-down>
&lt;/live-only>
&lt;/ha-policy>
</programlisting>
<para>In this instance the server is configured to use a specific connector to scale down, if a connector is not
specified then the first INVM connector is chosen, this is to make scale down fromm a backup server easy to configure.
It is also possible to use discovery to scale down, this would look like:</para>
<programlisting>
&lt;ha-policy>
&lt;live-only>
&lt;scale-down>
&lt;discovery-group>my-discovery-group&lt;/discovery-group>
&lt;/scale-down>
&lt;/live-only>
&lt;/ha-policy>
</programlisting>
<section id="ha.scaledown.group">
<title>Scale Down with groups</title>
<para>It is also possible to configure servers to only scale down to servers that belong in the same group. This
is done by configuring the group like so:</para>
<programlisting>
&lt;ha-policy>
&lt;live-only>
&lt;scale-down>
...
&lt;group-name>my-group&lt;/group-name>
&lt;/scale-down>
&lt;/live-only>
&lt;/ha-policy>
</programlisting>
<para>In this scenario only servers that belong to the group <literal>my-group</literal> will be scaled down to</para>
</section>
<section>
<title>Scale Down and Backups</title>
<para>It is also possible to mix scale down with HA via backup servers. If a slave is configured to scale down
then after failover has occurred, instead of starting fully the backup server will immediately scale down to
another live server. The most appropriate configuration for this is using the <literal>colocated</literal> approach.
it means as you bring up live server they will automatically be backed up by server and as live servers are
shutdown, there messages are made available on another live server. A typical configuration would look like:</para>
<programlisting>
&lt;ha-policy>
&lt;replication>
&lt;colocated>
&lt;backup-request-retries>44&lt;/backup-request-retries>
&lt;backup-request-retry-interval>33&lt;/backup-request-retry-interval>
&lt;max-backups>3&lt;/max-backups>
&lt;request-backup>false&lt;/request-backup>
&lt;backup-port-offset>33&lt;/backup-port-offset>
&lt;master>
&lt;group-name>purple&lt;/group-name>
&lt;check-for-live-server>true&lt;/check-for-live-server>
&lt;cluster-name>abcdefg&lt;/cluster-name>
&lt;/master>
&lt;slave>
&lt;group-name>tiddles&lt;/group-name>
&lt;max-saved-replicated-journals-size>22&lt;/max-saved-replicated-journals-size>
&lt;cluster-name>33rrrrr&lt;/cluster-name>
&lt;restart-backup>false&lt;/restart-backup>
&lt;scale-down>
&lt;!--a grouping of servers that can be scaled down to-->
&lt;group-name>boo!&lt;/group-name>
&lt;!--either a discovery group-->
&lt;discovery-group>wahey&lt;/discovery-group>
&lt;/scale-down>
&lt;/slave>
&lt;/colocated>
&lt;/replication>
&lt;/ha-policy>
</programlisting>
</section>
<section id="ha.scaledown.client">
<title>Scale Down and Clients</title>
<para>When a server is stopping and preparing to scale down it will send a message to all its clients informing them
which server it is scaling down to before disconnecting them. At this point the client will reconnect however this
will only succeed once the server has completed scaledown. This is to ensure that any state such as queues or transactions
are there for the client when it reconnects. The normal reconnect settings apply when the client is reconnecting so
these should be high enough to deal with the time needed to scale down.</para>
</section>
</section>
<section id="failover">
<title>Failover Modes</title>
<para>ActiveMQ defines two types of client failover:</para>
<itemizedlist>
<listitem>
<para>Automatic client failover</para>
</listitem>
<listitem>
<para>Application-level client failover</para>
</listitem>
</itemizedlist>
<para>ActiveMQ also provides 100% transparent automatic reattachment of connections to the
same server (e.g. in case of transient network problems). This is similar to failover,
except it is reconnecting to the same server and is discussed in
<xref linkend="client-reconnection"/></para>
<para>During failover, if the client has consumers on any non persistent or temporary
queues, those queues will be automatically recreated during failover on the backup node,
since the backup node will not have any knowledge of non persistent queues.</para>
<section id="ha.automatic.failover">
<title>Automatic Client Failover</title>
<para>ActiveMQ clients can be configured to receive knowledge of all live and backup servers, so
that in event of connection failure at the client - live server connection, the
client will detect this and reconnect to the backup server. The backup server will
then automatically recreate any sessions and consumers that existed on each
connection before failover, thus saving the user from having to hand-code manual
reconnection logic.</para>
<para>ActiveMQ clients detect connection failure when it has not received packets from
the server within the time given by <literal>client-failure-check-period</literal>
as explained in section <xref linkend="connection-ttl"/>. If the client does not
receive data in good time, it will assume the connection has failed and attempt
failover. Also if the socket is closed by the OS, usually if the server process is
killed rather than the machine itself crashing, then the client will failover straight away.
</para>
<para>ActiveMQ clients can be configured to discover the list of live-backup server groups in a
number of different ways. They can be configured explicitly or probably the most
common way of doing this is to use <emphasis>server discovery</emphasis> for the
client to automatically discover the list. For full details on how to configure
server discovery, please see <xref linkend="clusters"/>.
Alternatively, the clients can explicitly connect to a specific server and download
the current servers and backups see <xref linkend="clusters"/>.</para>
<para>To enable automatic client failover, the client must be configured to allow
non-zero reconnection attempts (as explained in <xref linkend="client-reconnection"
/>).</para>
<para>By default failover will only occur after at least one connection has been made to
the live server. In other words, by default, failover will not occur if the client
fails to make an initial connection to the live server - in this case it will simply
retry connecting to the live server according to the reconnect-attempts property and
fail after this number of attempts.</para>
<section>
<title>Failing over on the Initial Connection</title>
<para>
Since the client does not learn about the full topology until after the first
connection is made there is a window where it does not know about the backup. If a failure happens at
this point the client can only try reconnecting to the original live server. To configure
how many attempts the client will make you can set the property <literal>initialConnectAttempts</literal>
on the <literal>ClientSessionFactoryImpl</literal> or <literal >ActiveMQConnectionFactory</literal> or
<literal>initial-connect-attempts</literal> in xml. The default for this is <literal>0</literal>, that
is try only once. Once the number of attempts has been made an exception will be thrown.
</para>
</section>
<para>For examples of automatic failover with transacted and non-transacted JMS
sessions, please see <xref linkend="examples.transaction-failover"/> and <xref
linkend="examples.non-transaction-failover"/>.</para>
<section id="ha.automatic.failover.noteonreplication">
<title>A Note on Server Replication</title>
<para>ActiveMQ does not replicate full server state between live and backup servers.
When the new session is automatically recreated on the backup it won't have any
knowledge of messages already sent or acknowledged in that session. Any
in-flight sends or acknowledgements at the time of failover might also be
lost.</para>
<para>By replicating full server state, theoretically we could provide a 100%
transparent seamless failover, which would avoid any lost messages or
acknowledgements, however this comes at a great cost: replicating the full
server state (including the queues, session, etc.). This would require
replication of the entire server state machine; every operation on the live
server would have to replicated on the replica server(s) in the exact same
global order to ensure a consistent replica state. This is extremely hard to do
in a performant and scalable way, especially when one considers that multiple
threads are changing the live server state concurrently.</para>
<para>It is possible to provide full state machine replication using techniques such
as <emphasis role="italic">virtual synchrony</emphasis>, but this does not scale
well and effectively serializes all operations to a single thread, dramatically
reducing concurrency.</para>
<para>Other techniques for multi-threaded active replication exist such as
replicating lock states or replicating thread scheduling but this is very hard
to achieve at a Java level.</para>
<para>Consequently it has decided it was not worth massively reducing performance
and concurrency for the sake of 100% transparent failover. Even without 100%
transparent failover, it is simple to guarantee <emphasis role="italic">once and
only once</emphasis> delivery, even in the case of failure, by using a
combination of duplicate detection and retrying of transactions. However this is
not 100% transparent to the client code.</para>
</section>
<section id="ha.automatic.failover.blockingcalls">
<title>Handling Blocking Calls During Failover</title>
<para>If the client code is in a blocking call to the server, waiting for a response
to continue its execution, when failover occurs, the new session will not have
any knowledge of the call that was in progress. This call might otherwise hang
for ever, waiting for a response that will never come.</para>
<para>To prevent this, ActiveMQ will unblock any blocking calls that were in progress
at the time of failover by making them throw a <literal
>javax.jms.JMSException</literal> (if using JMS), or a <literal
>ActiveMQException</literal> with error code <literal
>ActiveMQException.UNBLOCKED</literal>. It is up to the client code to catch
this exception and retry any operations if desired.</para>
<para>If the method being unblocked is a call to commit(), or prepare(), then the
transaction will be automatically rolled back and ActiveMQ will throw a <literal
>javax.jms.TransactionRolledBackException</literal> (if using JMS), or a
<literal>ActiveMQException</literal> with error code <literal
>ActiveMQException.TRANSACTION_ROLLED_BACK</literal> if using the core
API.</para>
</section>
<section id="ha.automatic.failover.transactions">
<title>Handling Failover With Transactions</title>
<para>If the session is transactional and messages have already been sent or
acknowledged in the current transaction, then the server cannot be sure that
messages sent or acknowledgements have not been lost during the failover.</para>
<para>Consequently the transaction will be marked as rollback-only, and any
subsequent attempt to commit it will throw a <literal
>javax.jms.TransactionRolledBackException</literal> (if using JMS), or a
<literal>ActiveMQException</literal> with error code <literal
>ActiveMQException.TRANSACTION_ROLLED_BACK</literal> if using the core
API.</para>
<warning>
<title>2 phase commit</title>
<para>
The caveat to this rule is when XA is used either via JMS or through the core API.
If 2 phase commit is used and prepare has already been called then rolling back could
cause a <literal>HeuristicMixedException</literal>. Because of this the commit will throw
a <literal>XAException.XA_RETRY</literal> exception. This informs the Transaction Manager
that it should retry the commit at some later point in time, a side effect of this is
that any non persistent messages will be lost. To avoid this use persistent
messages when using XA. With acknowledgements this is not an issue since they are
flushed to the server before prepare gets called.
</para>
</warning>
<para>It is up to the user to catch the exception, and perform any client side local
rollback code as necessary. There is no need to manually rollback the session -
it is already rolled back. The user can then just retry the transactional
operations again on the same session.</para>
<para>ActiveMQ ships with a fully functioning example demonstrating how to do this,
please see <xref linkend="examples.transaction-failover"/></para>
<para>If failover occurs when a commit call is being executed, the server, as
previously described, will unblock the call to prevent a hang, since no response
will come back. In this case it is not easy for the client to determine whether
the transaction commit was actually processed on the live server before failure
occurred.</para>
<note>
<para>
If XA is being used either via JMS or through the core API then an <literal>XAException.XA_RETRY</literal>
is thrown. This is to inform Transaction Managers that a retry should occur at some point. At
some later point in time the Transaction Manager will retry the commit. If the original
commit has not occurred then it will still exist and be committed, if it does not exist
then it is assumed to have been committed although the transaction manager may log a warning.
</para>
</note>
<para>To remedy this, the client can simply enable duplicate detection (<xref
linkend="duplicate-detection"/>) in the transaction, and retry the
transaction operations again after the call is unblocked. If the transaction had
indeed been committed on the live server successfully before failover, then when
the transaction is retried, duplicate detection will ensure that any durable
messages resent in the transaction will be ignored on the server to prevent them
getting sent more than once.</para>
<note>
<para>By catching the rollback exceptions and retrying, catching unblocked calls
and enabling duplicate detection, once and only once delivery guarantees for
messages can be provided in the case of failure, guaranteeing 100% no loss
or duplication of messages.</para>
</note>
</section>
<section id="ha.automatic.failover.nontransactional">
<title>Handling Failover With Non Transactional Sessions</title>
<para>If the session is non transactional, messages or acknowledgements can be lost
in the event of failover.</para>
<para>If you wish to provide <emphasis role="italic">once and only once</emphasis>
delivery guarantees for non transacted sessions too, enabled duplicate
detection, and catch unblock exceptions as described in <xref
linkend="ha.automatic.failover.blockingcalls"/></para>
</section>
</section>
<section>
<title>Getting Notified of Connection Failure</title>
<para>JMS provides a standard mechanism for getting notified asynchronously of
connection failure: <literal>java.jms.ExceptionListener</literal>. Please consult
the JMS javadoc or any good JMS tutorial for more information on how to use
this.</para>
<para>The ActiveMQ core API also provides a similar feature in the form of the class
<literal>org.apache.activemq.core.client.SessionFailureListener</literal></para>
<para>Any ExceptionListener or SessionFailureListener instance will always be called by
ActiveMQ on event of connection failure, <emphasis role="bold"
>irrespective</emphasis> of whether the connection was successfully failed over,
reconnected or reattached, however you can find out if reconnect or reattach has happened
by either the <literal>failedOver</literal> flag passed in on the <literal>connectionFailed</literal>
on <literal>SessionfailureListener</literal> or by inspecting the error code on the
<literal>javax.jms.JMSException</literal> which will be one of the following:</para>
<table frame="topbot" border="2">
<title>JMSException error codes</title>
<tgroup cols="2">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<thead>
<row>
<entry>error code</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>FAILOVER</entry>
<entry>
Failover has occurred and we have successfully reattached or reconnected.
</entry>
</row>
<row>
<entry>DISCONNECT</entry>
<entry>
No failover has occurred and we are disconnected.
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section>
<title>Application-Level Failover</title>
<para>In some cases you may not want automatic client failover, and prefer to handle any
connection failure yourself, and code your own manually reconnection logic in your
own failure handler. We define this as <emphasis>application-level</emphasis>
failover, since the failover is handled at the user application level.</para>
<para>To implement application-level failover, if you're using JMS then you need to set
an <literal>ExceptionListener</literal> class on the JMS connection. The
<literal>ExceptionListener</literal> will be called by ActiveMQ in the event that
connection failure is detected. In your <literal>ExceptionListener</literal>, you
would close your old JMS connections, potentially look up new connection factory
instances from JNDI and creating new connections. In this case you may well be using
<ulink url="http://www.jboss.org/community/wiki/JBossHAJNDIImpl">HA-JNDI</ulink>
to ensure that the new connection factory is looked up from a different server.</para>
<para>For a working example of application-level failover, please see
<xref linkend="application-level-failover"/>.</para>
<para>If you are using the core API, then the procedure is very similar: you would set a
<literal>FailureListener</literal> on the core <literal>ClientSession</literal>
instances.</para>
</section>
</section>
</chapter>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,84 @@
Intercepting Operations
=======================
ActiveMQ supports *interceptors* to intercept packets entering and
exiting the server. Incoming and outgoing interceptors are be called for
any packet entering or exiting the server respectively. This allows
custom code to be executed, e.g. for auditing packets, filtering or
other reasons. Interceptors can change the packets they intercept. This
makes interceptors powerful, but also potentially dangerous.
Implementing The Interceptors
=============================
An interceptor must implement the `Interceptor interface`:
package org.apache.activemq.api.core.interceptor;
public interface Interceptor
{
boolean intercept(Packet packet, RemotingConnection connection) throws ActiveMQException;
}
The returned boolean value is important:
- if `true` is returned, the process continues normally
- if `false` is returned, the process is aborted, no other
interceptors will be called and the packet will not be processed
further by the server.
Configuring The Interceptors
============================
Both incoming and outgoing interceptors are configured in
`activemq-configuration.xml`:
<remoting-incoming-interceptors>
<class-name>org.apache.activemq.jms.example.LoginInterceptor</class-name>
<class-name>org.apache.activemq.jms.example.AdditionalPropertyInterceptor</class-name>
</remoting-incoming-interceptors>
<remoting-outgoing-interceptors>
<class-name>org.apache.activemq.jms.example.LogoutInterceptor</class-name>
<class-name>org.apache.activemq.jms.example.AdditionalPropertyInterceptor</class-name>
</remoting-outgoing-interceptors>
The interceptors classes (and their dependencies) must be added to the
server classpath to be properly instantiated and called.
Interceptors on the Client Side
===============================
The interceptors can also be run on the client side to intercept packets
either sent by the client to the server or by the server to the client.
This is done by adding the interceptor to the `ServerLocator` with the
`addIncomingInterceptor(Interceptor)` or
`addOutgoingInterceptor(Interceptor)` methods.
As noted above, if an interceptor returns `false` then the sending of
the packet is aborted which means that no other interceptors are be
called and the packet is not be processed further by the client.
Typically this process happens transparently to the client (i.e. it has
no idea if a packet was aborted or not). However, in the case of an
outgoing packet that is sent in a `blocking` fashion a
`ActiveMQException` will be thrown to the caller. The exception is
thrown because blocking sends provide reliability and it is considered
an error for them not to succeed. `Blocking` sends occurs when, for
example, an application invokes `setBlockOnNonDurableSend(true)` or
`setBlockOnDurableSend(true)` on its `ServerLocator` or if an
application is using a JMS connection factory retrieved from JNDI that
has either `block-on-durable-send` or `block-on-non-durable-send` set to
`true`. Blocking is also used for packets dealing with transactions
(e.g. commit, roll-back, etc.). The `ActiveMQException` thrown will
contain the name of the interceptor that returned false.
As on the server, the client interceptor classes (and their
dependencies) must be added to the classpath to be properly instantiated
and invoked.
Example
=======
See ? for an example which shows how to use interceptors to add
properties to a message on the server.

View File

@ -1,99 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="intercepting-operations">
<title>Intercepting Operations</title>
<para>ActiveMQ supports <emphasis>interceptors</emphasis> to intercept packets entering
and exiting the server. Incoming and outgoing interceptors are be called for any packet
entering or exiting the server respectively. This allows custom code to be executed,
e.g. for auditing packets, filtering or other reasons. Interceptors can change the
packets they intercept. This makes interceptors powerful, but also potentially
dangerous.</para>
<section>
<title>Implementing The Interceptors</title>
<para>An interceptor must implement the <literal>Interceptor interface</literal>:</para>
<programlisting>
package org.apache.activemq.api.core.interceptor;
public interface Interceptor
{
boolean intercept(Packet packet, RemotingConnection connection) throws ActiveMQException;
}</programlisting>
<para>The returned boolean value is important:</para>
<itemizedlist>
<listitem>
<para>if <literal>true</literal> is returned, the process continues normally</para>
</listitem>
<listitem>
<para>if <literal>false</literal> is returned, the process is aborted, no other interceptors
will be called and the packet will not be processed further by the server.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Configuring The Interceptors</title>
<para>Both incoming and outgoing interceptors are configured in
<literal>activemq-configuration.xml</literal>:</para>
<programlisting>
&lt;remoting-incoming-interceptors>
&lt;class-name>org.apache.activemq.jms.example.LoginInterceptor&lt;/class-name>
&lt;class-name>org.apache.activemq.jms.example.AdditionalPropertyInterceptor&lt;/class-name>
&lt;/remoting-incoming-interceptors></programlisting>
<programlisting>
&lt;remoting-outgoing-interceptors>
&lt;class-name>org.apache.activemq.jms.example.LogoutInterceptor&lt;/class-name>
&lt;class-name>org.apache.activemq.jms.example.AdditionalPropertyInterceptor&lt;/class-name>
&lt;/remoting-outgoing-interceptors></programlisting>
<para>The interceptors classes (and their dependencies) must be added to the server classpath
to be properly instantiated and called.</para>
</section>
<section>
<title>Interceptors on the Client Side</title>
<para>The interceptors can also be run on the client side to intercept packets either sent by the
client to the server or by the server to the client. This is done by adding the interceptor to
the <code>ServerLocator</code> with the <code>addIncomingInterceptor(Interceptor)</code> or
<code>addOutgoingInterceptor(Interceptor)</code> methods.</para>
<para>As noted above, if an interceptor returns <literal>false</literal> then the sending of the
packet is aborted which means that no other interceptors are be called and the packet is not
be processed further by the client. Typically this process happens transparently to the client
(i.e. it has no idea if a packet was aborted or not). However, in the case of an outgoing packet
that is sent in a <literal>blocking</literal> fashion a <literal>ActiveMQException</literal> will
be thrown to the caller. The exception is thrown because blocking sends provide reliability and
it is considered an error for them not to succeed. <literal>Blocking</literal> sends occurs when,
for example, an application invokes <literal>setBlockOnNonDurableSend(true)</literal> or
<literal>setBlockOnDurableSend(true)</literal> on its <literal>ServerLocator</literal> or if an
application is using a JMS connection factory retrieved from JNDI that has either
<literal>block-on-durable-send</literal> or <literal>block-on-non-durable-send</literal>
set to <literal>true</literal>. Blocking is also used for packets dealing with transactions (e.g.
commit, roll-back, etc.). The <literal>ActiveMQException</literal> thrown will contain the name
of the interceptor that returned false.</para>
<para>As on the server, the client interceptor classes (and their dependencies) must be added to the classpath
to be properly instantiated and invoked.</para>
</section>
<section>
<title>Example</title>
<para>See <xref linkend="examples.interceptor" /> for an example which
shows how to use interceptors to add properties to a message on the server.</para>
</section>
</chapter>

View File

@ -0,0 +1,365 @@
Interoperability
================
Stomp
=====
[Stomp](http://stomp.github.com/) is a text-orientated wire protocol
that allows Stomp clients to communicate with Stomp Brokers. ActiveMQ
now supports Stomp 1.0, 1.1 and 1.2.
Stomp clients are available for several languages and platforms making
it a good choice for interoperability.
Native Stomp support
--------------------
ActiveMQ provides native support for Stomp. To be able to send and
receive Stomp messages, you must configure a `NettyAcceptor` with a
`protocols` parameter set to have `stomp`:
<acceptor name="stomp-acceptor">
<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="protocols" value="STOMP"/>
<param key="port" value="61613"/>
</acceptor>
With this configuration, ActiveMQ will accept Stomp connections on the
port `61613` (which is the default port of the Stomp brokers).
See the `stomp` example which shows how to configure a ActiveMQ server
with Stomp.
### Limitations
Message acknowledgements are not transactional. The ACK frame can not be
part of a transaction (it will be ignored if its `transaction` header is
set).
### Stomp 1.1/1.2 Notes
#### Virtual Hosting
ActiveMQ currently doesn't support virtual hosting, which means the
'host' header in CONNECT fram will be ignored.
#### Heart-beating
ActiveMQ specifies a minimum value for both client and server heart-beat
intervals. The minimum interval for both client and server heartbeats is
500 milliseconds. That means if a client sends a CONNECT frame with
heartbeat values lower than 500, the server will defaults the value to
500 milliseconds regardless the values of the 'heart-beat' header in the
frame.
Mapping Stomp destinations to ActiveMQ addresses and queues
-----------------------------------------------------------
Stomp clients deals with *destinations* when sending messages and
subscribing. Destination names are simply strings which are mapped to
some form of destination on the server - how the server translates these
is left to the server implementation.
In ActiveMQ, these destinations are mapped to *addresses* and *queues*.
When a Stomp client sends a message (using a `SEND` frame), the
specified destination is mapped to an address. When a Stomp client
subscribes (or unsubscribes) for a destination (using a `SUBSCRIBE` or
`UNSUBSCRIBE` frame), the destination is mapped to a ActiveMQ queue.
STOMP and connection-ttl
------------------------
Well behaved STOMP clients will always send a DISCONNECT frame before
closing their connections. In this case the server will clear up any
server side resources such as sessions and consumers synchronously.
However if STOMP clients exit without sending a DISCONNECT frame or if
they crash the server will have no way of knowing immediately whether
the client is still alive or not. STOMP connections therefore default to
a connection-ttl value of 1 minute (see chapter on
[connection-ttl](#connection-ttl) for more information. This value can
be overridden using connection-ttl-override.
If you need a specific connection-ttl for your stomp connections without
affecting the connection-ttl-override setting, you can configure your
stomp acceptor with the "connection-ttl" property, which is used to set
the ttl for connections that are created from that acceptor. For
example:
<acceptor name="stomp-acceptor">
<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="protocols" value="STOMP"/>
<param key="port" value="61613"/>
<param key="connection-ttl" value="20000"/>
</acceptor>
The above configuration will make sure that any stomp connection that is
created from that acceptor will have its connection-ttl set to 20
seconds.
> **Note**
>
> Please note that the STOMP protocol version 1.0 does not contain any
> heartbeat frame. It is therefore the user's responsibility to make
> sure data is sent within connection-ttl or the server will assume the
> client is dead and clean up server side resources. With `Stomp 1.1`
> users can use heart-beats to maintain the life cycle of stomp
> connections.
Stomp and JMS interoperability
------------------------------
### Using JMS destinations
As explained in ?, JMS destinations are also mapped to ActiveMQ
addresses and queues. If you want to use Stomp to send messages to JMS
destinations, the Stomp destinations must follow the same convention:
- send or subscribe to a JMS *Queue* by prepending the queue name by
`jms.queue.`.
For example, to send a message to the `orders` JMS Queue, the Stomp
client must send the frame:
SEND
destination:jms.queue.orders
hello queue orders
^@
- send or subscribe to a JMS *Topic* by prepending the topic name by
`jms.topic.`.
For example to subscribe to the `stocks` JMS Topic, the Stomp client
must send the frame:
SUBSCRIBE
destination:jms.topic.stocks
^@
### Sending and consuming Stomp message from JMS or ActiveMQ Core API
Stomp is mainly a text-orientated protocol. To make it simpler to
interoperate with JMS and ActiveMQ Core API, our Stomp implementation
checks for presence of the `content-length` header to decide how to map
a Stomp message to a JMS Message or a Core message.
If the Stomp message does *not* have a `content-length` header, it will
be mapped to a JMS *TextMessage* or a Core message with a *single
nullable SimpleString in the body buffer*.
Alternatively, if the Stomp message *has* a `content-length` header, it
will be mapped to a JMS *BytesMessage* or a Core message with a *byte[]
in the body buffer*.
The same logic applies when mapping a JMS message or a Core message to
Stomp. A Stomp client can check the presence of the `content-length`
header to determine the type of the message body (String or bytes).
### Message IDs for Stomp messages
When receiving Stomp messages via a JMS consumer or a QueueBrowser, the
messages have no properties like JMSMessageID by default. However this
may bring some inconvenience to clients who wants an ID for their
purpose. ActiveMQ Stomp provides a parameter to enable message ID on
each incoming Stomp message. If you want each Stomp message to have a
unique ID, just set the `stomp-enable-message-id` to true. For example:
<acceptor name="stomp-acceptor">
<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="protocols" value="STOMP"/>
<param key="port" value="61613"/>
<param key="stomp-enable-message-id" value="true"/>
</acceptor>
When the server starts with the above setting, each stomp message sent
through this acceptor will have an extra property added. The property
key is `
hq-message-id` and the value is a String representation of a
long type internal message id prefixed with "`STOMP`", like:
hq-message-id : STOMP12345
If `stomp-enable-message-id` is not specified in the configuration,
default is `false`.
### Handling of Large Messages with Stomp
Stomp clients may send very large bodys of frames which can exceed the
size of ActiveMQ server's internal buffer, causing unexpected errors. To
prevent this situation from happening, ActiveMQ provides a stomp
configuration attribute `stomp-min-large-message-size`. This attribute
can be configured inside a stomp acceptor, as a parameter. For example:
<acceptor name="stomp-acceptor">
<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="protocols" value="STOMP"/>
<param key="port" value="61613"/>
<param key="stomp-min-large-message-size" value="10240"/>
</acceptor>
The type of this attribute is integer. When this attributed is
configured, ActiveMQ server will check the size of the body of each
Stomp frame arrived from connections established with this acceptor. If
the size of the body is equal or greater than the value of
`stomp-min-large-message`, the message will be persisted as a large
message. When a large message is delievered to a stomp consumer, the
HorentQ server will automatically handle the conversion from a large
message to a normal message, before sending it to the client.
If a large message is compressed, the server will uncompressed it before
sending it to stomp clients. The default value of
`stomp-min-large-message-size` is the same as the default value of
[min-large-message-size](#large-messages.core.config).
Stomp Over Web Sockets
----------------------
ActiveMQ also support Stomp over [Web
Sockets](http://dev.w3.org/html5/websockets/). Modern web browser which
support Web Sockets can send and receive Stomp messages from ActiveMQ.
To enable Stomp over Web Sockets, you must configure a `NettyAcceptor`
with a `protocol` parameter set to `stomp_ws`:
<acceptor name="stomp-ws-acceptor">
<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="protocols" value="STOMP_WS"/>
<param key="port" value="61614"/>
</acceptor>
With this configuration, ActiveMQ will accept Stomp connections over Web
Sockets on the port `61614` with the URL path `/stomp`. Web browser can
then connect to `ws://<server>:61614/stomp` using a Web Socket to send
and receive Stomp messages.
A companion JavaScript library to ease client-side development is
available from [GitHub](http://github.com/jmesnil/stomp-websocket)
(please see its [documentation](http://jmesnil.net/stomp-websocket/doc/)
for a complete description).
The `stomp-websockets` example shows how to configure ActiveMQ server to
have web browsers and Java applications exchanges messages on a JMS
topic.
StompConnect
------------
[StompConnect](http://stomp.codehaus.org/StompConnect) is a server that
can act as a Stomp broker and proxy the Stomp protocol to the standard
JMS API. Consequently, using StompConnect it is possible to turn
ActiveMQ into a Stomp Broker and use any of the available stomp clients.
These include clients written in C, C++, c\# and .net etc.
To run StompConnect first start the ActiveMQ server and make sure that
it is using JNDI.
Stomp requires the file `jndi.properties` to be available on the
classpath. This should look something like:
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
Configure any required JNDI resources in this file according to the
documentation.
Make sure this file is in the classpath along with the StompConnect jar
and the ActiveMQ jars and simply run `java org.codehaus.stomp.jms.Main`.
REST
====
Please see ?
AMQP
====
ActiveMQ supports the [AMQP
1.0](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=amqp)
specification. To enable AMQP you must configure a Netty Acceptor to
receive AMQP clients, like so:
<acceptor name="stomp-acceptor">
<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="protocols" value="AMQP"/>
<param key="port" value="5672"/>
</acceptor>
ActiveMQ will then accept AMQP 1.0 clients on port 5672 which is the
default AMQP port.
There are 2 Stomp examples available see proton-j and proton-ruby which
use the qpid Java and Ruby clients respectively
AMQP and security
-----------------
The ActiveMQ Server accepts AMQP SASL Authentication and will use this
to map onto the underlying session created for the connection so you can
use the normal ActiveMQ security configuration.
AMQP Links
----------
An AMQP Link is a uni directional transport for messages between a
source and a target, i.e. a client and the ActiveMQ Broker. A link will
have an endpoint of which there are 2 kinds, a Sender and A Receiver. At
the Broker a Sender will have its messages converted into a ActiveMQ
Message and forwarded to its destination or target. A Receiver will map
onto a ActiveMQ Server Consumer and convert ActiveMQ messages back into
AMQP messages before being delivered.
AMQP and destinations
---------------------
If an AMQP Link is dynamic then a temporary queue will be created and
either the remote source or remote target address will be set to the
name of the temporary queue. If the Link is not dynamic then the the
address of the remote target or source will used for the queue. If this
does not exist then an exception will be sent
> **Note**
>
> For the next version we will add a flag to aut create durable queue
> but for now you will have to add them via the configuration
AMQP and Coordinations - Handling Transactions
----------------------------------------------
An AMQP links target can also be a Coordinator, the Coordinator is used
to handle transactions. If a coordinator is used the the underlying
HormetQ Server session will be transacted and will be either rolled back
or committed via the coordinator.
> **Note**
>
> AMQP allows the use of multiple transactions per session,
> `amqp:multi-txns-per-ssn`, however in this version ActiveMQ will only
> support single transactions per session
OpenWire
========
ActiveMQ now supports the
[OpenWire](http://activemq.apache.org/openwire.html) protocol so that an
ActiveMQ JMS client can talk directly to a ActiveMQ server. To enable
OpenWire support you must configure a Netty Acceptor, like so:
<acceptor name="openwire-acceptor">
<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="protocols" value="OPENWIRE"/>
<param key="port" value="61616"/>
</acceptor>
The ActiveMQ server will then listens on port 61616 for incoming
openwire commands. Please note the "protocols" is not mandatory here.
The openwire configuration conforms to ActiveMQ's "Single Port" feature.
Please refer to [Configuring Single
Port](#configuring-transports.single-port) for details.
Please refer to the openwire example for more coding details.
Currently we support ActiveMQ clients that using standard JMS APIs. In
the future we will get more supports for some advanced, ActiveMQ
specific features into ActiveMQ.

View File

@ -1,305 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="interoperability">
<title>Interoperability</title>
<section id="stomp">
<title>Stomp</title>
<para><ulink url="http://stomp.github.com/">Stomp</ulink> is a text-orientated wire protocol that allows
Stomp clients to communicate with Stomp Brokers. ActiveMQ now supports Stomp 1.0, 1.1 and 1.2.</para>
<para>Stomp clients are available for
several languages and platforms making it a good choice for interoperability.</para>
<section id="stomp.native">
<title>Native Stomp support</title>
<para>ActiveMQ provides native support for Stomp. To be able to send and receive Stomp messages,
you must configure a <literal>NettyAcceptor</literal> with a <literal>protocols</literal>
parameter set to have <literal>stomp</literal>:</para>
<programlisting>
&lt;acceptor name="stomp-acceptor">
&lt;factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory&lt;/factory-class>
&lt;param key="protocols" value="STOMP"/>
&lt;param key="port" value="61613"/>
&lt;/acceptor></programlisting>
<para>With this configuration, ActiveMQ will accept Stomp connections on
the port <literal>61613</literal> (which is the default port of the Stomp brokers).</para>
<para>See the <literal>stomp</literal> example which shows how to configure a ActiveMQ server with Stomp.</para>
<section>
<title>Limitations</title>
<para>Message acknowledgements are not transactional. The ACK frame can not be part of a transaction
(it will be ignored if its <literal>transaction</literal> header is set).</para>
</section>
<section>
<title>Stomp 1.1/1.2 Notes</title>
<section>
<title>Virtual Hosting</title>
<para>ActiveMQ currently doesn't support virtual hosting, which means the 'host' header
in CONNECT fram will be ignored.</para>
</section>
<section>
<title>Heart-beating</title>
<para>ActiveMQ specifies a minimum value for both client and server heart-beat intervals.
The minimum interval for both client and server heartbeats is 500 milliseconds. That means if
a client sends a CONNECT frame with heartbeat values lower than 500, the server will defaults
the value to 500 milliseconds regardless the values of the 'heart-beat' header in the frame.</para>
</section>
</section>
</section>
<section>
<title>Mapping Stomp destinations to ActiveMQ addresses and queues</title>
<para>Stomp clients deals with <emphasis>destinations</emphasis> when sending messages and subscribing.
Destination names are simply strings which are mapped to some form of destination on the
server - how the server translates these is left to the server implementation.</para>
<para>In ActiveMQ, these destinations are mapped to <emphasis>addresses</emphasis> and <emphasis>queues</emphasis>.
When a Stomp client sends a message (using a <literal>SEND</literal> frame), the specified destination is mapped
to an address.
When a Stomp client subscribes (or unsubscribes) for a destination (using a <literal>SUBSCRIBE</literal>
or <literal>UNSUBSCRIBE</literal> frame), the destination is mapped to a ActiveMQ queue.</para>
</section>
<section>
<title>STOMP and connection-ttl</title>
<para>Well behaved STOMP clients will always send a DISCONNECT frame before closing their connections. In this case the server
will clear up any server side resources such as sessions and consumers synchronously. However if STOMP clients exit without
sending a DISCONNECT frame or if they crash the server will have no way of knowing immediately whether the client is still alive
or not. STOMP connections therefore default to a connection-ttl value of 1 minute (see chapter on <link linkend="connection-ttl"
>connection-ttl</link> for more information. This value can be overridden using connection-ttl-override.
</para>
<para>If you need a specific connection-ttl for your stomp connections without affecting the connection-ttl-override setting, you
can configure your stomp acceptor with the "connection-ttl" property, which is used to set the ttl for connections that are
created from that acceptor. For example:
</para>
<programlisting>
&lt;acceptor name="stomp-acceptor">
&lt;factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory&lt;/factory-class>
&lt;param key="protocols" value="STOMP"/>
&lt;param key="port" value="61613"/>
&lt;param key="connection-ttl" value="20000"/>
&lt;/acceptor></programlisting>
<para>The above configuration will make sure that any stomp connection that is created from that acceptor will have its
connection-ttl set to 20 seconds.</para>
<note><para>Please note that the STOMP protocol version 1.0 does not contain any heartbeat frame. It is therefore the user's
responsibility to make sure data is sent within connection-ttl or the server will assume the client is dead and clean up server
side resources. With <literal>Stomp 1.1</literal> users can use heart-beats to maintain the life cycle of stomp
connections.</para></note>
</section>
<section>
<title>Stomp and JMS interoperability</title>
<section>
<title>Using JMS destinations</title>
<para>As explained in <xref linkend="jms-core-mapping" />, JMS destinations are also mapped to ActiveMQ addresses and queues.
If you want to use Stomp to send messages to JMS destinations, the Stomp destinations must follow the same convention:</para>
<itemizedlist>
<listitem>
<para>send or subscribe to a JMS <emphasis>Queue</emphasis> by prepending the queue name by <literal>jms.queue.</literal>.</para>
<para>For example, to send a message to the <literal>orders</literal> JMS Queue, the Stomp client must send the frame:</para>
<programlisting>
SEND
destination:jms.queue.orders
hello queue orders
^@</programlisting>
</listitem>
<listitem>
<para>send or subscribe to a JMS <emphasis>Topic</emphasis> by prepending the topic name by <literal>jms.topic.</literal>.</para>
<para>For example to subscribe to the <literal>stocks</literal> JMS Topic, the Stomp client must send the frame:</para>
<programlisting>
SUBSCRIBE
destination:jms.topic.stocks
^@</programlisting>
</listitem>
</itemizedlist>
</section>
<section>
<title>Sending and consuming Stomp message from JMS or ActiveMQ Core API</title>
<para>Stomp is mainly a text-orientated protocol. To make it simpler to interoperate with JMS and ActiveMQ Core API,
our Stomp implementation checks for presence of the <literal>content-length</literal> header to decide how to map a Stomp message
to a JMS Message or a Core message.
</para>
<para>If the Stomp message does <emphasis>not</emphasis> have a <literal>content-length</literal> header, it will be mapped to a JMS <emphasis>TextMessage</emphasis>
or a Core message with a <emphasis>single nullable SimpleString in the body buffer</emphasis>.</para>
<para>Alternatively, if the Stomp message <emphasis>has</emphasis> a <literal>content-length</literal> header,
it will be mapped to a JMS <emphasis>BytesMessage</emphasis>
or a Core message with a <emphasis>byte[] in the body buffer</emphasis>.</para>
<para>The same logic applies when mapping a JMS message or a Core message to Stomp. A Stomp client can check the presence
of the <literal>content-length</literal> header to determine the type of the message body (String or bytes).</para>
</section>
<section>
<title>Message IDs for Stomp messages</title>
<para>When receiving Stomp messages via a JMS consumer or a QueueBrowser, the messages have
no properties like JMSMessageID by default. However this may bring some inconvenience to
clients who wants an ID for their purpose. ActiveMQ Stomp provides a parameter to enable
message ID on each incoming Stomp message. If you want each Stomp message to have a unique ID,
just set the <literal>stomp-enable-message-id</literal> to true. For example:</para>
<programlisting>
&lt;acceptor name="stomp-acceptor">
&lt;factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory&lt;/factory-class>
&lt;param key="protocols" value="STOMP"/>
&lt;param key="port" value="61613"/>
&lt;param key="stomp-enable-message-id" value="true"/>
&lt;/acceptor></programlisting>
<para>When the server starts with the above setting, each stomp message sent through this
acceptor will have an extra property added. The property key is <literal>
hq-message-id</literal> and the value is a String representation of a long type internal
message id prefixed with "<literal>STOMP</literal>", like:
<programlisting>
hq-message-id : STOMP12345</programlisting>
If <literal>stomp-enable-message-id</literal> is not specified in the configuration, default
is <literal>false</literal>. </para>
</section>
<section>
<title>Handling of Large Messages with Stomp</title>
<para>Stomp clients may send very large bodys of frames which can exceed the size of ActiveMQ
server's internal buffer, causing unexpected errors. To prevent this situation from happening,
ActiveMQ provides a stomp configuration attribute <literal>stomp-min-large-message-size</literal>.
This attribute can be configured inside a stomp acceptor, as a parameter. For example: </para>
<programlisting>
&lt;acceptor name="stomp-acceptor">
&lt;factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory&lt;/factory-class>
&lt;param key="protocols" value="STOMP"/>
&lt;param key="port" value="61613"/>
&lt;param key="stomp-min-large-message-size" value="10240"/>
&lt;/acceptor></programlisting>
<para>The type of this attribute is integer. When this attributed is configured, ActiveMQ server
will check the size of the body of each Stomp frame arrived from connections established with
this acceptor. If the size of the body is equal or greater than the value of
<literal>stomp-min-large-message</literal>, the message will be persisted as a large message.
When a large message is delievered to a stomp consumer, the HorentQ server will automatically
handle the conversion from a large message to a normal message, before sending it to the client.</para>
<para>If a large message is compressed, the server will uncompressed it before sending it to
stomp clients. The default value of <literal>stomp-min-large-message-size</literal> is the same
as the default value of <link linkend="large-messages.core.config">min-large-message-size</link>.</para>
</section>
</section>
<section id="stomp.websockets">
<title>Stomp Over Web Sockets</title>
<para>ActiveMQ also support Stomp over <ulink url="http://dev.w3.org/html5/websockets/">Web Sockets</ulink>. Modern web browser which support Web Sockets can send and receive
Stomp messages from ActiveMQ.</para>
<para>To enable Stomp over Web Sockets, you must configure a <literal>NettyAcceptor</literal> with a <literal>protocol</literal>
parameter set to <literal>stomp_ws</literal>:</para>
<programlisting>
&lt;acceptor name="stomp-ws-acceptor">
&lt;factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory&lt;/factory-class>
&lt;param key="protocols" value="STOMP_WS"/>
&lt;param key="port" value="61614"/>
&lt;/acceptor></programlisting>
<para>With this configuration, ActiveMQ will accept Stomp connections over Web Sockets on
the port <literal>61614</literal> with the URL path <literal>/stomp</literal>.
Web browser can then connect to <literal>ws://&lt;server>:61614/stomp</literal> using a Web Socket to send and receive Stomp
messages.</para>
<para>A companion JavaScript library to ease client-side development is available from
<ulink url="http://github.com/jmesnil/stomp-websocket">GitHub</ulink> (please see
its <ulink url="http://jmesnil.net/stomp-websocket/doc/">documentation</ulink> for a complete description).</para>
<para>The <literal>stomp-websockets</literal> example shows how to configure ActiveMQ server to have web browsers and Java
applications exchanges messages on a JMS topic.</para>
</section>
<section id="stompconnect">
<title>StompConnect</title>
<para><ulink url="http://stomp.codehaus.org/StompConnect">StompConnect</ulink> is a server that
can act as a Stomp broker and proxy the Stomp protocol to the standard JMS API.
Consequently, using StompConnect it is possible to turn ActiveMQ into a Stomp Broker and
use any of the available stomp clients. These include clients written in C, C++, c# and
.net etc.</para>
<para>To run StompConnect first start the ActiveMQ server and make sure that it is using
JNDI.</para>
<para>Stomp requires the file <literal>jndi.properties</literal> to be available on the
classpath. This should look something like:</para>
<programlisting>
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory</programlisting>
<para>Configure any required JNDI resources in this file according to the documentation.</para>
<para>Make sure this file is in the classpath along with the StompConnect jar and the
ActiveMQ jars and simply run <literal>java org.codehaus.stomp.jms.Main</literal>.</para>
</section>
</section>
<section>
<title>REST</title>
<para>Please see <xref linkend="rest"/></para>
</section>
<section>
<title>AMQP</title>
<para>ActiveMQ supports the <ulink url="https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=amqp">AMQP 1.0</ulink>
specification. To enable AMQP you must configure a Netty Acceptor to receive AMQP clients, like so:</para>
<programlisting>
&lt;acceptor name="stomp-acceptor">
&lt;factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory&lt;/factory-class>
&lt;param key="protocols" value="AMQP"/>
&lt;param key="port" value="5672"/>
&lt;/acceptor>
</programlisting>
<para>ActiveMQ will then accept AMQP 1.0 clients on port 5672 which is the default AMQP port.</para>
<para>There are 2 Stomp examples available see proton-j and proton-ruby which use the qpid Java and Ruby clients
respectively</para>
<section>
<title>AMQP and security</title>
<para>The ActiveMQ Server accepts AMQP SASL Authentication and will use this to map onto the underlying session created
for the connection so you can use the normal ActiveMQ security configuration.</para>
</section>
<section>
<title>AMQP Links</title>
<para>An AMQP Link is a uni directional transport for messages between a source and a target, i.e. a client and the
ActiveMQ Broker. A link will have an endpoint of which there are 2 kinds, a Sender and A Receiver. At the Broker a
Sender will have its messages converted into a ActiveMQ Message and forwarded to its destination or target. A
Receiver will map onto a ActiveMQ Server Consumer and convert ActiveMQ messages back into AMQP messages before being delivered.</para>
</section>
<section>
<title>AMQP and destinations</title>
<para>If an AMQP Link is dynamic then a temporary queue will be created and either the remote source or remote
target address will be set to the name of the temporary queue. If the Link is not dynamic then the the address
of the remote target or source will used for the queue. If this does not exist then an exception will be sent</para>
<note><para>For the next version we will add a flag to aut create durable queue but for now you will have to add them via
the configuration</para></note>
</section>
<section>
<title>AMQP and Coordinations - Handling Transactions</title>
<para>An AMQP links target can also be a Coordinator, the Coordinator is used to handle transactions. If a
coordinator is used the the underlying HormetQ Server session will be transacted and will be either rolled back
or committed via the coordinator.</para>
<note><para>AMQP allows the use of multiple transactions per session, <literal>amqp:multi-txns-per-ssn</literal>,
however in this version ActiveMQ will only support single transactions per session</para></note>
</section>
</section>
<section>
<title>OpenWire</title>
<para>ActiveMQ now supports the <ulink url="http://activemq.apache.org/openwire.html">OpenWire</ulink>
protocol so that an ActiveMQ JMS client can talk directly to a ActiveMQ server. To enable OpenWire support
you must configure a Netty Acceptor, like so:</para>
<programlisting>
&lt;acceptor name="openwire-acceptor">
&lt;factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory&lt;/factory-class>
&lt;param key="protocols" value="OPENWIRE"/>
&lt;param key="port" value="61616"/>
&lt;/acceptor>
</programlisting>
<para>The ActiveMQ server will then listens on port 61616 for incoming openwire commands. Please note the "protocols" is not mandatory here.
The openwire configuration conforms to ActiveMQ's "Single Port" feature. Please refer to
<link linkend="configuring-transports.single-port">Configuring Single Port</link> for details.</para>
<para>Please refer to the openwire example for more coding details.</para>
<para>Currently we support ActiveMQ clients that using standard JMS APIs. In the future we will get more supports
for some advanced, ActiveMQ specific features into ActiveMQ.</para>
</section>
</chapter>

View File

@ -0,0 +1,460 @@
The JMS Bridge
==============
ActiveMQ includes a fully functional JMS message bridge.
The function of the bridge is to consume messages from a source queue or
topic, and send them to a target queue or topic, typically on a
different server.
The source and target servers do not have to be in the same cluster
which makes bridging suitable for reliably sending messages from one
cluster to another, for instance across a WAN, and where the connection
may be unreliable.
A bridge can be deployed as a standalone application, with ActiveMQ
standalone server or inside a JBoss AS instance. The source and the
target can be located in the same virtual machine or another one.
The bridge can also be used to bridge messages from other non ActiveMQ
JMS servers, as long as they are JMS 1.1 compliant.
> **Note**
>
> Do not confuse a JMS bridge with a core bridge. A JMS bridge can be
> used to bridge any two JMS 1.1 compliant JMS providers and uses the
> JMS API. A core bridge (described in ?) is used to bridge any two
> ActiveMQ instances and uses the core API. Always use a core bridge if
> you can in preference to a JMS bridge. The core bridge will typically
> provide better performance than a JMS bridge. Also the core bridge can
> provide *once and only once* delivery guarantees without using XA.
The bridge has built-in resilience to failure so if the source or target
server connection is lost, e.g. due to network failure, the bridge will
retry connecting to the source and/or target until they come back
online. When it comes back online it will resume operation as normal.
The bridge can be configured with an optional JMS selector, so it will
only consume messages matching that JMS selector
It can be configured to consume from a queue or a topic. When it
consumes from a topic it can be configured to consume using a non
durable or durable subscription
Typically, the bridge is deployed by the JBoss Micro Container via a
beans configuration file. This would typically be deployed inside the
JBoss Application Server and the following example shows an example of a
beans file that bridges 2 destinations which are actually on the same
server.
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="urn:jboss:bean-deployer:2.0">
<bean name="JMSBridge" class="org.apache.activemq.api.jms.bridge.impl.JMSBridgeImpl">
<!-- ActiveMQ must be started before the bridge -->
<depends>ActiveMQServer</depends>
<constructor>
<!-- Source ConnectionFactory Factory -->
<parameter>
<inject bean="SourceCFF"/>
</parameter>
<!-- Target ConnectionFactory Factory -->
<parameter>
<inject bean="TargetCFF"/>
</parameter>
<!-- Source DestinationFactory -->
<parameter>
<inject bean="SourceDestinationFactory"/>
</parameter>
<!-- Target DestinationFactory -->
<parameter>
<inject bean="TargetDestinationFactory"/>
</parameter>
<!-- Source User Name (no username here) -->
<parameter><null /></parameter>
<!-- Source Password (no password here)-->
<parameter><null /></parameter>
<!-- Target User Name (no username here)-->
<parameter><null /></parameter>
<!-- Target Password (no password here)-->
<parameter><null /></parameter>
<!-- Selector -->
<parameter><null /></parameter>
<!-- Failure Retry Interval (in ms) -->
<parameter>5000</parameter>
<!-- Max Retries -->
<parameter>10</parameter>
<!-- Quality Of Service -->
<parameter>ONCE_AND_ONLY_ONCE</parameter>
<!-- Max Batch Size -->
<parameter>1</parameter>
<!-- Max Batch Time (-1 means infinite) -->
<parameter>-1</parameter>
<!-- Subscription name (no subscription name here)-->
<parameter><null /></parameter>
<!-- Client ID (no client ID here)-->
<parameter><null /></parameter>
<!-- Add MessageID In Header -->
<parameter>true</parameter>
<!-- register the JMS Bridge in the AS MBeanServer -->
<parameter>
<inject bean="MBeanServer"/>
</parameter>
<parameter>org.apache.activemq:service=JMSBridge</parameter>
</constructor>
<property name="transactionManager">
<inject bean="RealTransactionManager"/>
</property>
</bean>
<!-- SourceCFF describes the ConnectionFactory used to connect to the source destination -->
<bean name="SourceCFF"
class="org.apache.activemq.api.jms.bridge.impl.JNDIConnectionFactoryFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/ConnectionFactory</parameter>
</constructor>
</bean>
<!-- TargetCFF describes the ConnectionFactory used to connect to the target destination -->
<bean name="TargetCFF"
class="org.apache.activemq.api.jms.bridge.impl.JNDIConnectionFactoryFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/ConnectionFactory</parameter>
</constructor>
</bean>
<!-- SourceDestinationFactory describes the Destination used as the source -->
<bean name="SourceDestinationFactory" class="org.apache.activemq.api.jms.bridge.impl.JNDIDestinationFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/queue/source</parameter>
</constructor>
</bean>
<!-- TargetDestinationFactory describes the Destination used as the target -->
<bean name="TargetDestinationFactory" class="org.apache.activemq.api.jms.bridge.impl.JNDIDestinationFactory">
<constructor>
<parameter>
<inject bean="JNDI" />
</parameter>
<parameter>/queue/target</parameter>
</constructor>
</bean>
<!-- JNDI is a Hashtable containing the JNDI properties required -->
<!-- to connect to the sources and targets JMS resrouces -->
<bean name="JNDI" class="java.util.Hashtable">
<constructor class="java.util.Map">
<map class="java.util.Hashtable" keyClass="String"
valueClass="String">
<entry>
<key>java.naming.factory.initial</key>
<value>org.jnp.interfaces.NamingContextFactory</value>
</entry>
<entry>
<key>java.naming.provider.url</key>
<value>jnp://localhost:1099</value>
</entry>
<entry>
<key>java.naming.factory.url.pkgs</key>
<value>org.jboss.naming:org.jnp.interfaces"</value>
</entry>
<entry>
<key>jnp.timeout</key>
<value>5000</value>
</entry>
<entry>
<key>jnp.sotimeout</key>
<value>5000</value>
</entry>
</map>
</constructor>
</bean>
<bean name="MBeanServer" class="javax.management.MBeanServer">
<constructor factoryClass="org.jboss.mx.util.MBeanServerLocator" factoryMethod="locateJBoss"/>
</bean>
</deployment>
JMS Bridge Parameters
=====================
The main bean deployed is the `JMSBridge` bean. The bean is configurable
by the parameters passed to its constructor.
> **Note**
>
> To let a parameter be unspecified (for example, if the authentication
> is anonymous or no message selector is provided), use `<null
> />` for the unspecified parameter value.
- Source Connection Factory Factory
This injects the `SourceCFF` bean (also defined in the beans file).
This bean is used to create the *source* `ConnectionFactory`
- Target Connection Factory Factory
This injects the `TargetCFF` bean (also defined in the beans file).
This bean is used to create the *target* `ConnectionFactory`
- Source Destination Factory Factory
This injects the `SourceDestinationFactory` bean (also defined in
the beans file). This bean is used to create the *source*
`Destination`
- Target Destination Factory Factory
This injects the `TargetDestinationFactory` bean (also defined in
the beans file). This bean is used to create the *target*
`Destination`
- Source User Name
this parameter is the username for creating the *source* connection
- Source Password
this parameter is the parameter for creating the *source* connection
- Target User Name
this parameter is the username for creating the *target* connection
- Target Password
this parameter is the password for creating the *target* connection
- Selector
This represents a JMS selector expression used for consuming
messages from the source destination. Only messages that match the
selector expression will be bridged from the source to the target
destination
The selector expression must follow the [JMS selector
syntax](http://docs.oracle.com/javaee/6/api/javax/jms/Message.html)
- Failure Retry Interval
This represents the amount of time in ms to wait between trying to
recreate connections to the source or target servers when the bridge
has detected they have failed
- Max Retries
This represents the number of times to attempt to recreate
connections to the source or target servers when the bridge has
detected they have failed. The bridge will give up after trying this
number of times. `-1` represents 'try forever'
- Quality Of Service
This parameter represents the desired quality of service mode
Possible values are:
- `AT_MOST_ONCE`
- `DUPLICATES_OK`
- `ONCE_AND_ONLY_ONCE`
See ? for a explanation of these modes.
- Max Batch Size
This represents the maximum number of messages to consume from the
source destination before sending them in a batch to the target
destination. Its value must `>= 1`
- Max Batch Time
This represents the maximum number of milliseconds to wait before
sending a batch to target, even if the number of messages consumed
has not reached `MaxBatchSize`. Its value must be `-1` to represent
'wait forever', or `>= 1` to specify an actual time
- Subscription Name
If the source destination represents a topic, and you want to
consume from the topic using a durable subscription then this
parameter represents the durable subscription name
- Client ID
If the source destination represents a topic, and you want to
consume from the topic using a durable subscription then this
attribute represents the the JMS client ID to use when
creating/looking up the durable subscription
- Add MessageID In Header
If `true`, then the original message's message ID will be appended
in the message sent to the destination in the header
`ACTIVEMQ_BRIDGE_MSG_ID_LIST`. If the message is bridged more than
once, each message ID will be appended. This enables a distributed
request-response pattern to be used
> **Note**
>
> when you receive the message you can send back a response using
> the correlation id of the first message id, so when the original
> sender gets it back it will be able to correlate it.
- MBean Server
To manage the JMS Bridge using JMX, set the MBeanServer where the
JMS Bridge MBean must be registered (e.g. the JVM Platform
MBeanServer or JBoss AS MBeanServer)
- ObjectName
If you set the MBeanServer, you also need to set the ObjectName used
to register the JMS Bridge MBean (must be unique)
The "transactionManager" property points to a JTA transaction manager
implementation. ActiveMQ doesn't ship with such an implementation, but
one is available in the JBoss Community. If you are running ActiveMQ in
standalone mode and wish to use a JMS bridge simply download the latest
version of JBossTS from http://www.jboss.org/jbosstm/downloads and add
it to ActiveMQ's classpath. If you are running ActiveMQ with JBoss AS
then you won't need to do this as JBoss AS ships with a JTA transaction
manager already. The bean definition for the transaction manager would
look something like this:
<bean name="RealTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple"/>
Source and Target Connection Factories
======================================
The source and target connection factory factories are used to create
the connection factory used to create the connection for the source or
target server.
The configuration example above uses the default implementation provided
by ActiveMQ that looks up the connection factory using JNDI. For other
Application Servers or JMS providers a new implementation may have to be
provided. This can easily be done by implementing the interface
`org.apache.activemq.jms.bridge.ConnectionFactoryFactory`.
Source and Target Destination Factories
=======================================
Again, similarly, these are used to create or lookup up the
destinations.
In the configuration example above, we have used the default provided by
ActiveMQ that looks up the destination using JNDI.
A new implementation can be provided by implementing
`org.apache.activemq.jms.bridge.DestinationFactory` interface.
Quality Of Service
==================
The quality of service modes used by the bridge are described here in
more detail.
AT\_MOST\_ONCE
--------------
With this QoS mode messages will reach the destination from the source
at most once. The messages are consumed from the source and acknowledged
before sending to the destination. Therefore there is a possibility that
if failure occurs between removing them from the source and them
arriving at the destination they could be lost. Hence delivery will
occur at most once.
This mode is available for both durable and non-durable messages.
DUPLICATES\_OK
--------------
With this QoS mode, the messages are consumed from the source and then
acknowledged after they have been successfully sent to the destination.
Therefore there is a possibility that if failure occurs after sending to
the destination but before acknowledging them, they could be sent again
when the system recovers. I.e. the destination might receive duplicates
after a failure.
This mode is available for both durable and non-durable messages.
ONCE\_AND\_ONLY\_ONCE
---------------------
This QoS mode ensures messages will reach the destination from the
source once and only once. (Sometimes this mode is known as "exactly
once"). If both the source and the destination are on the same ActiveMQ
server instance then this can be achieved by sending and acknowledging
the messages in the same local transaction. If the source and
destination are on different servers this is achieved by enlisting the
sending and consuming sessions in a JTA transaction. The JTA transaction
is controlled by JBoss Transactions JTA \* implementation which is a
fully recovering transaction manager, thus providing a very high degree
of durability. If JTA is required then both supplied connection
factories need to be XAConnectionFactory implementations. This is likely
to be the slowest mode since it requires extra persistence for the
transaction logging.
This mode is only available for durable messages.
> **Note**
>
> For a specific application it may possible to provide once and only
> once semantics without using the ONCE\_AND\_ONLY\_ONCE QoS level. This
> can be done by using the DUPLICATES\_OK mode and then checking for
> duplicates at the destination and discarding them. Some JMS servers
> provide automatic duplicate message detection functionality, or this
> may be possible to implement on the application level by maintaining a
> cache of received message ids on disk and comparing received messages
> to them. The cache would only be valid for a certain period of time so
> this approach is not as watertight as using ONCE\_AND\_ONLY\_ONCE but
> may be a good choice depending on your specific application.
Time outs and the JMS bridge
----------------------------
There is a possibility that the target or source server will not be
available at some point in time. If this occurs then the bridge will try
`Max Retries` to reconnect every `Failure Retry Interval` milliseconds
as specified in the JMS Bridge definition.
However since a third party JNDI is used, in this case the JBoss naming
server, it is possible for the JNDI lookup to hang if the network were
to disappear during the JNDI lookup. To stop this from occurring the
JNDI definition can be configured to time out if this occurs. To do this
set the `jnp.timeout` and the `jnp.sotimeout` on the Initial Context
definition. The first sets the connection timeout for the initial
connection and the second the read timeout for the socket.
> **Note**
>
> Once the initial JNDI connection has succeeded all calls are made
> using RMI. If you want to control the timeouts for the RMI connections
> then this can be done via system properties. JBoss uses Sun's RMI and
> the properties can be found
> [here](http://docs.oracle.com/javase/6/docs/technotes/guides/rmi/sunrmiproperties.html).
> The default connection timeout is 10 seconds and the default read
> timeout is 18 seconds.
If you implement your own factories for looking up JMS resources then
you will have to bear in mind timeout issues.
Examples
--------
Please see ? which shows how to configure and use a JMS Bridge with
JBoss AS to send messages to the source destination and consume them
from the target destination.
Please see ? which shows how to configure and use a JMS Bridge between
two standalone ActiveMQ servers.

View File

@ -1,449 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
<!-- contributor license agreements. See the NOTICE file distributed with -->
<!-- this work for additional information regarding copyright ownership. -->
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
<!-- (the "License"); you may not use this file except in compliance with -->
<!-- the License. You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<!-- ============================================================================= -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
%BOOK_ENTITIES;
]>
<chapter id="jms-bridge">
<title>The JMS Bridge</title>
<para>ActiveMQ includes a fully functional JMS message bridge.</para>
<para>The function of the bridge is to consume messages from a source queue or topic, and
send them to a target queue or topic, typically on a different server.</para>
<para>The source and target servers do not have to be in the same cluster which makes
bridging suitable for reliably sending messages from one cluster to another, for
instance across a WAN, and where the connection may be unreliable.</para>
<para>A bridge can be deployed as a standalone application, with ActiveMQ standalone server or inside a JBoss AS
instance. The source and the target can be located in the same virtual machine or another one.</para>
<para>The bridge can also be used to bridge messages from other non ActiveMQ JMS servers, as
long as they are JMS 1.1 compliant.<note><para>Do not confuse a JMS bridge with a core
bridge. A JMS bridge can be used to bridge any two JMS 1.1 compliant JMS
providers and uses the JMS API. A core bridge (described in <xref
linkend="core-bridges"/>) is used to bridge any two ActiveMQ instances and
uses the core API. Always use a core bridge if you can in preference to a JMS
bridge. The core bridge will typically provide better performance than a JMS
bridge. Also the core bridge can provide <emphasis>once and only once</emphasis>
delivery guarantees without using XA.</para></note></para>
<para>The bridge has built-in resilience to failure so if the source or target server
connection is lost, e.g. due to network failure, the bridge will retry connecting to the
source and/or target until they come back online. When it comes back online it will
resume operation as normal.</para>
<para>The bridge can be configured with an optional JMS selector, so it will only consume
messages matching that JMS selector</para>
<para>It can be configured to consume from a queue or a topic. When it consumes from a topic
it can be configured to consume using a non durable or durable subscription</para>
<para>Typically, the bridge is deployed by the JBoss Micro Container via a beans configuration file.
This would typically be deployed inside the JBoss Application Server and the following
example shows an example of a beans file that bridges 2 destinations which are actually
on the same server. </para>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;deployment xmlns="urn:jboss:bean-deployer:2.0">
&lt;bean name="JMSBridge" class="org.apache.activemq.api.jms.bridge.impl.JMSBridgeImpl">
&lt;!-- ActiveMQ must be started before the bridge -->
&lt;depends>ActiveMQServer&lt;/depends>
&lt;constructor>
&lt;!-- Source ConnectionFactory Factory -->
&lt;parameter>
&lt;inject bean="SourceCFF"/>
&lt;/parameter>
&lt;!-- Target ConnectionFactory Factory -->
&lt;parameter>
&lt;inject bean="TargetCFF"/>
&lt;/parameter>
&lt;!-- Source DestinationFactory -->
&lt;parameter>
&lt;inject bean="SourceDestinationFactory"/>
&lt;/parameter>
&lt;!-- Target DestinationFactory -->
&lt;parameter>
&lt;inject bean="TargetDestinationFactory"/>
&lt;/parameter>
&lt;!-- Source User Name (no username here) -->
&lt;parameter>&lt;null />&lt;/parameter>
&lt;!-- Source Password (no password here)-->
&lt;parameter>&lt;null />&lt;/parameter>
&lt;!-- Target User Name (no username here)-->
&lt;parameter>&lt;null />&lt;/parameter>
&lt;!-- Target Password (no password here)-->
&lt;parameter>&lt;null />&lt;/parameter>
&lt;!-- Selector -->
&lt;parameter>&lt;null />&lt;/parameter>
&lt;!-- Failure Retry Interval (in ms) -->
&lt;parameter>5000&lt;/parameter>
&lt;!-- Max Retries -->
&lt;parameter>10&lt;/parameter>
&lt;!-- Quality Of Service -->
&lt;parameter>ONCE_AND_ONLY_ONCE&lt;/parameter>
&lt;!-- Max Batch Size -->
&lt;parameter>1&lt;/parameter>
&lt;!-- Max Batch Time (-1 means infinite) -->
&lt;parameter>-1&lt;/parameter>
&lt;!-- Subscription name (no subscription name here)-->
&lt;parameter>&lt;null />&lt;/parameter>
&lt;!-- Client ID (no client ID here)-->
&lt;parameter>&lt;null />&lt;/parameter>
&lt;!-- Add MessageID In Header -->
&lt;parameter>true&lt;/parameter>
&lt;!-- register the JMS Bridge in the AS MBeanServer -->
&lt;parameter>
&lt;inject bean="MBeanServer"/>
&lt;/parameter>
&lt;parameter>org.apache.activemq:service=JMSBridge&lt;/parameter>
&lt;/constructor>
&lt;property name="transactionManager">
&lt;inject bean="RealTransactionManager"/>
&lt;/property>
&lt;/bean>
&lt;!-- SourceCFF describes the ConnectionFactory used to connect to the source destination -->
&lt;bean name="SourceCFF"
class="org.apache.activemq.api.jms.bridge.impl.JNDIConnectionFactoryFactory">
&lt;constructor>
&lt;parameter>
&lt;inject bean="JNDI" />
&lt;/parameter>
&lt;parameter>/ConnectionFactory&lt;/parameter>
&lt;/constructor>
&lt;/bean>
&lt;!-- TargetCFF describes the ConnectionFactory used to connect to the target destination -->
&lt;bean name="TargetCFF"
class="org.apache.activemq.api.jms.bridge.impl.JNDIConnectionFactoryFactory">
&lt;constructor>
&lt;parameter>
&lt;inject bean="JNDI" />
&lt;/parameter>
&lt;parameter>/ConnectionFactory&lt;/parameter>
&lt;/constructor>
&lt;/bean>
&lt;!-- SourceDestinationFactory describes the Destination used as the source -->
&lt;bean name="SourceDestinationFactory" class="org.apache.activemq.api.jms.bridge.impl.JNDIDestinationFactory">
&lt;constructor>
&lt;parameter>
&lt;inject bean="JNDI" />
&lt;/parameter>
&lt;parameter>/queue/source&lt;/parameter>
&lt;/constructor>
&lt;/bean>
&lt;!-- TargetDestinationFactory describes the Destination used as the target -->
&lt;bean name="TargetDestinationFactory" class="org.apache.activemq.api.jms.bridge.impl.JNDIDestinationFactory">
&lt;constructor>
&lt;parameter>
&lt;inject bean="JNDI" />
&lt;/parameter>
&lt;parameter>/queue/target&lt;/parameter>
&lt;/constructor>
&lt;/bean>
&lt;!-- JNDI is a Hashtable containing the JNDI properties required -->
&lt;!-- to connect to the sources and targets JMS resrouces -->
&lt;bean name="JNDI" class="java.util.Hashtable">
&lt;constructor class="java.util.Map">
&lt;map class="java.util.Hashtable" keyClass="String"
valueClass="String">
&lt;entry>
&lt;key>java.naming.factory.initial&lt;/key>
&lt;value>org.jnp.interfaces.NamingContextFactory&lt;/value>
&lt;/entry>
&lt;entry>
&lt;key>java.naming.provider.url&lt;/key>
&lt;value>jnp://localhost:1099&lt;/value>
&lt;/entry>
&lt;entry>
&lt;key>java.naming.factory.url.pkgs&lt;/key>
&lt;value>org.jboss.naming:org.jnp.interfaces"&lt;/value>
&lt;/entry>
&lt;entry>
&lt;key>jnp.timeout&lt;/key>
&lt;value>5000&lt;/value>
&lt;/entry>
&lt;entry>
&lt;key>jnp.sotimeout&lt;/key>
&lt;value>5000&lt;/value>
&lt;/entry>
&lt;/map>
&lt;/constructor>
&lt;/bean>
&lt;bean name="MBeanServer" class="javax.management.MBeanServer">
&lt;constructor factoryClass="org.jboss.mx.util.MBeanServerLocator" factoryMethod="locateJBoss"/>
&lt;/bean>
&lt;/deployment></programlisting>
<section>
<title>JMS Bridge Parameters</title>
<para>The main bean deployed is the <literal>JMSBridge</literal> bean. The bean is
configurable by the parameters passed to its constructor.</para>
<note>
<para>To let a parameter be unspecified (for example, if the authentication is
anonymous or no message selector is provided), use <literal>&lt;null
/></literal> for the unspecified parameter value.</para>
</note>
<itemizedlist>
<listitem>
<para>Source Connection Factory Factory</para>
<para>This injects the <literal>SourceCFF</literal> bean (also defined in the
beans file). This bean is used to create the <emphasis>source</emphasis>
<literal>ConnectionFactory</literal>
</para>
</listitem>
<listitem>
<para>Target Connection Factory Factory</para>
<para>This injects the <literal>TargetCFF</literal> bean (also defined in the
beans file). This bean is used to create the <emphasis>target</emphasis>
<literal>ConnectionFactory</literal>
</para>
</listitem>
<listitem>
<para>Source Destination Factory Factory</para>
<para>This injects the <literal>SourceDestinationFactory</literal> bean (also
defined in the beans file). This bean is used to create the
<emphasis>source</emphasis>
<literal>Destination</literal>
</para>
</listitem>
<listitem>
<para>Target Destination Factory Factory</para>
<para>This injects the <literal>TargetDestinationFactory</literal> bean (also
defined in the beans file). This bean is used to create the
<emphasis>target</emphasis>
<literal>Destination</literal>
</para>
</listitem>
<listitem>
<para>Source User Name</para>
<para>this parameter is the username for creating the
<emphasis>source</emphasis> connection</para>
</listitem>
<listitem>
<para>Source Password</para>
<para>this parameter is the parameter for creating the
<emphasis>source</emphasis> connection</para>
</listitem>
<listitem>
<para>Target User Name</para>
<para>this parameter is the username for creating the
<emphasis>target</emphasis> connection</para>
</listitem>
<listitem>
<para>Target Password</para>
<para>this parameter is the password for creating the
<emphasis>target</emphasis> connection</para>
</listitem>
<listitem>
<para>Selector</para>
<para>This represents a JMS selector expression used for consuming messages from
the source destination. Only messages that match the selector expression
will be bridged from the source to the target destination</para>
<para>The selector expression must follow the <ulink
url="http://docs.oracle.com/javaee/6/api/javax/jms/Message.html">JMS
selector syntax</ulink></para>
</listitem>
<listitem>
<para>Failure Retry Interval</para>
<para>This represents the amount of time in ms to wait between trying to
recreate connections to the source or target servers when the bridge has
detected they have failed</para>
</listitem>
<listitem>
<para>Max Retries</para>
<para>This represents the number of times to attempt to recreate connections to
the source or target servers when the bridge has detected they have failed.
The bridge will give up after trying this number of times. <literal
>-1</literal> represents 'try forever'</para>
</listitem>
<listitem>
<para>Quality Of Service</para>
<para>This parameter represents the desired quality of service mode</para>
<para>Possible values are:</para>
<itemizedlist>
<listitem>
<para><literal>AT_MOST_ONCE</literal></para>
</listitem>
<listitem>
<para><literal>DUPLICATES_OK</literal></para>
</listitem>
<listitem>
<para><literal>ONCE_AND_ONLY_ONCE</literal></para>
</listitem>
</itemizedlist>
<para>See <xref linkend="quality-of-service"/> for a explanation of these
modes.</para>
</listitem>
<listitem>
<para>Max Batch Size</para>
<para>This represents the maximum number of messages to consume from the source
destination before sending them in a batch to the target destination. Its
value must <literal>>= 1</literal>
</para>
</listitem>
<listitem>
<para>Max Batch Time</para>
<para>This represents the maximum number of milliseconds to wait before sending
a batch to target, even if the number of messages consumed has not reached
<literal>MaxBatchSize</literal>. Its value must be <literal>-1</literal>
to represent 'wait forever', or <literal>>= 1</literal> to specify an actual
time </para>
</listitem>
<listitem>
<para>Subscription Name</para>
<para>If the source destination represents a topic, and you want to consume from
the topic using a durable subscription then this parameter represents the
durable subscription name</para>
</listitem>
<listitem>
<para>Client ID</para>
<para>If the source destination represents a topic, and you want to consume from
the topic using a durable subscription then this attribute represents the
the JMS client ID to use when creating/looking up the durable
subscription</para>
</listitem>
<listitem>
<para>Add MessageID In Header</para>
<para>If <literal>true</literal>, then the original message's message ID will be
appended in the message sent to the destination in the header <literal
>ACTIVEMQ_BRIDGE_MSG_ID_LIST</literal>. If the message is bridged more
than once, each message ID will be appended. This enables a distributed
request-response pattern to be used</para>
<note>
<para>when you receive the message you can send back a response using the
correlation id of the first message id, so when the original sender gets
it back it will be able to correlate it. </para>
</note>
</listitem>
<listitem>
<para>MBean Server</para>
<para>To manage the JMS Bridge using JMX, set the MBeanServer where the JMS Bridge MBean
must be registered (e.g. the JVM Platform MBeanServer or JBoss AS MBeanServer)</para>
</listitem>
<listitem>
<para>ObjectName</para>
<para>If you set the MBeanServer, you also need to set the ObjectName used to register
the JMS Bridge MBean (must be unique)</para>
</listitem>
</itemizedlist>
<para>The "transactionManager" property points to a JTA transaction manager implementation.
ActiveMQ doesn't ship with such an implementation, but one is available in the JBoss
Community. If you are running ActiveMQ in standalone mode and wish to use a JMS bridge
simply download the latest version of JBossTS from http://www.jboss.org/jbosstm/downloads
and add it to ActiveMQ's classpath. If you are running ActiveMQ with JBoss AS then you
won't need to do this as JBoss AS ships with a JTA transaction manager already. The
bean definition for the transaction manager would look something like this:
</para>
<programlisting>&lt;bean name="RealTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple"/></programlisting>
</section>
<section>
<title>Source and Target Connection Factories</title>
<para>The source and target connection factory factories are used to create the
connection factory used to create the connection for the source or target
server.</para>
<para>The configuration example above uses the default implementation provided by
ActiveMQ that looks up the connection factory using JNDI. For other Application
Servers or JMS providers a new implementation may have to be provided. This can
easily be done by implementing the interface <literal
>org.apache.activemq.jms.bridge.ConnectionFactoryFactory</literal>.</para>
</section>
<section>
<title>Source and Target Destination Factories</title>
<para>Again, similarly, these are used to create or lookup up the destinations.</para>
<para>In the configuration example above, we have used the default provided by ActiveMQ
that looks up the destination using JNDI.</para>
<para>A new implementation can be provided by implementing <literal
>org.apache.activemq.jms.bridge.DestinationFactory</literal> interface.</para>
</section>
<section id="quality-of-service">
<title>Quality Of Service</title>
<para>The quality of service modes used by the bridge are described here in more
detail.</para>
<section>
<title>AT_MOST_ONCE</title>
<para>With this QoS mode messages will reach the destination from the source at most
once. The messages are consumed from the source and acknowledged before sending
to the destination. Therefore there is a possibility that if failure occurs
between removing them from the source and them arriving at the destination they
could be lost. Hence delivery will occur at most once.</para>
<para>This mode is available for both durable and non-durable messages.</para>
</section>
<section>
<title>DUPLICATES_OK</title>
<para>With this QoS mode, the messages are consumed from the source and then
acknowledged after they have been successfully sent to the destination.
Therefore there is a possibility that if failure occurs after sending to the
destination but before acknowledging them, they could be sent again when the
system recovers. I.e. the destination might receive duplicates after a
failure.</para>
<para>This mode is available for both durable and non-durable messages.</para>
</section>
<section>
<title>ONCE_AND_ONLY_ONCE</title>
<para>This QoS mode ensures messages will reach the destination from the source once
and only once. (Sometimes this mode is known as "exactly once"). If both the
source and the destination are on the same ActiveMQ server instance then this can
be achieved by sending and acknowledging the messages in the same local
transaction. If the source and destination are on different servers this is
achieved by enlisting the sending and consuming sessions in a JTA transaction.
The JTA transaction is controlled by JBoss Transactions JTA * implementation
which is a fully recovering transaction manager, thus providing a very high
degree of durability. If JTA is required then both supplied connection factories
need to be XAConnectionFactory implementations. This is likely to be the slowest
mode since it requires extra persistence for the transaction logging.</para>
<para>This mode is only available for durable messages.</para>
<note>
<para>For a specific application it may possible to provide once and only once
semantics without using the ONCE_AND_ONLY_ONCE QoS level. This can be done
by using the DUPLICATES_OK mode and then checking for duplicates at the
destination and discarding them. Some JMS servers provide automatic
duplicate message detection functionality, or this may be possible to
implement on the application level by maintaining a cache of received
message ids on disk and comparing received messages to them. The cache would
only be valid for a certain period of time so this approach is not as
watertight as using ONCE_AND_ONLY_ONCE but may be a good choice depending on
your specific application.</para>
</note>
</section>
<section>
<title>Time outs and the JMS bridge</title>
<para>There is a possibility that the target or source server will not be available at some point in time.
If this occurs then the bridge will try <literal>Max Retries</literal> to reconnect every
<literal>Failure Retry Interval</literal> milliseconds as specified in the JMS Bridge definition.</para>
<para>However since a third party JNDI is used, in this case the JBoss naming server, it is possible for the
JNDI lookup to hang if the network were to disappear during the JNDI lookup. To stop this from occurring the JNDI
definition can be configured to time out if this occurs. To do this set the <literal>jnp.timeout</literal>
and the <literal>jnp.sotimeout</literal> on the Initial Context definition. The first sets the connection
timeout for the initial connection and the second the read timeout for the socket.</para>
<note>
<para>Once the initial JNDI connection has succeeded all calls are made using RMI. If you want to control
the timeouts for the RMI connections then this can be done via system properties. JBoss uses Sun's RMI
and the properties can be found <ulink
url="http://docs.oracle.com/javase/6/docs/technotes/guides/rmi/sunrmiproperties.html">here</ulink>.
The default connection timeout is 10 seconds and the default read timeout is 18 seconds.</para>
</note>
<para>If you implement your own factories for looking up JMS resources then you will have to bear in mind timeout issues.</para>
</section>
<section>
<title>Examples</title>
<para>Please see <xref linkend="examples.javaee.jms-bridge"/> which shows how to configure
and use a JMS Bridge with JBoss AS to send messages to the source destination and consume them
from the target destination.</para>
<para>Please see <xref linkend="examples.jms.jms-bridge"/> which shows how to configure
and use a JMS Bridge between two standalone ActiveMQ servers.</para>
</section>
</section>
</chapter>

Some files were not shown because too many files have changed in this diff Show More