Skip to content

Commit 9f1d449

Browse files
committed
Re-organized JCA test and improved compatibility
Main change; the bean class method is now used instead of the proxy method.
1 parent 4924191 commit 9f1d449

File tree

11 files changed

+227
-126
lines changed

11 files changed

+227
-126
lines changed

jca/mdb-filewatcher/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
### What is this?
44

5-
This sample project demonstrates that writing (and testing) JCA resource adapter is fairly easy. We implemented Message Driven Bean which observes certain directory for files which are created, updated or deleted.
5+
This sample project demonstrates that writing (and testing) a JCA resource adapter is fairly easy. We implemented a Message Driven Bean which observes a certain directory for files which are created, updated or deleted.
66

77
It's tested using:
88

jca/mdb-filewatcher/pom.xml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
33
<modelVersion>4.0.0</modelVersion>
4+
45
<parent>
56
<artifactId>jca</artifactId>
67
<groupId>org.javaee7</groupId>
78
<version>1.0-SNAPSHOT</version>
8-
<relativePath>../pom.xml</relativePath>
99
</parent>
1010

11-
<groupId>org.javaee7</groupId>
1211
<artifactId>mdb-filewatcher</artifactId>
13-
<version>1.0-SNAPSHOT</version>
1412
<name>Java EE 7 Sample: mdb-filewatcher</name>
13+
1514
</project>

jca/mdb-filewatcher/src/main/java/org/javaee7/jca/filewatch/adapter/FileSystemWatcherActivationSpec.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ public ResourceAdapter getResourceAdapter() {
3838
}
3939

4040
@Override
41-
public void setResourceAdapter(ResourceAdapter resourceAdapter)
42-
throws ResourceException {
41+
public void setResourceAdapter(ResourceAdapter resourceAdapter) throws ResourceException {
4342
this.resourceAdapter = resourceAdapter;
4443
}
4544

jca/mdb-filewatcher/src/main/java/org/javaee7/jca/filewatch/adapter/FileSystemWatcherResourceAdapter.java

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,70 @@
1616
*/
1717
package org.javaee7.jca.filewatch.adapter;
1818

19-
import javax.resource.ResourceException;
20-
import javax.resource.spi.*;
21-
import javax.resource.spi.endpoint.MessageEndpointFactory;
22-
import javax.transaction.xa.XAResource;
19+
import static java.lang.System.out;
20+
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
21+
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
22+
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
23+
2324
import java.io.IOException;
24-
import java.nio.file.*;
25+
import java.nio.file.FileSystem;
26+
import java.nio.file.FileSystems;
27+
import java.nio.file.WatchKey;
28+
import java.nio.file.WatchService;
2529
import java.util.Map;
2630
import java.util.concurrent.ConcurrentHashMap;
2731

32+
import javax.resource.ResourceException;
33+
import javax.resource.spi.ActivationSpec;
34+
import javax.resource.spi.BootstrapContext;
35+
import javax.resource.spi.Connector;
36+
import javax.resource.spi.ResourceAdapter;
37+
import javax.resource.spi.ResourceAdapterInternalException;
38+
import javax.resource.spi.endpoint.MessageEndpointFactory;
39+
import javax.transaction.xa.XAResource;
40+
2841
/**
2942
* @author Robert Panzer (robert.panzer@me.com)
3043
* @author Bartosz Majsak (bartosz.majsak@gmail.com)
3144
*/
3245
@Connector
3346
public class FileSystemWatcherResourceAdapter implements ResourceAdapter {
3447

35-
FileSystem fileSystem;
36-
37-
WatchService watchService;
38-
39-
Map<WatchKey, MessageEndpointFactory> listeners = new ConcurrentHashMap<>();
48+
private BootstrapContext bootstrapContext;
49+
50+
private FileSystem fileSystem;
51+
private WatchService watchService;
52+
private Map<WatchKey, MessageEndpointFactory> listeners = new ConcurrentHashMap<>();
53+
private Map<MessageEndpointFactory, Class<?>> endpointFactoryToBeanClass = new ConcurrentHashMap<>();
54+
55+
@Override
56+
public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException {
57+
58+
out.println(this.getClass().getSimpleName() + " resource adapater started");
59+
60+
this.bootstrapContext = bootstrapContext;
4061

41-
Map<MessageEndpointFactory, Class<?>> endpointFactoryToBeanClass = new ConcurrentHashMap<>();
62+
try {
63+
fileSystem = FileSystems.getDefault();
64+
watchService = fileSystem.newWatchService();
65+
} catch (IOException e) {
66+
throw new ResourceAdapterInternalException(e);
67+
}
4268

43-
private BootstrapContext bootstrapContext;
69+
new WatchingThread(watchService, this).start();
70+
}
4471

4572
@Override
4673
public void endpointActivation(MessageEndpointFactory endpointFactory, ActivationSpec activationSpec) throws ResourceException {
74+
75+
out.println(this.getClass().getSimpleName() + " resource adapater endpoint activated for " + endpointFactory.getEndpointClass());
76+
4777
FileSystemWatcherActivationSpec fsWatcherAS = (FileSystemWatcherActivationSpec) activationSpec;
4878

4979
try {
50-
WatchKey watchKey = fileSystem.getPath(fsWatcherAS.getDir())
51-
.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
52-
StandardWatchEventKinds.ENTRY_DELETE,
53-
StandardWatchEventKinds.ENTRY_MODIFY);
80+
WatchKey watchKey =
81+
fileSystem.getPath(fsWatcherAS.getDir())
82+
.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
5483

5584
listeners.put(watchKey, endpointFactory);
5685

@@ -62,6 +91,9 @@ public void endpointActivation(MessageEndpointFactory endpointFactory, Activatio
6291

6392
@Override
6493
public void endpointDeactivation(MessageEndpointFactory endpointFactory, ActivationSpec activationSpec) {
94+
95+
out.println(this.getClass().getSimpleName() + " resource adapater endpoint deactivated for " + endpointFactory.getEndpointClass());
96+
6597
for (WatchKey watchKey : listeners.keySet()) {
6698
if (listeners.get(watchKey) == endpointFactory) {
6799
listeners.remove(watchKey);
@@ -76,22 +108,11 @@ public XAResource[] getXAResources(ActivationSpec[] arg0) throws ResourceExcepti
76108
return new XAResource[0];
77109
}
78110

79-
@Override
80-
public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException {
81-
this.bootstrapContext = bootstrapContext;
82-
83-
try {
84-
fileSystem = FileSystems.getDefault();
85-
watchService = fileSystem.newWatchService();
86-
} catch (IOException e) {
87-
throw new ResourceAdapterInternalException(e);
88-
}
89-
90-
new WatchingThread(watchService, this).start();
91-
}
92-
93111
@Override
94112
public void stop() {
113+
114+
out.println(this.getClass().getSimpleName() + " resource adapater stopping");
115+
95116
try {
96117
watchService.close();
97118
} catch (IOException e) {

jca/mdb-filewatcher/src/main/java/org/javaee7/jca/filewatch/adapter/WatchingThread.java

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,28 @@
1616
*/
1717
package org.javaee7.jca.filewatch.adapter;
1818

19+
import static java.lang.System.out;
20+
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
21+
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
22+
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
23+
24+
import java.lang.reflect.Method;
25+
import java.nio.file.ClosedWatchServiceException;
26+
import java.nio.file.Path;
27+
import java.nio.file.WatchEvent;
28+
import java.nio.file.WatchEvent.Kind;
29+
import java.nio.file.WatchKey;
30+
import java.nio.file.WatchService;
31+
import java.util.List;
32+
1933
import javax.resource.spi.endpoint.MessageEndpoint;
2034
import javax.resource.spi.endpoint.MessageEndpointFactory;
2135
import javax.resource.spi.work.Work;
2236
import javax.resource.spi.work.WorkException;
23-
import java.lang.reflect.Method;
24-
import java.nio.file.*;
25-
import java.util.List;
2637

27-
import org.javaee7.jca.filewatch.event.*;
38+
import org.javaee7.jca.filewatch.event.Created;
39+
import org.javaee7.jca.filewatch.event.Deleted;
40+
import org.javaee7.jca.filewatch.event.Modified;
2841

2942
/**
3043
* @author Robert Panzer (robert.panzer@me.com)
@@ -36,8 +49,7 @@ final class WatchingThread extends Thread {
3649

3750
private FileSystemWatcherResourceAdapter resourceAdapter;
3851

39-
WatchingThread(WatchService watchService,
40-
FileSystemWatcherResourceAdapter ra) {
52+
WatchingThread(WatchService watchService, FileSystemWatcherResourceAdapter ra) {
4153
this.watchService = watchService;
4254
this.resourceAdapter = ra;
4355
}
@@ -61,23 +73,16 @@ public void run() {
6173
private void dispatchEvents(List<WatchEvent<?>> events, MessageEndpointFactory messageEndpointFactory) {
6274
for (WatchEvent<?> event : events) {
6375
Path path = (Path) event.context();
76+
77+
out.println("Watch thread received event of kind: " + event.kind() + " for " + path.getFileName());
6478

6579
try {
6680
MessageEndpoint endpoint = messageEndpointFactory.createEndpoint(null);
6781
Class<?> beanClass = resourceAdapter.getBeanClass(messageEndpointFactory);
68-
for (Method m : beanClass.getMethods()) {
69-
if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())
70-
&& m.isAnnotationPresent(Created.class)
71-
&& path.toString().matches(m.getAnnotation(Created.class).value())) {
72-
invoke(endpoint, m, path);
73-
} else if (StandardWatchEventKinds.ENTRY_DELETE.equals(event.kind())
74-
&& m.isAnnotationPresent(Deleted.class)
75-
&& path.toString().matches(m.getAnnotation(Deleted.class).value())) {
76-
invoke(endpoint, m, path);
77-
} else if (StandardWatchEventKinds.ENTRY_MODIFY.equals(event.kind())
78-
&& m.isAnnotationPresent(Modified.class)
79-
&& path.toString().matches(m.getAnnotation(Modified.class).value())) {
80-
invoke(endpoint, m, path);
82+
83+
for (Method beanClassMethod : beanClass.getMethods()) {
84+
if (methodIsForEvent(path.toString(), beanClassMethod, event.kind())) {
85+
invoke(endpoint, beanClassMethod, path);
8186
}
8287
}
8388
} catch (Exception e) {
@@ -86,18 +91,23 @@ private void dispatchEvents(List<WatchEvent<?>> events, MessageEndpointFactory m
8691
}
8792
}
8893

89-
private void invoke(final MessageEndpoint endpoint, final Method m, final Path path) throws WorkException {
94+
private void invoke(final MessageEndpoint endpoint, final Method beanClassMethod, final Path path) throws WorkException {
95+
96+
out.println("Watch thread scheduling endpoint call via workmanager for method: " + beanClassMethod.getName() + " and file" + path.getFileName());
97+
9098
resourceAdapter.getBootstrapContext().getWorkManager().scheduleWork(new Work() {
9199

92100
@Override
93101
public void run() {
94102
try {
95-
Method endpointMethod = endpoint.getClass().getMethod(m.getName(), m.getParameterTypes());
96-
endpoint.beforeDelivery(endpointMethod);
97-
98-
endpointMethod.invoke(endpoint, path.toFile());
99-
100-
endpoint.afterDelivery();
103+
try {
104+
endpoint.beforeDelivery(beanClassMethod);
105+
106+
beanClassMethod.invoke(endpoint, path.toFile());
107+
108+
} finally {
109+
endpoint.afterDelivery();
110+
}
101111
} catch (Exception e) {
102112
e.printStackTrace();
103113
}
@@ -108,4 +118,31 @@ public void release() {
108118
}
109119
});
110120
}
121+
122+
private boolean methodIsForEvent(String path, Method method, Kind<?> eventKind) {
123+
return
124+
(
125+
ENTRY_CREATE.equals(eventKind) &&
126+
method.isAnnotationPresent(Created.class) &&
127+
path.matches(method.getAnnotation(Created.class).value())
128+
)
129+
130+
||
131+
132+
(
133+
ENTRY_DELETE.equals(eventKind) &&
134+
method.isAnnotationPresent(Deleted.class) &&
135+
path.matches(method.getAnnotation(Deleted.class).value())
136+
)
137+
138+
||
139+
140+
(
141+
ENTRY_MODIFY.equals(eventKind) &&
142+
method.isAnnotationPresent(Modified.class) &&
143+
path.matches(method.getAnnotation(Modified.class).value())
144+
)
145+
146+
;
147+
}
111148
}

jca/mdb-filewatcher/src/main/java/org/javaee7/jca/filewatch/event/Created.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
*/
1717
package org.javaee7.jca.filewatch.event;
1818

19+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
20+
1921
import java.lang.annotation.Retention;
20-
import java.lang.annotation.RetentionPolicy;
2122

2223
/**
2324
* @author Robert Panzer (robert.panzer@me.com)
2425
*/
25-
@Retention(RetentionPolicy.RUNTIME)
26+
@Retention(RUNTIME)
2627
public @interface Created {
2728

2829
public String value() default ".*";

jca/mdb-filewatcher/src/main/java/org/javaee7/jca/filewatch/event/Deleted.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
*/
1717
package org.javaee7.jca.filewatch.event;
1818

19+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
20+
1921
import java.lang.annotation.Retention;
20-
import java.lang.annotation.RetentionPolicy;
2122

2223
/**
2324
* @author Robert Panzer (robert.panzer@me.com)
2425
*/
25-
@Retention(RetentionPolicy.RUNTIME)
26+
@Retention(RUNTIME)
2627
public @interface Deleted {
2728

2829
public String value() default ".*";

jca/mdb-filewatcher/src/test/java/org/javaee7/jca/filewatch/FileEvent.java renamed to jca/mdb-filewatcher/src/main/java/org/javaee7/jca/filewatch/event/FileEvent.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
package org.javaee7.jca.filewatch;
17+
package org.javaee7.jca.filewatch.event;
1818

1919
import java.io.File;
2020

@@ -46,4 +46,9 @@ public File getFile() {
4646
public Type getType() {
4747
return type;
4848
}
49+
50+
@Override
51+
public String toString() {
52+
return "Type: " + type.name() + " File: " + file.getName();
53+
}
4954
}

jca/mdb-filewatcher/src/main/java/org/javaee7/jca/filewatch/event/Modified.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
*/
1717
package org.javaee7.jca.filewatch.event;
1818

19+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
20+
1921
import java.lang.annotation.Retention;
20-
import java.lang.annotation.RetentionPolicy;
2122

2223
/**
2324
* @author Robert Panzer (robert.panzer@me.com)
2425
*/
25-
@Retention(RetentionPolicy.RUNTIME)
26+
@Retention(RUNTIME)
2627
public @interface Modified {
2728

2829
public String value() default ".*";

0 commit comments

Comments
 (0)