Skip to content

Commit 85cfd01

Browse files
Josh Longphilwebb
Josh Long
authored andcommitted
Add JNDI Sample
Add a sample application that can be deployed to WildFly to demonstrate how JTA can be used when running in a application server. See spring-projectsgh-947
1 parent 239d19d commit 85cfd01

File tree

11 files changed

+466
-0
lines changed

11 files changed

+466
-0
lines changed

spring-boot-samples/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
<module>spring-boot-sample-jetty</module>
4141
<module>spring-boot-sample-jta-atomikos</module>
4242
<module>spring-boot-sample-jta-bitronix</module>
43+
<module>spring-boot-sample-jta-jndi</module>
4344
<module>spring-boot-sample-liquibase</module>
4445
<module>spring-boot-sample-parent-context</module>
4546
<module>spring-boot-sample-profile</module>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
## Introduction
2+
3+
This application is intended to run inside of a Java EE application server such as
4+
JBoss Wildfly. It demonstrates Spring Boot's auto-configuration defaulting for a
5+
container-managed `TransactionManager` and `DataSource`. This example unfortunately
6+
requires a fully configured Wildfly installation. You'll need to configure a PostgreSQL
7+
XA `DataSource` and an XA `ConnectionFactory` in the Java EE application server's
8+
JNDI machinery.
9+
10+
## Setup
11+
12+
### Postgres
13+
We will use postgres as the underlying database, v9.3.5 or above is recommend. Follow
14+
the installation instructions from http://www.postgresql.org/[postgresql.org] or use
15+
a package manager to install the appropriate binaries.
16+
17+
Once installed you will need to initialize and start the server.
18+
19+
[source,indent=0]
20+
----
21+
$ initdb /usr/local/var/postgres -E utf8
22+
$ pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start
23+
----
24+
25+
With the server running you can create a user and a database:
26+
27+
[source,indent=0]
28+
----
29+
$ createuser springboot
30+
$ createdb bootdemo
31+
----
32+
33+
Finally you can type `psql bootdemo` to configure a password:
34+
35+
[source,indent=0]
36+
----
37+
ALTER USER springboot WITH PASSWORD 'springboot';
38+
\q
39+
----
40+
41+
42+
### WildFly 8.1
43+
Download an install WildFly 8.1 from http://wildfly.org/downloads/[wildfly.org]. Once
44+
installed you will need to add a management user by running `$JBOSS_HOME/bin/add-user.sh`
45+
(see the WildFly documentation for details).
46+
47+
You will also need to add a postgresql module. The following commands setup the basic
48+
structure:
49+
50+
[source,indent=0]
51+
----
52+
$ cd $JBOSS_HOME
53+
mkdir -p modules/org/postgresql/main
54+
wget http://jdbc.postgresql.org/download/postgresql-9.3-1102.jdbc41.jar
55+
mv postgresql-9.3-1102.jdbc41.jar modules/org/postgresql/main
56+
----
57+
58+
You can then add the following to `$JBOSS_HOME/modules/org/postgresql/main/module.xml`:
59+
60+
[source,indent=0]
61+
----
62+
<?xml version="1.0" encoding="UTF-8"?>
63+
<module xmlns="urn:jboss:module:1.0" name="org.postgresql">
64+
<resources>
65+
<resource-root path="postgresql-9.3-1102.jdbc41.jar"/>
66+
</resources>
67+
<dependencies>
68+
<module name="javax.api"/>
69+
<module name="javax.transaction.api"/>
70+
</dependencies>
71+
</module>
72+
----
73+
74+
## Configuration
75+
A custom WildFly configuration is required for the XA `DataSource` and `ConnectionFactory`
76+
elements. The `$JBOSS_HOME/standalone/configuration/standalone-full.xml` is a good
77+
starting point, copy this file to
78+
`$JBOSS_HOME/standalone/configuration/standalone-boot-demo.xml` then make the following
79+
changes.
80+
81+
### DataSource
82+
You need to register a PostgreSQL XA `Driver` and then configure an `xa-datasource`.
83+
84+
Here's a complete listing of the `xa-datasource` contribution to the `datasources`
85+
element, and the `driver` contribution to the `drivers` element to configure a PostgreSQL
86+
DB connection to localhost.
87+
https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6/html-single/Administration_and_Configuration_Guide/index.html#Install_a_JDBC_Driver_with_the_Management_Console[You can learn more from the documentation].
88+
89+
[source,xml,indent=0,subs="verbatim,attributes"]
90+
----
91+
<datasources>
92+
...
93+
<xa-datasource
94+
jndi-name="java:jboss/datasources/bootdemo"
95+
pool-name="CrmXADS"
96+
enabled="true">
97+
<xa-datasource-property name="url">jdbc:postgresql://localhost:5432/crm</xa-datasource-property>
98+
<driver>postgres</driver>
99+
<xa-pool>
100+
<min-pool-size>10</min-pool-size>
101+
<max-pool-size>20</max-pool-size>
102+
<prefill>true</prefill>
103+
</xa-pool>
104+
<security>
105+
<user-name>springboot</user-name>
106+
<password>springboot</password>
107+
</security>
108+
</xa-datasource>
109+
<drivers>
110+
...
111+
<driver name="postgres" module="org.postgresql">
112+
<xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
113+
</driver>
114+
</drivers>
115+
</datasources>
116+
----
117+
118+
### JMS Destination
119+
You will also need to configure a `javax.jms.Destination` by contributing the following to
120+
the `hornetq-server` element:
121+
122+
[source,xml,indent=0,subs="verbatim,attributes"]
123+
----
124+
<jms-destinations>
125+
<jms-queue name="accounts">
126+
<entry name="java:/jms/queue/bootdemo"/>
127+
</jms-queue>
128+
...
129+
</jms-destinations>
130+
----
131+
132+
133+
## Running and deploying the sample
134+
Run Wildfly with the following command:
135+
136+
[source,indent=0]
137+
----
138+
$JBOSS_HOME/bin/standalone.sh -c standalone-boot-demo.xml
139+
----
140+
141+
Once running you can deploy the application by copying
142+
`target/spring-boot-sample-jta-jndi.war` to `$JBOSS_HOME/standalone/deployments`.
143+
144+
Open a browser to http://localhost:8080/spring-boot-sample-jta-jndi to trigger the
145+
sample. You should see the current count (it will increment by one on each refresh). If
146+
you check the logs you should see a `----> Josh` message and some counts. Notice how the
147+
`error` message triggers an exception with causes both the database insert and the JMS
148+
message to be rolled back.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<!-- Your own application should inherit from spring-boot-starter-parent -->
7+
<groupId>org.springframework.boot</groupId>
8+
<artifactId>spring-boot-samples</artifactId>
9+
<version>1.2.0.BUILD-SNAPSHOT</version>
10+
</parent>
11+
<artifactId>spring-boot-sample-jta-jndi</artifactId>
12+
<name>Spring Boot JNDI JTA Sample</name>
13+
<packaging>war</packaging>
14+
<description>Spring Boot JNDI JTA Sample</description>
15+
<url>http://projects.spring.io/spring-boot/</url>
16+
<organization>
17+
<name>Pivotal Software, Inc.</name>
18+
<url>http://www.spring.io</url>
19+
</organization>
20+
<properties>
21+
<main.basedir>${basedir}/../..</main.basedir>
22+
</properties>
23+
<dependencies>
24+
<dependency>
25+
<groupId>org.springframework</groupId>
26+
<artifactId>spring-jms</artifactId>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-starter-data-jpa</artifactId>
31+
</dependency>
32+
<dependency>
33+
<groupId>org.springframework.boot</groupId>
34+
<artifactId>spring-boot-starter-web</artifactId>
35+
<exclusions>
36+
<exclusion>
37+
<groupId>org.springframework.boot</groupId>
38+
<artifactId>spring-boot-starter-tomcat</artifactId>
39+
</exclusion>
40+
</exclusions>
41+
</dependency>
42+
<dependency>
43+
<groupId>javax.servlet</groupId>
44+
<artifactId>javax.servlet-api</artifactId>
45+
<scope>provided</scope>
46+
</dependency>
47+
<dependency>
48+
<groupId>javax.jms</groupId>
49+
<artifactId>jms-api</artifactId>
50+
<scope>provided</scope>
51+
</dependency>
52+
<dependency>
53+
<groupId>org.springframework.boot</groupId>
54+
<artifactId>spring-boot-starter-test</artifactId>
55+
<scope>test</scope>
56+
</dependency>
57+
</dependencies>
58+
<build>
59+
<finalName>spring-boot-sample-jta-jndi</finalName>
60+
</build>
61+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample.jndi;
18+
19+
import javax.persistence.Entity;
20+
import javax.persistence.GeneratedValue;
21+
import javax.persistence.Id;
22+
23+
@Entity
24+
public class Account {
25+
26+
@Id
27+
@GeneratedValue
28+
private Long id;
29+
30+
private String username;
31+
32+
Account() {
33+
}
34+
35+
public Account(String username) {
36+
this.username = username;
37+
}
38+
39+
public String getUsername() {
40+
return this.username;
41+
}
42+
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample.jndi;
18+
19+
import org.springframework.data.repository.CrudRepository;
20+
21+
public interface AccountRepository extends CrudRepository<Account, Long> {
22+
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample.jndi;
18+
19+
import org.springframework.beans.factory.annotation.Autowired;
20+
import org.springframework.jms.core.JmsTemplate;
21+
import org.springframework.stereotype.Service;
22+
import org.springframework.transaction.annotation.Transactional;
23+
24+
@Service
25+
@Transactional
26+
public class AccountService {
27+
28+
private final JmsTemplate jmsTemplate;
29+
30+
private final AccountRepository accountRepository;
31+
32+
@Autowired
33+
public AccountService(JmsTemplate jmsTemplate, AccountRepository accountRepository) {
34+
this.jmsTemplate = jmsTemplate;
35+
this.accountRepository = accountRepository;
36+
}
37+
38+
public void createAccountAndNotify(String username) {
39+
this.jmsTemplate.convertAndSend("java:/jms/queue/bootdemo", username);
40+
Account entity = new Account(username);
41+
this.accountRepository.save(entity);
42+
if ("error".equals(username)) {
43+
throw new RuntimeException("Simulated error");
44+
}
45+
}
46+
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample.jndi;
18+
19+
import org.springframework.jms.annotation.JmsListener;
20+
import org.springframework.stereotype.Component;
21+
22+
@Component
23+
public class Messages {
24+
25+
@JmsListener(destination = "java:/jms/queue/bootdemo")
26+
public void onMessage(String content) {
27+
System.out.println("----> " + content);
28+
}
29+
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample.jndi;
18+
19+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
20+
import org.springframework.context.annotation.ComponentScan;
21+
import org.springframework.context.annotation.Configuration;
22+
23+
@Configuration
24+
@EnableAutoConfiguration
25+
@ComponentScan
26+
public class SampleJndiApplication {
27+
28+
}

0 commit comments

Comments
 (0)