initial commit

This commit is contained in:
markpollack
2010-06-29 22:16:39 -04:00
commit 0d08676e16
246 changed files with 19212 additions and 0 deletions

17
.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-amqp</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

196
pom.xml Normal file
View File

@@ -0,0 +1,196 @@
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp</artifactId>
<name>Spring AMQP</name>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>spring-amqp-core</module>
<module>spring-amqp-parent</module>
<module>spring-otp</module>
<module>spring-rabbit</module>
<module>spring-rabbit-admin</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<profiles>
<profile>
<id>staging</id>
<distributionManagement>
<site>
<id>staging</id>
<url>file:///${java.io.tmpdir}/target/site</url>
</site>
<repository>
<id>staging</id>
<url>file:///${java.io.tmpdir}/target/repository</url>
</repository>
<snapshotRepository>
<id>staging</id>
<url>file:///${java.io.tmpdir}/target/snapshotRepository</url>
</snapshotRepository>
</distributionManagement>
</profile>
</profiles>
<distributionManagement>
<!-- see 'staging' profile for dry-run deployment settings -->
<downloadUrl>http://static.springframework.org/spring-amqp/site/downloads/releases.html</downloadUrl>
<repository>
<id>local</id>
<url>file://${java.io.tmpdir}/spring-amqp-repo</url>
</repository>
<snapshotRepository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>s3://maven.springframework.org/snapshot</url>
</snapshotRepository>
<site>
<id>static.springframework.org</id>
<url>scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-amqp/sites/${project.version}</url>
</site>
</distributionManagement>
<build>
<extensions>
<extension>
<!-- available only in the springframework maven repository. see <repositories> section below -->
<groupId>org.springframework.build.aws</groupId>
<artifactId>org.springframework.build.aws.maven</artifactId>
<version>3.0.0.RELEASE</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>com.agilejava.docbkx</groupId>
<artifactId>docbkx-maven-plugin</artifactId>
<version>2.0.6</version>
<executions>
<execution>
<goals>
<goal>generate-html</goal>
<goal>generate-pdf</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.docbook</groupId>
<artifactId>docbook-xml</artifactId>
<version>4.4</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<configuration>
<includes>index.xml</includes>
<xincludeSupported>true</xincludeSupported>
<foCustomization>${project.basedir}/src/docbkx/resources/xsl/fopdf.xsl</foCustomization>
<!-- original spring-build fopdf xsl
<foCustomization>src/docbkx/resources/xsl/pdf/fopdf.xsl</foCustomization> -->
<htmlStylesheet>css/html.css</htmlStylesheet>
<!-- produce single-page html output -->
<chunkedOutput>false</chunkedOutput>
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html.xsl</htmlCustomization>
<!-- produce multi-page html output
<chunkedOutput>false</chunkedOutput>
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html_chunk.xsl</htmlCustomization> -->
<entities>
<entity>
<name>version</name>
<value>${pom.version}</value>
</entity>
</entities>
<postProcess>
<copy todir="${project.basedir}/target/site/reference">
<fileset dir="${project.basedir}/target/docbkx">
<include name="**/*.html" />
<include name="**/*.pdf" />
</fileset>
</copy>
<copy todir="${project.basedir}/target/site/reference/html">
<fileset dir="${project.basedir}/src/docbkx/resources">
<include name="**/*.css" />
<include name="**/*.png" />
<include name="**/*.gif" />
<include name="**/*.jpg" />
</fileset>
</copy>
<move file="${project.basedir}/target/site/reference/pdf/index.pdf"
tofile="${project.basedir}/target/site/reference/pdf/spring-amqp-reference.pdf"
failonerror="false" />
</postProcess>
</configuration>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
<phase>package</phase>
<configuration>
<javadoc:aggregate>true</javadoc:aggregate>
<breakiterator>true</breakiterator>
<header>Spring AMQP</header>
<source>1.5</source>
<quiet>true</quiet>
<javadocDirectory>${project.basedir}/src/main/javadoc</javadocDirectory>
<overview>${project.basedir}/src/main/javadoc/overview.html</overview>
<stylesheetfile>${project.basedir}/src/main/javadoc/spring-javadoc.css</stylesheetfile>
<!-- copies doc-files subdirectory which contains image resources -->
<docfilessubdirs>true</docfilessubdirs>
<groups>
<group>
<title>Spring AMQP</title>
<packages>org.springframework.amqp.core</packages>
</group>
<!-- TODO: fill in other groups -->
</groups>
<excludePackageNames>org.springframework.amqp.samples</excludePackageNames>
<links>
<link>http://static.springframework.org/spring/docs/3.0.3.RELEASE/javadoc-api</link>
<link>http://java.sun.com/javase/6/docs/api</link>
</links>
</configuration>
</execution>
</executions>
</plugin>
<plugin><!--
run `mvn package assembly:assembly` to trigger assembly creation.
see http://www.sonatype.com/books/mvnref-book/reference/assemblies-set-dist-assemblies.html -->
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<inherited>false</inherited>
<executions>
<execution>
<id>distribution</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/assembly/distribution.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<!-- necessary for org.springframework.build.aws.maven dependency -->
<id>repository.springframework.maven.release</id>
<name>Spring Framework Maven Release Repository</name>
<url>http://maven.springframework.org/release</url>
</repository>
</repositories>
</project>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry including="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry including="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

35
spring-amqp-core/.project Normal file
View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-amqp-core</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.springframework.ide.eclipse.core.springnature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,9 @@
#Wed Jan 13 19:28:20 EST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.3.3.201005160334-M1]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
<enableImports><![CDATA[false]]></enableImports>
<configs>
</configs>
<configSets>
</configSets>
</beansProjectDescription>

100
spring-amqp-core/pom.xml Normal file
View File

@@ -0,0 +1,100 @@
<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.springframework.amqp</groupId>
<artifactId>spring-amqp-parent</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>../spring-amqp-parent/pom.xml</relativePath>
</parent>
<artifactId>spring-amqp-core</artifactId>
<packaging>jar</packaging>
<name>Spring AMQP Core</name>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<!-- Other -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp;
/**
* Base RuntimeException for errors that occur when executing AMQP operations.
*
* @author Mark Fisher
*/
public class AmqpException extends RuntimeException {
public AmqpException(String message) {
super(message);
}
public AmqpException(Throwable cause) {
super(cause);
}
public AmqpException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp;
import java.io.IOException;
/**
* RuntimeException wrapper for an {@link IOException} which
* can be commonly thrown from AMQP operations.
*
* @author Mark Pollack
*/
public class AmqpIOException extends AmqpException {
public AmqpIOException(IOException cause) {
super(cause);
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp;
/**
* Equivalent of an IllegalStateException but within the AmqpException hierarchy.
*
* @author Mark Pollack
*/
public class AmqpIllegalStateException extends AmqpException {
public AmqpIllegalStateException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp;
/**
* RuntimeException for unsupported encoding in an AMQP operation.
*
* @author Mark Pollack
*/
public class AmqpUnsupportedEncodingException extends AmqpException {
public AmqpUnsupportedEncodingException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp;
/**
* A "catch-all" exception type within the AmqpException hierarchy
* when no more specific cause is known.
*
* @author Mark Pollack
*/
public class UncategorizedAmqpException extends AmqpException {
public UncategorizedAmqpException(Throwable cause) {
super(cause);
}
public UncategorizedAmqpException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import java.util.Map;
/**
* Define common properties for all exchange types.
*
* @author Mark Pollack
*/
public abstract class AbstractExchange {
protected String name;
private boolean passive = false;
private boolean durable = false;
private boolean autoDelete = false;
private Map<String, Object> arguments = null;
public abstract ExchangeType getExchangeType();
public String getName() {
return name;
}
public boolean isPassive() {
return passive;
}
public void setPassive(boolean passive) {
this.passive = passive;
}
public boolean isDurable() {
return durable;
}
public void setDurable(boolean durable) {
this.durable = durable;
}
public boolean isAutoDelete() {
return autoDelete;
}
public void setAutoDelete(boolean autoDelete) {
this.autoDelete = autoDelete;
}
public Map<String, Object> getArguments() {
return arguments;
}
public void setArguments(Map<String, Object> arguments) {
this.arguments = arguments;
}
@Override
public String toString() {
return "Exchange [name=" + name +
", type=" + getExchangeType().name() +
", passive=" + passive +
", durable=" + durable +
", autoDelete=" + autoDelete +
", arguments=" + arguments + "]";
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Represents an address for publication of an AMQP message. The AMQP 0-8 and
* 0-9 specifications have an unstructured string that is used as a "reply to"
* address. There are however conventions in use and this class makes it easier
* to follow these conventions.
*
* @author Mark Pollack
*/
public class Address {
private static final Pattern pattern = Pattern.compile("^([^:]+)://([^/]*)/(.*)$");
private String unstructuredAddress;
private ExchangeType exchangeType;
private String exchangeName;
private String routingKey;
private boolean structured;
/**
* Create an Address instance from an unstructured String.
* @param address an unstructured string.
*/
public Address(String address) {
this.unstructuredAddress = address;
}
/***
* Create an Address given the exchange type, exchange name and routing key. This
* will set the
* @param exchangeType
* @param exchangeName
* @param routingKey
*/
public Address(ExchangeType exchangeType, String exchangeName, String routingKey) {
this.structured = true;
this.exchangeType = exchangeType;
this.exchangeName = exchangeName;
this.routingKey = routingKey;
}
public static Address parse(String address) {
if (address == null) {
return null;
}
Matcher matcher = pattern.matcher(address);
boolean matchFound = matcher.find();
if (matchFound) {
//TODO regex not expecting as would like with grouping.
String exchangeType = matcher.group(1);
String routingKey = address.substring(address.lastIndexOf(matcher.group(2))+matcher.group(2).length()+1);
return new Address(ExchangeType.valueOf(exchangeType), matcher.group(2),routingKey);
}
return new Address(address);
}
public ExchangeType getExchangeType() {
return exchangeType;
}
public String getExchangeName() {
return exchangeName;
}
public String getRoutingKey() {
return routingKey;
}
public boolean isStructured() {
return structured;
}
public String toString() {
return this.structured ? this.exchangeType + "://" + this.exchangeName + "/" + this.routingKey
: this.unstructuredAddress;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import org.springframework.amqp.AmqpException;
/**
* Specifies a basic set of AMQP operations
*
* Implemented by {@link RabbitTemplate}. Not often used but a useful option to
* enhance testability, as it can easily be mocked or stubbed.
*
* Provides synchronous send an receive methods. The convertAndSend and receiveAndConvert
* methods allow let you send and receive POJO objects. RabbitTemplate delegates to
* an instance of {@link org.springframework.support.converter.MessageConverter} to perform
* conversion to and from Rabbit's byte[] payload type.
*
* @author Mark Pollack
* @author Mark Fisher
*/
public interface AmqpTemplate {
void send(MessageCreator messageCreator) throws AmqpException;
void send(String routingKey, MessageCreator messageCreator) throws AmqpException;
void send(String exchange, String routingKey, MessageCreator messageCreator) throws AmqpException;
void convertAndSend(Object message) throws AmqpException;
void convertAndSend(String routingKey, Object message) throws AmqpException;
void convertAndSend(String exchange, String routingKey, Object message) throws AmqpException;
void convertAndSend(Object message, MessagePostProcessor messagePostProcessor) throws AmqpException;
void convertAndSend(String routingKey, Object message, MessagePostProcessor messagePostProcessor) throws AmqpException;
void convertAndSend(String exchange, String routingKey, Object message, MessagePostProcessor messagePostProcessor) throws AmqpException;
Message receive() throws AmqpException;
Message receive(String queueName) throws AmqpException;
Object receiveAndConvert() throws AmqpException;
Object receiveAndConvert(String queueName) throws AmqpException;
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import java.util.Map;
/**
* Simple container collecting information to describe a queue binding. Takes Queue and Exchange
* class as arguments to facilitate wiring using @Bean code based configuration.
* Used in conjunction with RabbitAdminTemplate.
*
* @author Mark Pollack
* @see RabbitAdminTemplate
*/
public class Binding {
private String queue;
private String exchange;
private String routingKey;
Map<java.lang.String,java.lang.Object> arguments;
//Is this really worth the syntax sugar?
public static Binding binding(Queue queue, AbstractExchange exchange, String routingKey) {
return new Binding(queue, exchange, routingKey);
}
//TODO would be good to remove this because invalid bindings can be specified (fanout with routing key)
Binding(Queue queue, AbstractExchange exchange, String routingKey) {
this.queue = queue.getName();
this.exchange = exchange.getName();
this.routingKey = routingKey;
}
public Binding(Queue queue, FanoutExchange exchange) {
this.queue = queue.getName();
this.exchange = exchange.getName();
this.routingKey = "";
}
public Binding(Queue queue, DirectExchange exchange, String routingKey) {
this.queue = queue.getName();
this.exchange = exchange.getName();
this.routingKey = routingKey;
}
public Binding(Queue queue, DirectExchange exchange) {
this.queue = queue.getName();
this.exchange = exchange.getName();
this.routingKey = "";
}
public Binding(Queue queue, TopicExchange exchange, String routingKey) {
this.queue = queue.getName();
this.exchange = exchange.getName();
this.routingKey = routingKey;
}
public Binding(Queue queue, TopicExchange exchange) {
this.queue = queue.getName();
this.exchange = exchange.getName();
this.routingKey = "";
}
public String getQueue() {
return queue;
}
public String getExchange() {
return exchange;
}
public String getRoutingKey() {
return routingKey;
}
public Map<java.lang.String, java.lang.Object> getArguments() {
return arguments;
}
public void setArguments(Map<java.lang.String, java.lang.Object> arguments) {
this.arguments = arguments;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
/**
* Basic builder class to create bindings for a more fluent API style in code based configuration.
*
* @author Mark Pollack
* @author Mark Fisher
*/
public final class BindingBuilder {
private Queue queue;
private AbstractExchange exchange;
private String routingKey;
//return intermediate object that only allows to call 'to' to configure the binding.
public static BindingBuilder from(Queue queue) {
return new BindingBuilder(queue);
}
private BindingBuilder(Queue queue) {
super();
this.queue = queue;
}
//return intermediate object that only allows to call 'with' to configure the binding.
public BindingBuilder to(AbstractExchange exchange) {
this.exchange = exchange;
return this;
}
// creates the product.
public Binding with(String routingKey) {
this.routingKey = routingKey;
return new Binding(this.queue, this.exchange, this.routingKey);
}
public Binding with(Enum routingKeyEnum) {
this.routingKey = routingKeyEnum.toString();
return new Binding(this.queue, this.exchange, this.routingKey);
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
/**
* Simple container collecting information to describe a direct exchange.
* Used in conjunction with RabbitAdminTemplate.
*
* @author Mark Pollack
* @see RabbitAdminTemplate
*/
public class DirectExchange extends AbstractExchange {
public static final DirectExchange DEFAULT = new DirectExchange("");
public DirectExchange(String name) {
this.name = name;
}
public ExchangeType getExchangeType() {
return ExchangeType.direct;
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
/**
* Enumeration of exchange types.
* TODO consider 'header' type?
*
* @author Mark Pollack
*
*/
public enum ExchangeType {
fanout(), direct(), topic()
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
/**
* Simple container collecting information to describe a fanout exchange.
* Used in conjunction with RabbitAdminTemplate.
*
* @author Mark Pollack
* @see RabbitAdminTemplate
*/
public class FanoutExchange extends AbstractExchange {
public FanoutExchange(String name) {
this.name = name;
}
public ExchangeType getExchangeType() {
return ExchangeType.fanout;
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import org.springframework.amqp.utils.SerializationUtils;
/**
* @author Mark Pollack
* @author Mark Fisher
* @author Oleg Zhurakousky
*/
public class Message {
private final MessageProperties messageProperties;
private final byte[] body;
public Message(byte[] body, MessageProperties messageProperties) {
this.body = body;
this.messageProperties = messageProperties;
}
public byte[] getBody() {
return this.body;
}
public MessageProperties getMessageProperties() {
return this.messageProperties;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("(");
buffer.append("Body:'" + this.getBodyContentAsString() + "';");
buffer.append("ID:" + messageProperties.getMessageId() + ";");
buffer.append("Content:" + messageProperties.getContentType() + ";");
buffer.append("Headers:" + messageProperties.getHeaders() + ";");
buffer.append("Exchange:" + messageProperties.getReceivedExchange() + ";");
buffer.append("Routing key:" + messageProperties.getReceivedRoutingKey() + ";");
buffer.append("Reply:" + messageProperties.getReplyTo() + ";");
buffer.append("Delivery mode:" + messageProperties.getDeliveryMode() + ";");
buffer.append(")");
return buffer.toString();
}
private String getBodyContentAsString() {
String contentType = messageProperties.getContentType();
if (contentType.equals(MessageProperties.CONTENT_TYPE_SERIALIZED_OBJECT)) {
return (String) SerializationUtils.deserialize(body);
}
else if (contentType.equals(MessageProperties.CONTENT_TYPE_BYTES)) {
return body.toString();
}
else if (contentType.equals(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)) {
return new String(body);
}
else if (contentType.equals(MessageProperties.CONTENT_TYPE_JSON)) {
//TODO provide JSON conversion to string
return body.toString();
}
return null;
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
/**
* Strategy interface for creating RabbitMQ messages.
*
* @author Mark Fisher
*/
public interface MessageCreator {
/**
* Create a {@link Message} to be sent.
*/
Message createMessage();
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
/**
* Enumeration for the message delivery mode. Can be persistent or
* non persistent. Use the method 'toInt' to get the appropriate value
* that is used the he AMQP protocol instead of the ordinal() value when
* passing into AMQP APIs.
*
* @author Mark Pollack
*
*/
public enum MessageDeliveryMode {
NON_PERSISTENT, PERSISTENT;
public static int toInt(MessageDeliveryMode mode) {
switch (mode) {
case NON_PERSISTENT: {
return 1;
}
case PERSISTENT: {
return 2;
}
default: {
return -1;
}
}
}
public static MessageDeliveryMode fromInt(int modeAsNumber) {
switch (modeAsNumber) {
case 1: {
return NON_PERSISTENT;
}
case 2: {
return PERSISTENT;
}
default: {
return null;
}
}
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
/**
* Listener interface to receive asynchronous delivery of Amqp Messages.
*
* @author Mark Pollack
*/
public interface MessageListener {
void onMessage(Message message);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import org.springframework.amqp.AmqpException;
/**
* To be used with the send method of Amqp template classes (such as RabbitTemplate)
* that convert an object to a message.
* It allows for further modification of the message after it has been processed
* by the converter. This is useful for setting of Header and Properties.
*
* <p>This often as an anonymous class within a method implementation.
* @author Mark Pollack
*/
public interface MessagePostProcessor {
Message postProcessMessage(Message message) throws AmqpException;
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import java.util.Date;
import java.util.Map;
/**
* Message Properties for an AMQP message.
*
* @author Mark Fisher
* @author Mark Pollack
*
*/
public interface MessageProperties {
public static final String CONTENT_TYPE_BYTES = "application/octet-stream";
public static final String CONTENT_TYPE_TEXT_PLAIN = "text/plain";
public static final String CONTENT_TYPE_SERIALIZED_OBJECT = "application/x-java-serialized-object";
public static final String CONTENT_TYPE_JSON = "application/json";
public abstract Map<String, Object> getHeaders();
public abstract void setHeader(String key, Object value);
//NOTE qpid java timestamp is long, presumably can convert to Date.
public abstract Date getTimestamp();
public abstract void setAppId(String appId);
public abstract String getAppId();
public abstract void setUserId(String userId);
//NOTE Note forward compatible with qpid 1.0 .NET
// qpid 0.8 .NET/java: is a string
// qpid 1.0 .NET: getUserId is byte[]
public abstract String getUserId();
public abstract void setType(String type);
//TODO what is this? is it stuctureType - int in qpid
public abstract String getType();
//NOTE Not forward compatible with qpid 1.0 .NET
// qpid 0.8 .NET/Java: is a string
// qpid 1.0 .NET: MessageId property on class MessageProperties and is UUID
// There is an 'ID' stored IMessage class and is an int.
public abstract void setMessageId(String id);
public abstract String getMessageId();
//NOTE not foward compatible with qpid 1.0 .NET
// qpid 0.8 .NET/Java: is a string
// qpid 1.0 .NET: is not present
public abstract void setClusterId(String id);
public abstract String getClusterId();
public abstract void setCorrelationId(byte[] correlationId);
public abstract byte[] getCorrelationId();
public abstract void setReplyTo(Address replyTo);
//TODO - create Address/ReplyTo class to encapsulate exchangType/exchange/routingkey ?
// qpid 0.8/1.0 .NET don't use a single string, but a pair.
// qpid 0.8 Java uses a single string
//
// See RabbitMQ .NET developer guide for more details on conventions for this string
public abstract Address getReplyTo();
public abstract void setContentType(String contentType);
public abstract String getContentType();
public abstract void setContentEncoding(String contentEncoding);
public abstract String getContentEncoding();
public abstract void setContentLength(long contentLength);
public abstract long getContentLength();
public abstract void setDefaultCharset(String charSet);
public abstract void setDeliveryMode(MessageDeliveryMode deliveryMode);
public abstract MessageDeliveryMode getDeliveryMode();
public abstract void setExpiration(String expiration);
//NOTE qpid Java broker qpid 0.8/1.0 .NET: is a long.
// 0.8 Spec has: expiration (shortstr)
public abstract String getExpiration();
public abstract void setPriority(Integer priority);
public abstract Integer getPriority();
public abstract String getReceivedExchange();
public abstract String getReceivedRoutingKey();
public abstract Boolean isRedelivered();
public abstract long getDeliveryTag();
public abstract Integer getMessageCount();
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
/**
* Simple container collecting information to describe a queue.
* Used in conjunction with RabbitAdminTemplate.
*
* @author Mark Pollack
* @see RabbitAdminTemplate
*/
public class Queue {
private String name;
private boolean passive;
private boolean durable;
private boolean exclusive;
private boolean autoDelete;
private java.util.Map<java.lang.String,java.lang.Object> arguments;
public Queue(String name) {
this.name = name;
}
public String getName() {
return name;
}
public boolean isPassive() {
return passive;
}
public void setPassive(boolean passive) {
this.passive = passive;
}
public boolean isDurable() {
return durable;
}
public void setDurable(boolean durable) {
this.durable = durable;
}
public boolean isExclusive() {
return exclusive;
}
public void setExclusive(boolean exclusive) {
this.exclusive = exclusive;
}
public boolean isAutoDelete() {
return autoDelete;
}
public void setAutoDelete(boolean autoDelete) {
this.autoDelete = autoDelete;
}
public java.util.Map<java.lang.String, java.lang.Object> getArguments() {
return arguments;
}
public void setArguments(
java.util.Map<java.lang.String, java.lang.Object> arguments) {
this.arguments = arguments;
}
}

View File

@@ -0,0 +1,242 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author Mark Fisher
*/
public class SimpleMessageProperties implements MessageProperties {
private static final String DEFAULT_CHARSET = "UTF-8";
private volatile String defaultCharset = DEFAULT_CHARSET;
private volatile String appId;
private volatile String clusterId;
private volatile String contentEncoding;
private volatile long contentLength;
private volatile String contentType = MessageProperties.CONTENT_TYPE_BYTES;
private volatile byte[] correlationId;
private volatile MessageDeliveryMode deliveryMode;
private volatile long deliveryTag;
private volatile String expiration;
private volatile Map<String, Object> headers = new HashMap<String, Object>();
private volatile Integer messageCount;
private volatile String messageId;
private volatile Integer priority;
private volatile String receivedExchange;
private volatile String receivedRoutingKey;
private volatile Address replyTo;
private volatile Date timestamp;
private volatile String type;
private volatile String userId;
private volatile Boolean redelivered;
public String getAppId() {
return this.appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getClusterId() {
return this.clusterId;
}
public void setClusterId(String clusterId) {
this.clusterId = clusterId;
}
public String getContentEncoding() {
return this.contentEncoding;
}
public void setContentEncoding(String contentEncoding) {
this.contentEncoding = contentEncoding;
}
public long getContentLength() {
return this.contentLength;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
public String getContentType() {
return this.contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public byte[] getCorrelationId() {
return this.correlationId;
}
public void setCorrelationId(byte[] correlationId) {
this.correlationId = correlationId;
}
public MessageDeliveryMode getDeliveryMode() {
return this.deliveryMode;
}
public void setDeliveryMode(MessageDeliveryMode deliveryMode) {
this.deliveryMode = deliveryMode;
}
public long getDeliveryTag() {
return this.deliveryTag;
}
public void setDeliveryTag(long deliveryTag) {
this.deliveryTag = deliveryTag;
}
public String getExpiration() {
return this.expiration;
}
public void setExpiration(String expiration) {
this.expiration = expiration;
}
public Map<String, Object> getHeaders() {
return this.headers;
}
public void setHeaders(Map<String, Object> headers) {
this.headers = headers;
}
public Integer getMessageCount() {
return this.messageCount;
}
public void setMessageCount(Integer messageCount) {
this.messageCount = messageCount;
}
public String getMessageId() {
return this.messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public Integer getPriority() {
return this.priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
public String getReceivedExchange() {
return this.receivedExchange;
}
public void setReceivedExchange(String receivedExchange) {
this.receivedExchange = receivedExchange;
}
public String getReceivedRoutingKey() {
return this.receivedRoutingKey;
}
public void setReceivedRoutingKey(String receivedRoutingKey) {
this.receivedRoutingKey = receivedRoutingKey;
}
public Address getReplyTo() {
return this.replyTo;
}
public void setReplyTo(Address replyTo) {
this.replyTo = replyTo;
}
public Date getTimestamp() {
return this.timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public String getUserId() {
return this.userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Boolean isRedelivered() {
return this.redelivered;
}
public void setRedelivered(Boolean redelivered) {
this.redelivered = redelivered;
}
public void setDefaultCharset(String defaultCharset) {
this.defaultCharset = defaultCharset;
}
public void setHeader(String key, Object value) {
this.headers.put(key, value);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
/**
* Simple container collecting information to describe a topic exchange.
* Used in conjunction with RabbitAdminTemplate.
*
* @author Mark Pollack
* @see RabbitAdminTemplate
*/
public class TopicExchange extends AbstractExchange {
public TopicExchange(String name) {
this.name = name;
}
public ExchangeType getExchangeType() {
return ExchangeType.topic;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import java.util.UUID;
/**
* Create a queue with a unique name.
*
* @author Mark Pollack
*
*/
public class UniquelyNamedQueue extends Queue {
/**
* Create a uniquely named queue. The name of the queue is a random UUID.
*/
public UniquelyNamedQueue() {
super(UUID.randomUUID().toString());
}
/**
* Create a uniquely named queue with a fixed prefix. The constructor argument specifies
* the prefix which is prepended to a random UUID.
* @param prefix
*/
public UniquelyNamedQueue(String prefix) {
super(prefix + "-" + UUID.randomUUID());
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
/**
* Strategy for setting metadata on messages such that one can create the class that needs to
* be instantiated when receiving a message.
*
* @author Mark Pollack
*
*/
public interface ClassMapper {
String getClassIdFieldName();
String fromClass(Class clazz);
Class toClass(String classId);
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.ClassUtils;
/**
*
* @author Mark Pollack
*
*/
public class DefaultClassMapper implements ClassMapper, InitializingBean {
public static final String DEFAULT_CLASSID_FIELD_NAME = "__TypeId__";
private Map<String, Class> idClassMapping = new HashMap<String, Class>();
private Map<Class, String> classIdMapping = new HashMap<Class, String>();
private String defaultHashtableTypeId = "Hashtable";
private Class defaultHashtableClass = Hashtable.class;
public void setDefaultHashtableClass(Class defaultHashtableClass) {
this.defaultHashtableClass = defaultHashtableClass;
}
public String getClassIdFieldName() {
return DEFAULT_CLASSID_FIELD_NAME;
}
public void setIdClassMapping(Map<String, Class> idClassMapping) {
this.idClassMapping = idClassMapping;
}
public String fromClass(Class classOfObjectToConvert) {
if (classIdMapping.containsKey(classOfObjectToConvert)) {
return classIdMapping.get(classOfObjectToConvert);
}
if (Map.class.isAssignableFrom(classOfObjectToConvert))
{
return this.defaultHashtableTypeId;
}
return classOfObjectToConvert.getName();
}
public Class toClass(String classId) {
if (this.idClassMapping.containsKey(classId)) {
return idClassMapping.get(classId);
}
if (classId.equals(this.defaultHashtableTypeId))
{
return this.defaultHashtableClass;
}
try {
return ClassUtils.forName(classId, getClass().getClassLoader());
} catch (ClassNotFoundException e) {
throw new MessageConversionException("failed to resolve class name [" + classId + "]", e);
} catch (LinkageError e) {
throw new MessageConversionException("failed to resolve class name [" + classId + "]", e);
}
}
public void afterPropertiesSet() throws Exception {
validateIdTypeMapping();
}
private void validateIdTypeMapping() {
Map<String, Class> finalIdClassMapping = new HashMap<String, Class>();
for (Entry<String, Class> entry : idClassMapping.entrySet()) {
String id = entry.getKey();
Class clazz = entry.getValue();
finalIdClassMapping.put(id, clazz);
classIdMapping.put(clazz, id);
}
this.idClassMapping = finalIdClassMapping;
}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
/**
* JSON converter that uses the Jackson Json library.
*
* @author Mark Pollack
*/
public class JsonMessageConverter implements MessageConverter {
// TODO create composite MessageConverter with key/value pairs of content-type/converter. introduce base class
private static Log log = LogFactory.getLog(JsonMessageConverter.class);
public static final String DEFAULT_CHARSET = "UTF-8";
private volatile String defaultCharset = DEFAULT_CHARSET;
private ObjectMapper jsonObjectMapper = new ObjectMapper();
private ClassMapper classMapper = new DefaultClassMapper();
public JsonMessageConverter() {
super();
initializeJsonObjectMapper();
}
/**
* Specify the default charset to use when converting to or from text-based
* Message body content. If not specified, the charset will be "UTF-8".
*/
public void setDefaultCharset(String defaultCharset) {
this.defaultCharset = (defaultCharset != null) ? defaultCharset : DEFAULT_CHARSET;
}
public ClassMapper getClassMapper() {
return classMapper;
}
public void setClassMapper(ClassMapper classMapper) {
this.classMapper = classMapper;
}
/**
* Subclass and override to customize.
*/
protected void initializeJsonObjectMapper() {
jsonObjectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public Object fromMessage(Message message) throws MessageConversionException {
Object content = null;
MessageProperties properties = message.getMessageProperties();
if (properties != null) {
String contentType = properties.getContentType();
if (contentType != null && contentType.contains("json")) {
String encoding = properties.getContentEncoding();
if (encoding == null) {
encoding = this.defaultCharset;
}
try {
//content = new String(message.getBody(), encoding);
Map<String, Object> headers = message.getMessageProperties().getHeaders();
Object classIdFieldNameValue = headers.get(classMapper.getClassIdFieldName());
String classId = null;
if (classIdFieldNameValue != null) {
classId = classIdFieldNameValue.toString();
}
if (classId == null) {
throw new MessageConversionException(
"failed to convert json-based Message content. Could not resolve classId in header");
}
Class<?> targetClass = classMapper.toClass(classId);
content = convertBytesToObject(message.getBody(), encoding, targetClass);
}
catch (UnsupportedEncodingException e) {
throw new MessageConversionException("Failed to convert json-based Message content", e);
}
catch (JsonParseException e) {
throw new MessageConversionException("Failed to convert Message content", e);
}
catch (JsonMappingException e) {
throw new MessageConversionException("Failed to convert Message content", e);
}
catch (IOException e) {
throw new MessageConversionException("Failed to convert Message content", e);
}
}
else {
log.warn("Could not convert incoming message with content-type [" + contentType + "]");
}
}
if (content == null) {
content = message.getBody();
}
return content;
}
private Object convertBytesToObject(byte[] body, String encoding, Class<?> targetClass) throws JsonParseException, JsonMappingException, IOException {
String contentAsString = new String(body, encoding);
return jsonObjectMapper.readValue(contentAsString, targetClass);
}
public Message toMessage(Object objectToConvert, MessageProperties messageProperties) throws MessageConversionException {
byte[] bytes = null;
try {
String jsonString = jsonObjectMapper.writeValueAsString(objectToConvert);
bytes = jsonString.getBytes(this.defaultCharset);
}
catch (UnsupportedEncodingException e) {
throw new MessageConversionException("Failed to convert Message content", e);
}
catch (JsonGenerationException e) {
throw new MessageConversionException("Failed to convert Message content", e);
}
catch (JsonMappingException e) {
throw new MessageConversionException("Failed to convert Message content", e);
}
catch (IOException e) {
throw new MessageConversionException("Failed to convert Message content", e);
}
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
messageProperties.setContentEncoding(this.defaultCharset);
if (bytes != null) {
messageProperties.setContentLength(bytes.length);
}
Map<String, Object> headers = messageProperties.getHeaders();
headers.put(classMapper.getClassIdFieldName(), classMapper.fromClass(objectToConvert.getClass()));
return new Message(bytes, messageProperties);
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.XmlMappingException;
import org.springframework.util.Assert;
/**
* Spring Rabbit {@link MessageConverter} that uses a {@link Marshaller} and {@link Unmarshaller}.
* Marshals an object to a {@link Message} and unmarshals a {@link Message} to an object.
*
* @author Mark Fisher
* @author Arjen Poutsma
* @author Juergen Hoeller
* @see org.springframework.amqp.rabbit.core.RabbitTemplate#convertAndSend
* @see org.springframework.amqp.rabbit.core.RabbitTemplate#receiveAndConvert
*/
public class MarshallingMessageConverter implements MessageConverter, InitializingBean {
private Marshaller marshaller;
private Unmarshaller unmarshaller;
/**
* Construct a new <code>MarshallingMessageConverter</code> with no {@link Marshaller} or {@link Unmarshaller} set.
* The marshaller must be set after construction by invoking {@link #setMarshaller(Marshaller)} and
* {@link #setUnmarshaller(Unmarshaller)} .
*/
public MarshallingMessageConverter() {
}
/**
* Construct a new <code>MarshallingMessageConverter</code> with the given {@link Marshaller} set.
* <p>If the given {@link Marshaller} also implements the {@link Unmarshaller} interface,
* it is used for both marshalling and unmarshalling. Otherwise, an exception is thrown.
* <p>Note that all {@link Marshaller} implementations in Spring also implement the
* {@link Unmarshaller} interface, so that you can safely use this constructor.
* @param marshaller object used as marshaller and unmarshaller
* @throws IllegalArgumentException when <code>marshaller</code> does not implement the
* {@link Unmarshaller} interface as well
*/
public MarshallingMessageConverter(Marshaller marshaller) {
Assert.notNull(marshaller, "marshaller must not be null");
if (!(marshaller instanceof Unmarshaller)) {
throw new IllegalArgumentException(
"Marshaller [" + marshaller + "] does not implement the Unmarshaller " +
"interface. Please set an Unmarshaller explicitly by using the " +
"MarshallingMessageConverter(Marshaller, Unmarshaller) constructor.");
}
else {
this.marshaller = marshaller;
this.unmarshaller = (Unmarshaller) marshaller;
}
}
/**
* Construct a new <code>MarshallingMessageConverter</code> with the
* given Marshaller and Unmarshaller.
* @param marshaller the Marshaller to use
* @param unmarshaller the Unmarshaller to use
*/
public MarshallingMessageConverter(Marshaller marshaller, Unmarshaller unmarshaller) {
Assert.notNull(marshaller, "marshaller must not be null");
Assert.notNull(unmarshaller, "unmarshaller must not be null");
this.marshaller = marshaller;
this.unmarshaller = unmarshaller;
}
/**
* Set the {@link Marshaller} to be used by this message converter.
*/
public void setMarshaller(Marshaller marshaller) {
this.marshaller = marshaller;
}
/**
* Set the {@link Unmarshaller} to be used by this message converter.
*/
public void setUnmarshaller(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller;
}
public void afterPropertiesSet() {
Assert.notNull(this.marshaller, "Property 'marshaller' is required");
Assert.notNull(this.unmarshaller, "Property 'unmarshaller' is required");
}
/**
* Marshals the given object to a {@link Message}.
*/
public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
StreamResult streamResult = new StreamResult(bos);
marshaller.marshal(object, streamResult);
return new Message(bos.toByteArray(), messageProperties);
}
catch (XmlMappingException ex) {
throw new MessageConversionException("Could not marshal [" + object + "]", ex);
}
catch (IOException ex) {
throw new MessageConversionException("Could not marshal [" + object + "]", ex);
}
}
/**
* Unmarshals the given {@link Message} into an object.
*/
public Object fromMessage(Message message) throws MessageConversionException {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(message.getBody());
StreamSource source = new StreamSource(bis);
return unmarshaller.unmarshal(source);
}
catch (IOException ex) {
throw new MessageConversionException("Could not access message content: " + message, ex);
}
catch (XmlMappingException ex) {
throw new MessageConversionException("Could not unmarshal message: " + message, ex);
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
import org.springframework.amqp.AmqpException;
/**
* @author Mark Fisher
*/
public class MessageConversionException extends AmqpException {
public MessageConversionException(String message, Throwable cause) {
super(message, cause);
}
public MessageConversionException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
/**
* @author Mark Fisher
* @author Mark Pollack
*/
public interface MessageConverter {
/**
* Convert a Java object to a Rabbit Message.
* @param object the object to convert
* @return the Rabbit Message
* @throws MessageConversionException in case of conversion failure
*/
Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException;
/**
* Convert from a Rabbit GetResponse to a Java object.
* @param message the message to convert
* @return the converted Java object
* @throws MessageConversionException in case of conversion failure
*/
Object fromMessage(Message message) throws MessageConversionException;
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.utils.SerializationUtils;
/**
* Implementation of {@link MessageConverter} that can work with Strings, Serializable instances,
* or byte arrays. The {@link #toMessage(Object)} method simply checks the type of the provided
* instance while the {@link #fromMessage(Message)} method relies upon the
* {@link DefaultMessageProperties#getContentType() content-type} of the provided Message.
*
* @author Mark Fisher
* @author Oleg Zhurakousky
*/
public class SimpleMessageConverter implements MessageConverter {
public static final String DEFAULT_CHARSET = "UTF-8";
private volatile String defaultCharset = DEFAULT_CHARSET;
/**
* Specify the default charset to use when converting to or from text-based
* Message body content. If not specified, the charset will be "UTF-8".
*/
public void setDefaultCharset(String defaultCharset) {
this.defaultCharset = (defaultCharset != null) ? defaultCharset : DEFAULT_CHARSET;
}
/**
* Converts from a Rabbit Message to an Object.
*/
public Object fromMessage(Message message) throws MessageConversionException {
Object content = null;
MessageProperties properties = message.getMessageProperties();
if (properties != null) {
String contentType = properties.getContentType();
if (contentType != null && contentType.startsWith("text")) {
String encoding = properties.getContentEncoding();
if (encoding == null) {
encoding = this.defaultCharset;
}
try {
content = new String(message.getBody(), encoding);
}
catch (UnsupportedEncodingException e) {
throw new MessageConversionException(
"failed to convert text-based Message content", e);
}
}
else if (contentType != null &&
contentType.equals(MessageProperties.CONTENT_TYPE_SERIALIZED_OBJECT)) {
content = SerializationUtils.deserialize(message.getBody());
}
}
if (content == null) {
content = message.getBody();
}
return content;
}
/**
* Creates a Rabbit Mesasge from the provided Object.
*/
public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
byte[] bytes = null;
if (object instanceof byte[]) {
bytes = (byte[]) object;
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_BYTES);
}
else if (object instanceof String) {
try {
bytes = ((String) object).getBytes(this.defaultCharset);
}
catch (UnsupportedEncodingException e) {
throw new MessageConversionException(
"failed to convert Message content", e);
}
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
messageProperties.setContentEncoding(this.defaultCharset);
}
else if (object instanceof Serializable) {
bytes = SerializationUtils.serialize((Serializable) object);
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_SERIALIZED_OBJECT);
}
if (bytes != null) {
messageProperties.setContentLength(bytes.length);
}
return new Message(bytes, messageProperties);
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2006-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* Static utility to help with serialization.
*
* @author Dave Syer
*/
public class SerializationUtils {
/**
* Serialize the object provided.
*
* @param object the object to serialize
* @return an array of bytes representing the object in a portable fashion
*/
public static byte[] serialize(Object object) {
if (object == null) {
return null;
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
new ObjectOutputStream(stream).writeObject(object);
}
catch (IOException e) {
throw new IllegalArgumentException("Could not serialize object of type: " + object.getClass(), e);
}
return stream.toByteArray();
}
/**
* @param bytes a serialized object created
* @return the result of deserializing the bytes
*/
public static Object deserialize(byte[] bytes) {
if (bytes == null) {
return null;
}
try {
return new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject();
}
catch (IOException e) {
throw new IllegalArgumentException("Could not deserialize object", e);
}
catch (ClassNotFoundException e) {
throw new IllegalStateException("Could not deserialize object type", e);
}
}
}

View File

@@ -0,0 +1,8 @@
Many of the "integration" tests here require a running RabbitMQ server.
If RabbitMQ is not installed on your system, refer to the instructions for your
particular OS here: http://www.rabbitmq.com/install.html
Start the server. For example, and a *nix-based system where RabbitMQ has been
installed within /opt/rabbitmq, issue the following command:
> sudo /opt/rabbitmq/sbin/rabbitmq-server start

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import junit.framework.Assert;
import org.junit.Test;
/**
* @author Mark Pollack
*/
public class AddressTests {
@Test
public void parse() {
Address a = new Address(ExchangeType.direct, "my-exchange", "routing-key");
String replyToUri = "direct://my-exchange/routing-key";
Assert.assertEquals(replyToUri, a.toString());
Address b = Address.parse(replyToUri);
assertEquals(b.getExchangeType(), ExchangeType.direct);
assertEquals(b.getExchangeName(), "my-exchange");
assertEquals(b.getRoutingKey(), "routing-key");
assertTrue(b.isStructured());
b = Address.parse("my-exchange/routing-key");
assertFalse(b.isStructured());
assertEquals("my-exchange/routing-key", b.toString());
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
/**
* @author Mark Fisher
*/
public class MessageTests {
@Test
public void toStringForEmptyMessage() {
Message message = new Message(new byte[0], new TestMessageProperties());
assertNotNull(message.toString());
}
}

View File

@@ -0,0 +1,237 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.core;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author Mark Fisher
*/
public class TestMessageProperties implements MessageProperties {
private volatile String appId;
private volatile String clusterId;
private volatile String contentEncoding;
private volatile long contentLength;
private volatile String contentType = MessageProperties.CONTENT_TYPE_BYTES;
private volatile byte[] correlationId;
private volatile MessageDeliveryMode deliveryMode = MessageDeliveryMode.PERSISTENT;
private volatile long deliveryTag;
private volatile String expiration;
private volatile Map<String, Object> headers = new HashMap<String, Object>();
private volatile Integer messageCount;
private volatile String messageId;
private volatile Integer priority;
private volatile String receivedExchange;
private volatile String receivedRoutingKey;
private volatile Address replyTo;
private volatile Date timestamp;
private volatile String type;
private volatile String userId;
private volatile Boolean redelivered;
public String getAppId() {
return this.appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getClusterId() {
return this.clusterId;
}
public void setClusterId(String clusterId) {
this.clusterId = clusterId;
}
public String getContentEncoding() {
return this.contentEncoding;
}
public void setContentEncoding(String contentEncoding) {
this.contentEncoding = contentEncoding;
}
public long getContentLength() {
return this.contentLength;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
public String getContentType() {
return this.contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public byte[] getCorrelationId() {
return this.correlationId;
}
public void setCorrelationId(byte[] correlationId) {
this.correlationId = correlationId;
}
public MessageDeliveryMode getDeliveryMode() {
return this.deliveryMode;
}
public void setDeliveryMode(MessageDeliveryMode deliveryMode) {
this.deliveryMode = deliveryMode;
}
public long getDeliveryTag() {
return this.deliveryTag;
}
public void setDeliveryTag(long deliveryTag) {
this.deliveryTag = deliveryTag;
}
public String getExpiration() {
return this.expiration;
}
public void setExpiration(String expiration) {
this.expiration = expiration;
}
public Map<String, Object> getHeaders() {
return this.headers;
}
public void setHeaders(Map<String, Object> headers) {
this.headers = headers;
}
public Integer getMessageCount() {
return this.messageCount;
}
public void setMessageCount(Integer messageCount) {
this.messageCount = messageCount;
}
public String getMessageId() {
return this.messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public Integer getPriority() {
return this.priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
public String getReceivedExchange() {
return this.receivedExchange;
}
public void setReceivedExchange(String receivedExchange) {
this.receivedExchange = receivedExchange;
}
public String getReceivedRoutingKey() {
return this.receivedRoutingKey;
}
public void setReceivedRoutingKey(String receivedRoutingKey) {
this.receivedRoutingKey = receivedRoutingKey;
}
public Address getReplyTo() {
return this.replyTo;
}
public void setReplyTo(Address replyTo) {
this.replyTo = replyTo;
}
public Date getTimestamp() {
return this.timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public String getUserId() {
return this.userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Boolean isRedelivered() {
return this.redelivered;
}
public void setRedelivered(Boolean redelivered) {
this.redelivered = redelivered;
}
public void setHeader(String key, Object value) {
this.headers.put(key, value);
}
public void setDefaultCharset(String charSet) {
// TODO: where would this be used?
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
import static org.junit.Assert.assertEquals;
import java.math.BigDecimal;
import java.util.Hashtable;
import org.junit.Test;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.TestMessageProperties;
/**
* @author Mark Pollack
*/
public class JsonMessageConverterTests {
@Test
public void simpleTrade() {
SimpleTrade trade = new SimpleTrade();
trade.setAccountName("Acct1");
trade.setBuyRequest(true);
trade.setOrderType("Market");
trade.setPrice(new BigDecimal(103.30));
trade.setQuantity(100);
trade.setRequestId("R123");
trade.setTicker("VMW");
trade.setUserName("Joe Trader");
JsonMessageConverter converter = new JsonMessageConverter();
Message message = converter.toMessage(trade, new TestMessageProperties());
String classIdFieldName = converter.getClassMapper().getClassIdFieldName();
Object classIdHeaderObject = message.getMessageProperties().getHeaders().get(classIdFieldName);
assertEquals(String.class, classIdHeaderObject.getClass());
SimpleTrade marshalledTrade = (SimpleTrade) converter.fromMessage(message);
assertEquals(trade, marshalledTrade);
}
@Test
@SuppressWarnings("unchecked")
public void hashtable() {
Hashtable<String, String> hashtable = new Hashtable<String, String>();
hashtable.put("TICKER", "VMW");
hashtable.put("PRICE", "103.2");
JsonMessageConverter converter = new JsonMessageConverter();
Message message = converter.toMessage(hashtable, new TestMessageProperties());
Hashtable<String, String> marhsalledHashtable = (Hashtable<String, String>) converter.fromMessage(message);
assertEquals("VMW", marhsalledHashtable.get("TICKER"));
assertEquals("103.2", marhsalledHashtable.get("PRICE"));
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.junit.Test;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.TestMessageProperties;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.XmlMappingException;
/**
* @author Mark Fisher
*/
public class MarshallingMessageConverterTests {
@Test
public void marshal() throws Exception {
TestMarshaller marshaller = new TestMarshaller();
MarshallingMessageConverter converter = new MarshallingMessageConverter(marshaller);
converter.afterPropertiesSet();
Message message = converter.toMessage("marshal test", new TestMessageProperties());
String response = new String(message.getBody(), "UTF-8");
assertEquals("MARSHAL TEST", response);
}
@Test
public void unmarshal() {
TestMarshaller marshaller = new TestMarshaller();
MarshallingMessageConverter converter = new MarshallingMessageConverter(marshaller);
converter.afterPropertiesSet();
Message message = new Message("UNMARSHAL TEST".getBytes(), new TestMessageProperties());
Object result = converter.fromMessage(message);
assertEquals("unmarshal test", (String) result);
}
private static class TestMarshaller implements Marshaller, Unmarshaller {
public boolean supports(Class<?> clazz) {
return true;
}
public void marshal(Object graph, Result result) throws IOException, XmlMappingException {
String response = ((String) graph).toUpperCase();
((StreamResult) result).getOutputStream().write(response.getBytes());
}
public Object unmarshal(Source source) throws IOException, XmlMappingException {
byte[] buffer = new byte["UNMARSHAL TEST".length()];
((StreamSource) source).getInputStream().read(buffer);
return new String(buffer, "UTF-8").toLowerCase();
}
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.support.converter;
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import org.junit.Test;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.TestMessageProperties;
import org.springframework.util.Assert;
/**
* @author Mark Fisher
*/
public class SimpleMessageConverterTests {
@Test
public void bytesAsDefaultMessageBodyType() throws Exception {
SimpleMessageConverter converter = new SimpleMessageConverter();
Message message = new Message("test".getBytes(), new TestMessageProperties());
Object result = converter.fromMessage(message);
assertEquals(byte[].class, result.getClass());
assertEquals("test", new String((byte[]) result, "UTF-8"));
}
@Test
public void messageToString() {
SimpleMessageConverter converter = new SimpleMessageConverter();
Message message = new Message("test".getBytes(), new TestMessageProperties());
message.getMessageProperties().setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
Object result = converter.fromMessage(message);
assertEquals(String.class, result.getClass());
assertEquals("test", result);
}
@Test
public void messageToBytes() {
SimpleMessageConverter converter = new SimpleMessageConverter();
Message message = new Message(new byte[] { 1, 2, 3 }, new TestMessageProperties());
message.getMessageProperties().setContentType(MessageProperties.CONTENT_TYPE_BYTES);
Object result = converter.fromMessage(message);
assertEquals(byte[].class, result.getClass());
byte[] resultBytes = (byte[]) result;
assertEquals(3, resultBytes.length);
assertEquals(1, resultBytes[0]);
assertEquals(2, resultBytes[1]);
assertEquals(3, resultBytes[2]);
}
@Test
public void messageToSerializedObject() throws Exception {
SimpleMessageConverter converter = new SimpleMessageConverter();
MessageProperties properties = new TestMessageProperties();
properties.setContentType(MessageProperties.CONTENT_TYPE_SERIALIZED_OBJECT);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
ObjectOutputStream objectStream = new ObjectOutputStream(byteStream);
TestBean testBean = new TestBean("foo");
objectStream.writeObject(testBean);
objectStream.flush();
objectStream.close();
byte[] bytes = byteStream.toByteArray();
Message message = new Message(bytes, properties);
Object result = converter.fromMessage(message);
assertEquals(TestBean.class, result.getClass());
assertEquals(testBean, result);
}
@Test
public void stringToMessage() throws Exception {
SimpleMessageConverter converter = new SimpleMessageConverter();
Message message = converter.toMessage("test", new TestMessageProperties());
String contentType = message.getMessageProperties().getContentType();
String content = new String(message.getBody(),
message.getMessageProperties().getContentEncoding());
assertEquals("text/plain", contentType);
assertEquals("test", content);
}
@Test
public void bytesToMessage() throws Exception {
SimpleMessageConverter converter = new SimpleMessageConverter();
Message message = converter.toMessage(new byte[] { 1, 2, 3 }, new TestMessageProperties());
String contentType = message.getMessageProperties().getContentType();
byte[] body = message.getBody();
assertEquals("application/octet-stream", contentType);
assertEquals(3, body.length);
assertEquals(1, body[0]);
assertEquals(2, body[1]);
assertEquals(3, body[2]);
}
@Test
public void serializedObjectToMessage() throws Exception {
SimpleMessageConverter converter = new SimpleMessageConverter();
TestBean testBean = new TestBean("foo");
Message message = converter.toMessage(testBean, new TestMessageProperties());
String contentType = message.getMessageProperties().getContentType();
byte[] body = message.getBody();
assertEquals("application/x-java-serialized-object", contentType);
ByteArrayInputStream bais = new ByteArrayInputStream(body);
Object deserializedObject = new ObjectInputStream(bais).readObject();
assertEquals(testBean, deserializedObject);
}
@SuppressWarnings("serial")
private static class TestBean implements Serializable {
private final String text;
TestBean(String text) {
Assert.notNull(text, "text must not be null");
this.text = text;
}
public boolean equals(Object other) {
return (other instanceof TestBean && this.text.equals(((TestBean) other).text));
}
public int hashCode() {
return this.text.hashCode();
}
}
}

View File

@@ -0,0 +1,153 @@
package org.springframework.amqp.support.converter;
import java.math.BigDecimal;
public class SimpleTrade {
private String ticker;
private long quantity;
private BigDecimal price;
private String orderType;
private String accountName;
private boolean buyRequest;
private String userName;
private String requestId;
public String getTicker() {
return ticker;
}
public void setTicker(String ticker) {
this.ticker = ticker;
}
public long getQuantity() {
return quantity;
}
public void setQuantity(long quantity) {
this.quantity = quantity;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getOrderType() {
return orderType;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public boolean isBuyRequest() {
return buyRequest;
}
public void setBuyRequest(boolean buyRequest) {
this.buyRequest = buyRequest;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((accountName == null) ? 0 : accountName.hashCode());
result = prime * result + (buyRequest ? 1231 : 1237);
result = prime * result
+ ((orderType == null) ? 0 : orderType.hashCode());
result = prime * result + ((price == null) ? 0 : price.hashCode());
result = prime * result + (int) (quantity ^ (quantity >>> 32));
result = prime * result
+ ((requestId == null) ? 0 : requestId.hashCode());
result = prime * result + ((ticker == null) ? 0 : ticker.hashCode());
result = prime * result
+ ((userName == null) ? 0 : userName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SimpleTrade other = (SimpleTrade) obj;
if (accountName == null) {
if (other.accountName != null)
return false;
} else if (!accountName.equals(other.accountName))
return false;
if (buyRequest != other.buyRequest)
return false;
if (orderType == null) {
if (other.orderType != null)
return false;
} else if (!orderType.equals(other.orderType))
return false;
if (price == null) {
if (other.price != null)
return false;
} else if (!price.equals(other.price))
return false;
if (quantity != other.quantity)
return false;
if (requestId == null) {
if (other.requestId != null)
return false;
} else if (!requestId.equals(other.requestId))
return false;
if (ticker == null) {
if (other.ticker != null)
return false;
} else if (!ticker.equals(other.ticker))
return false;
if (userName == null) {
if (other.userName != null)
return false;
} else if (!userName.equals(other.userName))
return false;
return true;
}
}

View File

@@ -0,0 +1,9 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.category.org.springframework.amqp=DEBUG
log4j.category.org.springframework.beans.factory=INFO

View File

@@ -0,0 +1,10 @@
Bundle-SymbolicName: org.springframework.amqp
Bundle-Name: Spring AMQP Core
Bundle-Vendor: SpringSource
Bundle-ManifestVersion: 2
Import-Template:
org.springframework.*;version="[3.0.3, 4.0.0)",
org.apache.commons.logging;version="[1.1.1, 2.0.0)",
org.codehaus.jackson.*;version="[1.4.3, 2.0.0)";resolution:=optional,
org.w3c.dom.*;version="0",
javax.xml.*;version="0"

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-amqp-parent</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,9 @@
#Tue Jun 29 21:59:00 EDT 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

382
spring-amqp-parent/pom.xml Normal file
View File

@@ -0,0 +1,382 @@
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp-parent</artifactId>
<name>Spring AMQP Parent</name>
<url>http://www.springsource.org/spring-amqp</url>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- versions for commonly-used dependencies -->
<cglib.version>2.2</cglib.version>
<commons-io.version>1.4</commons-io.version>
<junit.version>4.7</junit.version>
<log4j.version>1.2.15</log4j.version>
<org.mockito.version>1.8.4</org.mockito.version>
<org.slf4j.version>1.5.10</org.slf4j.version>
<org.codehaus.jackson.version>1.4.3</org.codehaus.jackson.version>
<org.erlang.otp.version>1.5.3</org.erlang.otp.version>
<com.rabbitmq.version>1.7.2</com.rabbitmq.version>
<org.springframework.version>3.0.3.RELEASE</org.springframework.version>
</properties>
<profiles>
<profile>
<id>strict</id>
<properties>
<maven.test.failure.ignore>false</maven.test.failure.ignore>
</properties>
</profile>
<profile>
<id>fast</id>
<properties>
<maven.test.skip>true</maven.test.skip>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
</profile>
<profile>
<id>staging</id>
<distributionManagement>
<site>
<id>staging</id>
<url>file:///${java.io.tmpdir}/target/site</url>
</site>
<repository>
<id>staging</id>
<url>file:///${java.io.tmpdir}/target/repository</url>
</repository>
<snapshotRepository>
<id>staging</id>
<url>file:///${java.io.tmpdir}/target/snapshotRepository</url>
</snapshotRepository>
</distributionManagement>
</profile>
</profiles>
<distributionManagement>
<!-- see 'staging' profile for dry-run deployment settings -->
<downloadUrl>http://static.springframework.org/spring-amqp/site/downloads/releases.html</downloadUrl>
<repository>
<id>local</id>
<url>file://${java.io.tmpdir}/spring-amqp-repo</url>
</repository>
<snapshotRepository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>s3://maven.springframework.org/snapshot</url>
</snapshotRepository>
<site>
<id>static.springframework.org</id>
<url>scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-amqp/sites/${project.version}</url>
</site>
</distributionManagement>
<dependencyManagement><!--
inheritable <dependency> declarations for child poms. children still must
explicitly declare the groupId/artifactId of these dependencies in order
for them to show up on the classpath, but metadata like <version> and
<scope> are inherited, which cuts down on verbosity.
see http://www.sonatype.com/books/mvnref-book/reference/pom-relationships-sect-dep-manage.html -->
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>${com.rabbitmq.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-otp</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Other -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>${cglib.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>${org.mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>${org.codehaus.jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${org.codehaus.jackson.version}</version>
</dependency>
<dependency>
<groupId>org.erlang.otp</groupId>
<artifactId>jinterface</artifactId>
<version>${org.erlang.otp.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies><!--
dependency definitions to be inherited by child poms. any <dependency>
declarations here will automatically show up on child project classpaths.
only items that are truly common across all projects (modules and samples)
should go here. otherwise, consider <dependencyManagement> above -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<!-- available only in the springframework maven repository. see <repositories> section below -->
<groupId>org.springframework.build.aws</groupId>
<artifactId>org.springframework.build.aws.maven</artifactId>
<version>3.0.0.RELEASE</version>
</extension>
</extensions>
<resources>
<resource>
<directory>${project.basedir}/src/main/java</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/java</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>false</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useFile>false</useFile>
<includes>
<include>**/*Tests.java</include>
</includes>
<excludes>
<exclude>**/Abstract*.java</exclude>
</excludes>
<junitArtifactName>junit:junit</junitArtifactName>
</configuration>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin><!--
configures the springsource bundlor plugin, which generates OSGI-compatible MANIFEST.MF
files during the 'compile' phase of the maven build. this plugin is declared within
the pluginManagement section because not every module that inherits from this pom
needs bundlor's services, e.g.: spring-integration-samples and all its children. for this
reason, all modules that wish to use bundlor must declare it explicitly. it is not necessary
to specify the <version> or <configuration> sections, but groupId and artifactId are required.
see http://static.springsource.org/s2-bundlor/1.0.x/user-guide/html/ch04s03.html for more info -->
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
<version>1.0.0.RELEASE</version>
<configuration>
<failOnWarnings>true</failOnWarnings>
</configuration>
<executions>
<execution>
<id>bundlor</id>
<goals>
<goal>bundlor</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
<reporting>
<plugins>
<plugin><!--
significantly speeds up the 'Dependencies' report during site creation
see http://old.nabble.com/Skipping-dependency-report-during-Maven2-site-generation-td20116761.html -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.1</version>
<configuration>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
</configuration>
</plugin>
</plugins>
</reporting>
<pluginRepositories>
<pluginRepository>
<!-- necessary for bundlor and utils -->
<id>repository.plugin.springsource.release</id>
<name>SpringSource Maven Repository</name>
<url>http://repository.springsource.com/maven/bundles/release</url>
</pluginRepository>
</pluginRepositories>
<repositories>
<repository>
<!-- necessary for org.springframework.build.aws.maven dependency -->
<id>repository.springframework.maven.release</id>
<name>Spring Framework Maven Release Repository</name>
<url>http://maven.springframework.org/release</url>
</repository>
</repositories>
</project>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="src" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-rabbit-helloworld</name>
<comment>a simple Hello World example</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.springframework.ide.eclipse.core.springnature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.2.7.200909012107-CI-R3397-B453]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
<enableImports><![CDATA[true]]></enableImports>
<configs>
</configs>
<configSets>
<configSet>
<name><![CDATA[test]]></name>
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
</configs>
</configSet>
</configSets>
</beansProjectDescription>

View File

@@ -0,0 +1,174 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples.spring</groupId>
<artifactId>spring-rabbit-helloworld</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring AMQP Hello World</name>
<url>http://www.springframework.org</url>
<description>
<![CDATA[
This project shows the usage of Spring AMQP integration classes.
]]>
</description>
<properties>
<maven.test.failure.ignore>true</maven.test.failure.ignore>
<spring.framework.version>3.0.3.RELEASE</spring.framework.version>
<spring.amqp.version>1.0.0.BUILD-SNAPSHOT</spring.amqp.version>
</properties>
<profiles>
<profile>
<id>strict</id>
<properties>
<maven.test.failure.ignore>false</maven.test.failure.ignore>
</properties>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp-core</artifactId>
<version>${spring.amqp.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>${spring.amqp.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-admin</artifactId>
<version>${spring.amqp.version}</version>
</dependency>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.framework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.framework.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
<version>1.0.0.M1B</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<inherited>false</inherited>
<configuration>
<descriptorRefs>
<descriptorRef>project</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--forkMode>pertest</forkMode-->
<includes>
<include>**/*Tests.java</include>
</includes>
<excludes>
<exclude>**/Abstract*.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>Codehaus</id>
<url>http://repository.codehaus.org/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<distributionManagement>
<downloadUrl>http://www.springframework.org/download</downloadUrl>
<site>
<id>staging</id>
<url>file:///${user.dir}/target/staging/org.springframework.batch.archetype/${pom.artifactId}</url>
</site>
<repository>
<id>spring-release</id>
<name>Spring Release Repository</name>
<url>file:///${user.dir}/target/staging/release</url>
</repository>
<snapshotRepository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>file:///${user.dir}/target/staging/snapshot</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@@ -0,0 +1,19 @@
package org.springframework.amqp.helloworld;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Consumer {
public static void main(String[] args) {
//ApplicationContext ctx = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
ApplicationContext ctx = new AnnotationConfigApplicationContext(RabbitConfiguration.class);
RabbitTemplate rabbitTemplate = (RabbitTemplate) ctx.getBean(RabbitTemplate.class);
System.out.println("Received " + rabbitTemplate.receiveAndConvert());
}
}

View File

@@ -0,0 +1,20 @@
package org.springframework.amqp.helloworld;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConsumerConfiguration extends RabbitConfiguration {
@Bean
public SimpleMessageListenerContainer listenerContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.setQueueName(helloWorldQueue.getName());
container.setMessageListener(new MessageListenerAdapter(new HelloWorldHandler()));
return container;
}
}

View File

@@ -0,0 +1,8 @@
package org.springframework.amqp.helloworld;
public class HelloWorldHandler {
public void handleMessage(String text) {
System.out.println("Received: " + text);
}
}

View File

@@ -0,0 +1,21 @@
package org.springframework.amqp.helloworld;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Producer {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(RabbitConfiguration.class);
RabbitTemplate rabbitTemplate = (RabbitTemplate) ctx.getBean(RabbitTemplate.class);
rabbitTemplate.convertAndSend("Hello World");
System.out.println("Sent Hello World.");
}
}

View File

@@ -0,0 +1,89 @@
package org.springframework.amqp.helloworld;
import javax.annotation.PostConstruct;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.admin.config.AbstractRabbitConfiguration;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfiguration extends AbstractRabbitConfiguration {
protected Queue helloWorldQueue = new Queue("hello.world.queue");
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}
@Override
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
//The routing key is set to the name of the queue by the broker for the default exchange.
template.setDefaultRoutingKey(helloWorldQueue.getName());
//Where we will synchronously receive messages from
template.setDefaultReceiveQueue(helloWorldQueue);
return template;
}
@PostConstruct
private void configureBroker() {
declare(helloWorldQueue);
}
/*
@Bean
public Queue helloWorldQueue()
{
return declare(helloWorldQueue);
}*/
/*
//Each queue is bound to the default direct exchange
@Bean
public Binding binding() {
return declare(new Binding(helloWorldQueue(), defaultDirectExchange()));
}*/
/*
@Bean
public TopicExchange helloExchange() {
return declare(new TopicExchange("hello.world.exchange"));
}*/
/*
public Queue declareUniqueQueue(String namePrefix) {
Queue queue = new Queue(namePrefix + "-" + UUID.randomUUID());
rabbitAdminTemplate().declareQueue(queue);
return queue;
}
// if the default exchange isn't configured to your liking....
@Bean Binding declareP2PBinding(Queue queue, DirectExchange exchange) {
return declare(new Binding(queue, exchange, queue.getName()));
}
@Bean Binding declarePubSubBinding(String queuePrefix, FanoutExchange exchange) {
return declare(new Binding(declareUniqueQueue(queuePrefix), exchange));
}
@Bean Binding declarePubSubBinding(UniqueQueue uniqueQueue, TopicExchange exchange) {
return declare(new Binding(uniqueQueue, exchange));
}
@Bean Binding declarePubSubBinding(String queuePrefix, TopicExchange exchange, String routingKey) {
return declare(new Binding(declareUniqueQueue(queuePrefix), exchange, routingKey));
}*/
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="Spring Batch: ${project.name}">
<bannerLeft>
<name>Spring Batch: ${project.name}</name>
<href>index.html</href>
</bannerLeft>
<skin>
<groupId>org.springframework.maven.skins</groupId>
<artifactId>maven-spring-skin</artifactId>
<version>1.0.5</version>
</skin>
<body>
<links>
<item name="${project.name}" href="index.html"/>
</links>
<menu ref="reports"/>
</body>
</project>

View File

@@ -0,0 +1,7 @@
# Use Log4j
priority=1
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
# Configuration file of the log
#log4j.configuration=file:log4j-rabbit-stocks.properties

View File

@@ -0,0 +1,11 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.appender.stdout.layout.ConversionPattern=%-5p [%40.40c{4}]: %m%n
log4j.category.org.springframework.amqp.rabbit=DEBUG
log4j.category.org.springframework.beans.factory=INFO

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="src" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-rabbit-stocks</name>
<comment>sample of a basic trading app using RabbitMQ</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.springframework.ide.eclipse.core.springnature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples.spring</groupId>
<artifactId>spring-rabbit-stocks</artifactId>
<version>1.0.0.CI-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring Rabbit Stocks</name>
<url>http://www.springframework.org</url>
<description>
<![CDATA[
This project shows the usage of Spring Rabbit integration classes.
]]>
</description>
<properties>
<maven.test.failure.ignore>true</maven.test.failure.ignore>
<spring.framework.version>3.0.3.RELEASE</spring.framework.version>
<spring.amqp.version>1.0.0.BUILD-SNAPSHOT</spring.amqp.version>
</properties>
<profiles>
<profile>
<id>strict</id>
<properties>
<maven.test.failure.ignore>false</maven.test.failure.ignore>
</properties>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp-core</artifactId>
<version>${spring.amqp.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>${spring.amqp.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-admin</artifactId>
<version>${spring.amqp.version}</version>
</dependency>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.framework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.framework.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.jgoodies</groupId>
<artifactId>forms</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
<version>1.0.0.M1B</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<inherited>false</inherited>
<configuration>
<descriptorRefs>
<descriptorRef>project</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--forkMode>pertest</forkMode-->
<includes>
<include>**/*Tests.java</include>
</includes>
<excludes>
<exclude>**/Abstract*.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>Codehaus</id>
<url>http://repository.codehaus.org/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<distributionManagement>
<downloadUrl>http://www.springframework.org/download</downloadUrl>
<site>
<id>staging</id>
<url>file:///${user.dir}/target/staging/org.springframework.batch.archetype/${pom.artifactId}</url>
</site>
<repository>
<id>spring-release</id>
<name>Spring Release Repository</name>
<url>file:///${user.dir}/target/staging/release</url>
</repository>
<snapshotRepository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>file:///${user.dir}/target/staging/snapshot</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.config;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.admin.config.AbstractRabbitConfiguration;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Provides shared configuration between Client and Server.
* <p>The abstract method configureRabbitTemplate lets the Client and Server further customize
* the rabbit template to their specific needs.
*
* @author Mark Pollack
* @author Mark Fisher
*/
@Configuration
public abstract class AbstractStockAppRabbitConfiguration extends AbstractRabbitConfiguration {
/**
* Shared topic exchange used for publishing any market data (e.g. stock quotes)
*/
protected static String MARKET_DATA_EXCHANGE_NAME = "app.stock.marketdata";
/**
* The server-side consumer's queue that provides point-to-point semantics for stock requests.
*/
protected static String STOCK_REQUEST_QUEUE_NAME = "app.stock.request";
/**
* Key that clients will use to send to the stock request queue via the default direct exchange.
*/
protected static String STOCK_REQUEST_ROUTING_KEY = STOCK_REQUEST_QUEUE_NAME;
//protected static TopicExchange MARKET_DATA_EXCHANGE = new TopicExchange(MARKET_DATA_EXCHANGE_NAME);
protected abstract void configureRabbitTemplate(RabbitTemplate template);
@Bean
public ConnectionFactory connectionFactory() {
//TODO make it possible to customize in subclasses.
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
connectionFactory.setChannelCacheSize(10);
return connectionFactory;
}
@Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
template.setMessageConverter(jsonMessageConverter());
configureRabbitTemplate(template);
return template;
}
@Bean
public MessageConverter jsonMessageConverter() {
return new JsonMessageConverter();
}
// @PostConstruct
// public void declareExchange()
// {
// declare(this.MARKET_DATA_EXCHANGE);
// }
@Bean
public TopicExchange marketDataExchange() {
return declare(new TopicExchange(MARKET_DATA_EXCHANGE_NAME));
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.config;
/**
* Enumerations for the RoutingKeys used in the application to allow for a more fluent API
* style when configuring the broker in code.
*
* @author Mark Pollack
*/
public enum RoutingKey {
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.config.client;
import javax.annotation.PostConstruct;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.UniquelyNamedQueue;
import static org.springframework.amqp.core.BindingBuilder.*;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.rabbit.stocks.config.AbstractStockAppRabbitConfiguration;
import org.springframework.amqp.rabbit.stocks.gateway.RabbitStockServiceGateway;
import org.springframework.amqp.rabbit.stocks.gateway.StockServiceGateway;
import org.springframework.amqp.rabbit.stocks.handler.ClientHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Configures RabbitTemplate and creates the Trader queue and binding for the client.
*
* @author Mark Pollack
* @author Mark Fisher
*/
@Configuration
public class RabbitClientConfiguration extends AbstractStockAppRabbitConfiguration {
@Value("${stocks.quote.pattern}")
private String marketDataRoutingKey;
@Autowired
private ClientHandler clientHandler;
// Create the Queue definitions that write up the Message listener container
//private Queue marketDataQueue = new UniquelyNamedQueue("mktdata");
//private Queue traderJoeQueue = new UniquelyNamedQueue("joe");
/**
* The client's template will by default send to the exchange defined
* in {@link AbstractRabbitConfiguration.rabbitTemplate()}
* with the routing key {@link AbstractStockAppRabbitConfiguration#STOCK_REQUEST_QUEUE_NAME}
* <p>
* The default exchange will delivery to a queue whose name matches the routing key value.
*/
@Override
public void configureRabbitTemplate(RabbitTemplate rabbitTemplate) {
rabbitTemplate.setDefaultRoutingKey(STOCK_REQUEST_QUEUE_NAME);
}
@Bean
public StockServiceGateway stockServiceGateway() {
RabbitStockServiceGateway gateway = new RabbitStockServiceGateway();
gateway.setRabbitTemplate(rabbitTemplate());
gateway.setDefaultReplyToQueue(traderJoeQueue());
return gateway;
}
@Bean
public SimpleMessageListenerContainer messageListenerContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(marketDataQueue(), traderJoeQueue());
//container.setConcurrentConsumers(5); // note, now set to size of channel cache in CachingConnectionFactory by default
container.setMessageListener(messageListenerAdapter());
return container;
//container(using(connectionFactory()).listenToQueues(marketDataQueue(), traderJoeQueue()).withListener(messageListenerAdapter()).
}
@Bean
public MessageListenerAdapter messageListenerAdapter() {
return new MessageListenerAdapter(clientHandler, jsonMessageConverter());
}
// Broker Configuration
// @PostConstruct
// public void declareClientBrokerConfiguration() {
// declare(marketDataQueue);
// declare(new Binding(marketDataQueue, MARKET_DATA_EXCHANGE, marketDataRoutingKey));
// declare(traderJoeQueue);
// // no need to bind traderJoeQueue as it is automatically bound to the default direct exchanage, which is what we will use
//
// //add as many declare statements as needed like a script.
// }
@Bean
public Queue marketDataQueue() {
return declareQueue();
}
/**
* Binds to the market data exchange. Interested in any stock quotes.
* @return
*/
@Bean
public Binding marketDataBinding() {
return declare(new Binding(marketDataQueue(), marketDataExchange(), marketDataRoutingKey));
// Using BindingBuilder
//return declareBinding(from(marketDataQueue()).to(marketDataExchange()).with(marketDataRoutingKey));
}
/**
* This queue does not need a binding, since it relies on the default exchange.
*/
@Bean
public Queue traderJoeQueue() {
return declareQueue();
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.config.server;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.stocks.config.AbstractStockAppRabbitConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Configures RabbitTemplate for the server.
*
* @author Mark Pollack
* @author Mark Fisher
*/
@Configuration
public class RabbitServerConfiguration extends AbstractStockAppRabbitConfiguration {
/**
* The server's template will by default send to the topic exchange named
* {@link AbstractStockAppRabbitConfiguration#MARKET_DATA_EXCHANGE_NAME}.
*/
public void configureRabbitTemplate(RabbitTemplate rabbitTemplate) {
rabbitTemplate.setDefaultExchange(MARKET_DATA_EXCHANGE_NAME);
}
/**
* We don't need to define any binding for the stock request queue, since it's relying
* on the default (no-name) direct exchange to which every queue is implicitly bound.
*/
@Bean
public Queue stockRequestQueue() {
return declare(new Queue(STOCK_REQUEST_QUEUE_NAME));
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.domain;
/**
* Domain object representing a stock quote.
*
* @author Mark Fisher
*/
public class Quote {
private Stock stock;
private String price;
public Quote() {
}
public Quote(Stock stock, String price) {
this.stock = stock;
this.price = price;
}
public Stock getStock() {
return this.stock;
}
public void setStock(Stock stock) {
this.stock = stock;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.domain;
/**
* @author Mark Fisher
*/
public class Stock {
private String ticker;
private StockExchange stockExchange;
public String getTicker() {
return ticker;
}
public void setTicker(String ticker) {
this.ticker = ticker;
}
public StockExchange getStockExchange() {
return stockExchange;
}
public void setStockExchange(StockExchange stockExchange) {
this.stockExchange = stockExchange;
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.domain;
/**
* Enumeration for Stock Exchanges.
*
* @author Mark Fisher
*/
public enum StockExchange {
nyse, nasdaq;
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.domain;
import java.math.BigDecimal;
/**
* Simple trade request 'data' object. No functionality in this 'domain' class.
* @author Mark Pollack
*
*/
public class TradeRequest {
private String ticker;
private long quantity;
private BigDecimal price;
private String orderType;
private String accountName;
private boolean buyRequest;
private String userName;
private String requestId;
public String getTicker() {
return ticker;
}
public void setTicker(String ticker) {
this.ticker = ticker;
}
public long getQuantity() {
return quantity;
}
public void setQuantity(long quantity) {
this.quantity = quantity;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getOrderType() {
return orderType;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public boolean isBuyRequest() {
return buyRequest;
}
public void setBuyRequest(boolean buyRequest) {
this.buyRequest = buyRequest;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.domain;
import java.math.BigDecimal;
/**
* Simple trade request 'data' object. No functionality in this 'domain' class.
* @author Mark Pollack
*
*/
public class TradeResponse {
private String ticker;
private long quantity;
private BigDecimal price;
private String orderType;
private String confirmationNumber;
private boolean error;
private String errorMessage;
public String getTicker() {
return ticker;
}
public void setTicker(String ticker) {
this.ticker = ticker;
}
public long getQuantity() {
return quantity;
}
public void setQuantity(long quantity) {
this.quantity = quantity;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getOrderType() {
return orderType;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
}
public String getConfirmationNumber() {
return confirmationNumber;
}
public void setConfirmationNumber(String confirmationNumber) {
this.confirmationNumber = confirmationNumber;
}
public boolean isError() {
return error;
}
public void setError(boolean error) {
this.error = error;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
@Override
public String toString() {
return "TradeResponse [confirmationNumber=" + confirmationNumber
+ ", error=" + error + ", errorMessage=" + errorMessage
+ ", orderType=" + orderType + ", price=" + price
+ ", quantity=" + quantity + ", ticker=" + ticker + "]";
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.gateway;
/**
* Gateway interface for sending market data to clients
* @author Mark Pollack
*
*/
public interface MarketDataGateway {
void sendMarketData();
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.gateway;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.core.support.RabbitGatewaySupport;
import org.springframework.amqp.rabbit.stocks.domain.Quote;
import org.springframework.amqp.rabbit.stocks.domain.Stock;
import org.springframework.amqp.rabbit.stocks.domain.StockExchange;
/**
* Rabbit implementation of the {@link MarketDataGateway} for sending Market data.
*
* @author Mark Pollack
* @author Mark Fisher
*/
public class RabbitMarketDataGateway extends RabbitGatewaySupport implements MarketDataGateway {
private static Log logger = LogFactory.getLog(RabbitMarketDataGateway.class);
private static final Random random = new Random();
private final List<MockStock> stocks = new ArrayList<MockStock>();
public RabbitMarketDataGateway() {
this.stocks.add(new MockStock("AAPL", StockExchange.nasdaq, 255));
this.stocks.add(new MockStock("CSCO", StockExchange.nasdaq, 22));
this.stocks.add(new MockStock("DELL", StockExchange.nasdaq, 15));
this.stocks.add(new MockStock("GOOG", StockExchange.nasdaq, 500));
this.stocks.add(new MockStock("INTC", StockExchange.nasdaq, 22));
this.stocks.add(new MockStock("MSFT", StockExchange.nasdaq, 29));
this.stocks.add(new MockStock("ORCL", StockExchange.nasdaq, 24));
this.stocks.add(new MockStock("CAJ", StockExchange.nyse, 43));
this.stocks.add(new MockStock("F", StockExchange.nyse, 12));
this.stocks.add(new MockStock("GE", StockExchange.nyse, 18));
this.stocks.add(new MockStock("HMC", StockExchange.nyse, 32));
this.stocks.add(new MockStock("HPQ", StockExchange.nyse, 48));
this.stocks.add(new MockStock("IBM", StockExchange.nyse, 130));
this.stocks.add(new MockStock("TM", StockExchange.nyse, 76));
}
public void sendMarketData() {
Quote quote = generateFakeQuote();
Stock stock = quote.getStock();
logger.info("Sending Market Data for " + stock.getTicker());
String routingKey = "app.stock.quotes."+ stock.getStockExchange() + "." + stock.getTicker();
getRabbitTemplate().convertAndSend(routingKey, quote);
}
private Quote generateFakeQuote() {
MockStock stock = this.stocks.get(random.nextInt(this.stocks.size()));
String price = stock.randomPrice();
return new Quote(stock, price);
}
private static class MockStock extends Stock {
private final int basePrice;
private final DecimalFormat twoPlacesFormat = new DecimalFormat("0.00");
private MockStock(String ticker, StockExchange stockExchange, int basePrice) {
this.setTicker(ticker);
this.setStockExchange(stockExchange);
this.basePrice = basePrice;
}
private String randomPrice() {
return this.twoPlacesFormat.format(this.basePrice + Math.abs(random.nextGaussian()));
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.gateway;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Address;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.support.RabbitGatewaySupport;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
/**
* Rabbit implementation of {@link StockServiceGateway} to send trade requests to an external
* process.
* @author Mark Pollack
*
*/
public class RabbitStockServiceGateway extends RabbitGatewaySupport implements
StockServiceGateway {
private String defaultReplyToQueue;
public void setDefaultReplyToQueue(String defaultReplyToQueue) {
this.defaultReplyToQueue = defaultReplyToQueue;
}
public void setDefaultReplyToQueue(Queue defaultReplyToQueue) {
this.defaultReplyToQueue = defaultReplyToQueue.getName();
}
public void send(TradeRequest tradeRequest) {
getRabbitTemplate().convertAndSend(tradeRequest, new MessagePostProcessor() {
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setReplyTo(new Address(defaultReplyToQueue));
//bytes = ((String) object).getBytes(this.defaultCharset);
try {
message.getMessageProperties().setCorrelationId(UUID.randomUUID().toString().getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return message;
}
});
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.gateway;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
/**
* Gateway interface that sends trades to an external process.
* @author Mark Pollack
*
*/
public interface StockServiceGateway {
void send(TradeRequest tradeRequest);
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.handler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.stocks.domain.Quote;
import org.springframework.amqp.rabbit.stocks.domain.Stock;
import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
import org.springframework.amqp.rabbit.stocks.ui.StockController;
/**
* POJO handler that receives market data and trade responses. Calls are delegated to the UI controller.
*
* @author Mark Pollack
* @author Mark Fisher
*/
public class ClientHandler {
private static Log log = LogFactory.getLog(ClientHandler.class);
private StockController stockController;
public StockController getStockController() {
return stockController;
}
public void setStockController(StockController stockController) {
this.stockController = stockController;
}
public void handleMessage(Quote quote) {
Stock stock = quote.getStock();
log.info("Received market data. Ticker = " + stock.getTicker() + ", Price = " + quote.getPrice());
stockController.displayQuote(quote);
}
public void handleMessage(TradeResponse tradeResponse) {
log.info("Received trade repsonse. [" + tradeResponse + "]");
stockController.UpdateTrade(tradeResponse);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.handler;
import java.util.ArrayList;
import java.util.List;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
import org.springframework.amqp.rabbit.stocks.service.CreditCheckService;
import org.springframework.amqp.rabbit.stocks.service.ExecutionVenueService;
import org.springframework.amqp.rabbit.stocks.service.TradingService;
import org.springframework.util.StringUtils;
/**
* POJO handler that receives trade requests and sends back a trade response. Main application
* logic sits here which coordinates between {@link ExecutionVenueService}, {@link CreditCheckService},
* and {@link TradingService}.
*
* @author Mark Pollack
*
*/
public class ServerHandler {
private ExecutionVenueService executionVenueService;
private CreditCheckService creditCheckService;
private TradingService tradingService;
public ServerHandler(ExecutionVenueService executionVenueService,
CreditCheckService creditCheckService,
TradingService tradingService) {
this.executionVenueService = executionVenueService;
this.creditCheckService = creditCheckService;
this.tradingService = tradingService;
}
public TradeResponse handleMessage(TradeRequest tradeRequest)
{
TradeResponse tradeResponse;
List errors = new ArrayList();
if (creditCheckService.canExecute(tradeRequest, errors))
{
tradeResponse = executionVenueService.executeTradeRequest(tradeRequest);
}
else
{
tradeResponse = new TradeResponse();
tradeResponse.setError(true);
tradeResponse.setErrorMessage(StringUtils.arrayToCommaDelimitedString(errors.toArray()));
}
tradingService.processTrade(tradeRequest, tradeResponse);
return tradeResponse;
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.service;
import java.util.List;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
/**
* Credit service to see if the incoming trade can be processed. If it can not be processed
* a false value is returned and the error list contains information as to what went wrong.
*
* @author Mark Pollack
*
*/
public interface CreditCheckService {
boolean canExecute(TradeRequest tradeRequest, List errors);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.service;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
/**
* Executes the trade request, creating a Trade response. See the code flow in {@link ServerHandler} for
* its usage.
* @author Mark Pollack
*
*/
public interface ExecutionVenueService {
TradeResponse executeTradeRequest(TradeRequest request);
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.service;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
/**
* Trading Service to process trade requests and response. This is the place to perform
* any trade processing after executions. See code flow in {@link ServerHandler}.
*
* @author Mark Pollack
*
*/
public interface TradingService {
void processTrade(TradeRequest request, TradeResponse response);
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.service.stubs;
import java.util.List;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
import org.springframework.amqp.rabbit.stocks.service.CreditCheckService;
/***
* An implementation that always returns true (just like real-life for a mortgage check :)
*
* @author Mark Pollack
*
*/
public class CreditCheckServiceStub implements CreditCheckService {
public boolean canExecute(TradeRequest tradeRequest, List errors) {
return true;
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.service.stubs;
import java.math.BigDecimal;
import java.util.Random;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
import org.springframework.amqp.rabbit.stocks.service.ExecutionVenueService;
/**
* Execute the trade, setting the execution price to changing value in line with what the market data feed is producing.
*
* @author Mark Pollack
*
*/
public class ExecutionVenueServiceStub implements ExecutionVenueService {
private static Log log = LogFactory.getLog(ExecutionVenueServiceStub.class);
private Random random = new Random();
public TradeResponse executeTradeRequest(TradeRequest request) {
TradeResponse response = new TradeResponse();
response.setOrderType(request.getOrderType());
response.setPrice(calculatePrice(request.getTicker(), request.getQuantity(), request.getOrderType(), request.getPrice(), request.getUserName()));
response.setQuantity(request.getQuantity());
response.setTicker(request.getTicker());
response.setConfirmationNumber(UUID.randomUUID().toString());
try {
log.info("Sleeping 2 seconds to simulate processing..");
Thread.sleep(2000);
} catch (InterruptedException e) {
log.error("Didn't finish sleeping", e);
}
return response;
}
private BigDecimal calculatePrice(String ticker, long quantity,
String orderType, BigDecimal price, String userName) {
// provide as sophisticated implementation...for now all the same price.
if (orderType.compareTo("LIMIT") == 0)
{
return price;
}
else
{
//in line with market data implementation
return new BigDecimal(22 + Math.abs(gaussian()));
}
}
private double gaussian() {
return random.nextGaussian();
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.service.stubs;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
import org.springframework.amqp.rabbit.stocks.service.TradingService;
/**
* No-op implementation
* @author Mark Pollack
*
*/
public class TradingServiceStub implements TradingService {
public void processTrade(TradeRequest request, TradeResponse response) {
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.ui;
import org.springframework.amqp.rabbit.stocks.domain.Quote;
import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
import org.springframework.amqp.rabbit.stocks.gateway.StockServiceGateway;
/**
* Basic controller for the UI.
* TODO: Fix that the UI can receive events before it's panel has been initialized.
*
* @author Mark Pollack
* @author Mark Fisher
*/
public class StockController {
private StockPanel stockPanel;
private StockServiceGateway stockServiceGateway;
public StockPanel getStockPanel() {
return stockPanel;
}
public void setStockPanel(StockPanel stockPanel) {
this.stockPanel = stockPanel;
}
public StockServiceGateway getStockServiceGateway() {
return stockServiceGateway;
}
public void setStockServiceGateway(StockServiceGateway stockServiceGateway) {
this.stockServiceGateway = stockServiceGateway;
}
// "Actions"
public void sendTradeRequest(String text) {
String[] tokens = text.split("\\s");
String quantityString = tokens[0];
String ticker = tokens[1];
int quantity = Integer.parseInt(quantityString);
TradeRequest tr = new TradeRequest();
tr.setAccountName("ACCT-123");
tr.setBuyRequest(true);
tr.setOrderType("MARKET");
tr.setTicker(ticker);
tr.setQuantity(quantity);
tr.setRequestId("REQ-1");
tr.setUserName("Joe Trader");
tr.setUserName("Joe");
stockServiceGateway.send(tr);
}
public void displayQuote(Quote quote) {
//TODO race condition with message delivery and initalization... use @Configurable?
if (stockPanel != null) {
stockPanel.displayQuote(quote);
}
}
public void UpdateTrade(TradeResponse tradeResponse) {
stockPanel.update(tradeResponse);
}
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks.ui;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.text.DecimalFormat;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.stocks.domain.Quote;
import org.springframework.amqp.rabbit.stocks.domain.Stock;
import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
/**
* A typical poor mans UI to drive the application.
*
* @author Mark Pollack
* @author Mark Fisher
*/
public class StockPanel extends JPanel {
private static Log log = LogFactory.getLog(StockPanel.class);
private JTextField tradeRequestTextField;
private JButton tradeRequestButton;
private JTextArea marketDataTextArea;
private StockController stockController;
private DecimalFormat frmt = new DecimalFormat("$0.00");
public StockPanel(StockController controller) {
this.stockController = controller;
controller.setStockPanel(this);
this.setBorder(BorderFactory.createTitledBorder("Stock Form"));
FormLayout formLayout = new FormLayout("pref, 150dlu", // columns
"pref, fill:100dlu:grow"); // rows
setLayout(formLayout);
CellConstraints c = new CellConstraints();
tradeRequestButton = new JButton("Send Trade Request");
add(tradeRequestButton, c.xy(1, 1));
tradeRequestTextField = new JTextField("");
add(tradeRequestTextField, c.xy(2, 1));
add(new JLabel("Market Data"), c.xy(1, 2));
marketDataTextArea = new JTextArea();
JScrollPane sp = new JScrollPane(marketDataTextArea);
sp.setSize(200, 300);
add(sp, c.xy(2, 2));
tradeRequestTextField.addFocusListener(new FocusListener() {
public void focusLost(FocusEvent e) {
}
public void focusGained(FocusEvent e) {
tradeRequestTextField.setText("");
tradeRequestTextField.setForeground(Color.BLACK);
}
});
tradeRequestButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendTradeRequest();
}
});
}
private void sendTradeRequest() {
try {
stockController.sendTradeRequest(tradeRequestTextField.getText());
tradeRequestTextField.setForeground(Color.GRAY);
tradeRequestTextField.setText("Request Pending...");
log.info("Sent trade request.");
}
catch (Exception ex) {
tradeRequestTextField.setForeground(Color.RED);
tradeRequestTextField.setText("Required Format: 100 TCKR");
}
}
public static void main(String[] a) {
JFrame f = new JFrame("Rabbit Stock Demo");
f.setDefaultCloseOperation(2);
f.add(new StockPanel(new StockController()));
f.pack();
f.setVisible(true);
}
public void displayQuote(final Quote quote) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Stock stock = quote.getStock();
marketDataTextArea.append(stock.getTicker() + " " + quote.getPrice() + "\n");
}
});
}
public void update(final TradeResponse tradeResponse) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
tradeRequestTextField.setForeground(Color.GREEN);
tradeRequestTextField.setText("Confirmed. "
+ tradeResponse.getTicker() + " "
+ frmt.format(tradeResponse.getPrice().doubleValue()));
}
});
}
}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- pick up rabbit broker configuration -->
<context:component-scan base-package="org.springframework.amqp.rabbit.stocks.config.client"/>
<context:property-placeholder location="client.properties"/>
<import resource="classpath:client-handlers.xml" />
<!--
<import resource="classpath:client-messaging.xml" />
-->
</beans>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="stockController" class="org.springframework.amqp.rabbit.stocks.ui.StockController">
<property name="stockServiceGateway" ref="stockServiceGateway"/>
</bean>
<bean id="clientHandler" class="org.springframework.amqp.rabbit.stocks.handler.ClientHandler">
<property name="stockController" ref="stockController"/>
</bean>
</beans>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="stockServiceGateway" class="org.springframework.amqp.rabbit.stocks.gateway.RabbitStockServiceGateway">
<property name="rabbitTemplate" ref="rabbitTemplate" />
<property name="defaultReplyToQueue" value="#{traderJoeQueue.name}" />
</bean>
<bean id="messageListenerContainer" class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="queueName" value="#{marketDataQueue.name},#{traderJoeQueue.name}"/>
<property name="concurrentConsumers" value="5" />
<property name="messageListener" ref="messageListenerAdapter" />
</bean>
<bean id="messageListenerAdapter" class="org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="clientHandler" />
<property name="messageConverter" ref="jsonMessageConverter" />
</bean>
</beans>

View File

@@ -0,0 +1 @@
stocks.quote.pattern=app.stock.quotes.nasdaq.*

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- pick up rabbit broker configuration -->
<context:component-scan base-package="org.springframework.amqp.rabbit.stocks.config.server"/>
<import resource="classpath:server-handlers.xml" />
<import resource="classpath:server-messaging.xml" />
<import resource="classpath:server-services.xml" />
<import resource="classpath:server-jmx.xml" />
<task:scheduled-tasks>
<task:scheduled ref="marketDataGateway" method="sendMarketData" fixed-delay="5000"/>
</task:scheduled-tasks>
</beans>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean name="serverHandler" class="org.springframework.amqp.rabbit.stocks.handler.ServerHandler">
<constructor-arg ref="executionVenueService"/>
<constructor-arg ref="creditCheckService"/>
<constructor-arg ref="tradingService"/>
</bean>
</beans>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:mbean-export/>
<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
p:port="1099" />
<!-- Expose JMX over RMI -->
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry"
p:objectName="connector:name=rmi"
p:serviceUrl="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector" />
</beans>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="marketDataGateway" class="org.springframework.amqp.rabbit.stocks.gateway.RabbitMarketDataGateway">
<property name="rabbitTemplate" ref="rabbitTemplate" />
</bean>
<bean id="messageListenerContainer" class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="queueName" value="#{stockRequestQueue.name}" />
<property name="concurrentConsumers" value="5" />
<property name="messageListener" ref="messageListenerAdapter" />
</bean>
<bean id="messageListenerAdapter" class="org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="serverHandler" />
<property name="messageConverter" ref="jsonMessageConverter" />
</bean>
</beans>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="executionVenueService"
class="org.springframework.amqp.rabbit.stocks.service.stubs.ExecutionVenueServiceStub">
</bean>
<bean id="creditCheckService"
class="org.springframework.amqp.rabbit.stocks.service.stubs.CreditCheckServiceStub">
</bean>
<bean id="tradingService"
class="org.springframework.amqp.rabbit.stocks.service.stubs.TradingServiceStub">
</bean>
</beans>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="Spring Batch: ${project.name}">
<bannerLeft>
<name>Spring Batch: ${project.name}</name>
<href>index.html</href>
</bannerLeft>
<skin>
<groupId>org.springframework.maven.skins</groupId>
<artifactId>maven-spring-skin</artifactId>
<version>1.0.5</version>
</skin>
<body>
<links>
<item name="${project.name}" href="index.html"/>
</links>
<menu ref="reports"/>
</body>
</project>

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.amqp.rabbit.stocks;
import javax.swing.JFrame;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.springframework.amqp.rabbit.stocks.ui.StockController;
import org.springframework.amqp.rabbit.stocks.ui.StockPanel;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Main client application, can run as app or unit test.
* @author Mark Pollack
*
*/
public class Client {
private static Log log = LogFactory.getLog(Client.class);
/**
* @param args
*/
public static void main(String[] args) {
new Client().run();
}
@Test
public void run() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("client-bootstrap-config.xml");
StockController controller = ac.getBean(StockController.class);
JFrame f = new JFrame("Rabbit Stock Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//TODO consider @Configurable
f.add(new StockPanel(controller));
f.pack();
f.setVisible(true);
}
}

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