hello guys!
I have some trouble / misunderstanding concerning DMI. What I basically try is to avoid JMS as we use Terracotta 2.6.4 anyway. So in my special case each VM runs some backend functionality but I need a way to "control" all these different instances (one per vm) from a central place without JMS/JMX. This is where I thought DMI could be of help. So regardless on which JVM you call a backend method this call should be transparently propagated to all others "backends" in the cluster.
Please see sample project.
Backendprocess (this will do all the heavy backend work. one instance per vm):
Code:
import java.util.UUID;
public class HeavyNonPortableService
{
final UUID _nonPortableServiceExampleOnlyField;
public HeavyNonPortableService()
{
_nonPortableServiceExampleOnlyField = UUID.randomUUID();
System.out.println("HeavyNonPortableService created [" + _nonPortableServiceExampleOnlyField + "] instance=" + this);
}
public void serviceMethod(final String s)
{
System.out.println("serviceMethod [" + s + "] for [" + _nonPortableServiceExampleOnlyField + "] instance=" + this);
}
}
a simple service wrapper to introduce DMI. This service wrapper is shared but basically should do the DMI magic in each VM and pass the message (method call) to the backend part. Parts of it are stolen from the terracotta samples:
Code:
public class ServiceWrapper
{
public class DMI
{
public void internalBroadcast(final String s)
{
_heavyNonPortableService.serviceMethod(s);
}
}
private final HeavyNonPortableService _heavyNonPortableService;
private final DMI _dmi;
public ServiceWrapper()
{
_heavyNonPortableService = new HeavyNonPortableService();
_dmi = new DMI();
}
public void broadcastMethod(final String s)
{
_dmi.internalBroadcast(s);
}
}
and this is the tc-config
Code:
<?xml version="1.0" encoding="UTF-8"?>
<con:tc-config xmlns:con="http://www.terracotta.org/config">
<system>
<configuration-model>production</configuration-model>
</system>
<servers>
<server host="%i" name="local">
<dso-port>9510</dso-port>
<data>terracotta</data>
<logs>terracotta/server-logs</logs>
<statistics>terracotta/cluster-statistics</statistics>
</server>
</servers>
<clients>
<logs>/data/terracotta/logs/%(node.name)/</logs>
<statistics>/data/terracotta/client-statistics/%D/%(node.name)</statistics>
</clients>
<application>
<dso>
<roots>
<root>
<field-name>ServiceWrapper._dmi</field-name>
<root-name>Schedule_DMI</root-name>
</root>
</roots>
<instrumented-classes>
<include>
<class-expression>ServiceWrapper$DMI</class-expression>
</include>
</instrumented-classes>
<locks>
<autolock auto-synchronized="true">
<method-expression>* ServiceWrapper.__INIT__(..)</method-expression>
<lock-level>write</lock-level>
</autolock>
</locks>
<distributed-methods>
<method-expression>void ServiceWrapper$DMI.internalBroadcast(..)</method-expression>
</distributed-methods>
<transient-fields>
<field-name>ServiceWrapper._heavyNonPortableService</field-name>
</transient-fields>
</dso>
</application>
</con:tc-config>
and finally the "main" to start the service on each machine
Code:
/**
* -Xbootclasspath/p:/terracotta-2.6.4/lib/dso-boot/dso-boot-hotspot_osx_150_16.jar
* -Dtc.install-root="/terracotta-2.6.4"
* -Dtc.config=localhost:9510
*/
public class Sample_TerracottaDMI
{
public static void main(final String[] args)
{
final ServiceWrapper serviceWrapper = new ServiceWrapper();
serviceWrapper.broadcastMethod("hello");
try {
Thread.currentThread().join();
// Thread.sleep(60000); // block, whatever
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
The following output is produced in case of two running applications
Code:
VM1
HeavyNonPortableService created [04bfb9a5-6b3b-4585-8836-95a208e7a469] instance=HeavyNonPortableService@f71ad4
serviceMethod [hello] for [04bfb9a5-6b3b-4585-8836-95a208e7a469] instance=HeavyNonPortableService@f71ad4
serviceMethod [hello] for [04bfb9a5-6b3b-4585-8836-95a208e7a469] instance=HeavyNonPortableService@f71ad4
as you can see vm1 recognizes two calls to the service method which is correct (one call from each started vm). But VM2 is in trouble:
Code:
HeavyNonPortableService created [55bc94d1-4761-4b91-a667-ce38440118b3] instance=HeavyNonPortableService@851105
Exception in thread "main" java.lang.NullPointerException
at ServiceWrapper$DMI.__tc_dmi_internalBroadcast(ServiceWrapper.java:7)
at ServiceWrapper$DMI.internalBroadcast(ServiceWrapper.java)
at ServiceWrapper.broadcastMethod(ServiceWrapper.java:24)
at Sample_TerracottaDMI.main(Sample_TerracottaDMI.java:11)
Thanks in advance
Jens