make
but it doesn't work!ant test
but it doesn't work!ant uml
but it doesn't work!ant ramidoc
, ant
jacobdoc
or ant docs
but it doesn't work!ant javadoc
but the generated
documentation contains no link to standard Java class (such as
java.util.Map
)!Foo
class,
compiled it with the Jaya compiler, but when I instantiate
jaya.Foo()
, the StackOverflowError
is
thrown!build.xml!
java.lang.NoClassDefFoundError: jaya/your/ClassName
is
thrown!mandala.util.ThreadPool
throws
java.lang.ExceptionInInitializerError ... Caused by:
java.security.AccessControlException: access denied
(java.util.PropertyPermission java.util.PropertyPermission
mandala.util.ThreadPool.min read)
!AsynchronousReferencePair
class for?java
mandala.jacob.remote.rmi.RMIActiveMap
but the exception
java.lang.ExceptionInInitializerError ... Caused by:
java.security.AccessControlException: access denied
(java.util.PropertyPermission java.util.PropertyPermission
mandala.util.ThreadPool.min read)
is thrown!java.io.NotSerializableException:
mandala.rami.impl.BasicFutureFactory$BasicFutureComponents
is
thrown (after probably many other exceptions)RMIActiveMap
, the exception
java.rmi.UnmarshalException: error unmarshalling arguments; nested
exception is: java.lang.ClassNotFoundException: your.ClassName
is
thrown (after probably many other exceptions)To run a Mandala based code, you need a JRE >= 1.4.
To compile Mandala, you need a JDK >= 1.4.
Jikes compiler >= 1.18 is known to compile Mandala.
Jikes compile <= 1.14 do not compile Mandala due to a Jikes
bug.
Mandala is currently two subpackages: RAMI and JACOb.
RAMI (Reflective Asynchronous Method Invocation) provides
asynchronism on any objects using reflection.
JACOb (Java Active Container of Objects) uses the active
container concept which allows any public method of any object
to be invoked remotely.
Hence, RAMI + JACOb provides asynchronous remote method
invocation.
I needed a good term. It sounds good to me!
Mandala is written in 100% Java, and the Mandala is a Sanskrit word,
a language spoken in India and Indonesia where the Java island is
(please, tell me if I'm wrong, I'm not really sure).
I founded a French definition of Mandala: "N'importe quelle forme ou dessin géometrique qui est symmétrique, [...], d'une apparence compliquée".
And another one: "The mandala is a reflection of the true face of the Universe".
Hence, Mandala is related to Java (more or less), to reflection/symmetric (i know the words are not in the same context!), and to apparently complex structure. This reflect the Mandala Java project!
If you are afraid of threads, you may use RAMI which enables
implicit multithreading. Threads are really good to express some things
but are really complex to program. Moreover, Java tends to confuse
things naming the Java class which is responsible of threads creation
java.lang.Thread
. With RAMI, you can forget almost
everything about threads. But hey!, you must deal with asynchronism,
otherwise why do you need multithreading/asynchronism? Hence, you still
must ensure shared variables are properly synchronized, use lock
carefully to prevent deadlocks, and use wait()/notify()
in
a good way. But, for example, using RAMI, you can access an object
which is not thread safe still asynchronously using a "single threaded
semantic" (See documentation).
If you want to write distributed application but you're not confortable with RMI/CORBA/SOAP or anything else, consider JACOb. JACOb is based on the active container concept and allows your object services to be designed without the remote property in mind. You don't need to inherit any class, implement any interface nor compile anything! Just write you're object insert it in a remote active map and you're object is remotely accessible! Moreover, using RAMI and JACOb, you're object can be asynchronously remotely accessible! You also can take a given object, even if you didn't wrote its class and make it asynchronously remotely accessible by inserting it in a remote active map!
If any objects may become asynchronously remotely accessible in Mandala, the use of reflection is not really practical for developers and it brings new problems such as strong typing. Hence, for clients who want to use you're object, a proxy is used to provide some transparency. Two transparency mechanism are provided in Mandala. The Jaya compiler provides semi-transparent proxy (see documentation for details).
Note that you must set your JVM environment (either the CLASSPATH
variable or the java -classpath
option or the 'ext'
directory) to be able to load classes generated by jayac.
Jaya sounds really similar to Java, it sounds good to me and it means "victory in Sanskrit".
You need Ant properly installed and configured to compile Mandala!
You need JUnit properly installed and configured to run the Mandala test suite.
You need UMLDoclet properly installed and configured to make the Mandala UML schemas. Currently, UMLDoclet doesn't work. I've send a mail to its author and I'm waiting for a reply...
You need LaTeX properly installed and configured to compile the Mandala documentation.
<link offline="true" href="http://java.sun.com/products/jdk/1.4/docs/api" packagelistLoc="/usr/local/java/docs/jdk1.4/api"/>
"/usr/local/java/docs/jdk1.4/api"
by
"C:\TMP"
.ant javadoc
, that's all!
The mandala.jar
file must be in your your classpath or
in the JRE library extension directory (see INSTALL for more
details).
Your classpath must contain the "Examples/classes"
directory.
Note that Mandala examples may use the semi-transparent mechanism
provided by RAMI (see RAMI documentation for more explanation). In this
case, asynchronous proxy classes are generated by the Jaya
compiler. Those classes are usually written to a "JAYA"
directory. If you use the build.xml
given with the Mandala
examples, those files are deleted after being compiled into the classes
directory (see build.xml
for details). So having
Examples/classes
into your classpath is sufficient. But if
you compile them by hand (running the
mandala.rami.transparency.semi.JayaCompiler
and
javac
on the generated classes), then you must
modify your classpath so it contains the classes you have compiled by
hand.
Foo
class,
compiled it with the Jaya compiler, but when i instantiate
jaya.Foo()
, the StackOverflowError
is
thrown!
This is a bug in the JayaCompiler which generates bad source file
when you compile a class which is in the anonymous package. Your
Foo
class must resides in a named package (i.e. your
Foo.java
file must begin with package foo;
or something the like!). Sorry, we'll working on this bug later. Feel
free to contact us, if this is a bug really important to you!
build.xml
!
Yes, some tests requires more operations than just running a
build.xml
. For example, testing a
RemoteCollection
(such as RMICollection
),
requires a running server. Hence, those test must be run on their own
using for example the following command:
java -classpath \ $MANDALA/classes:$MANDALA/test/classes:$JUNIT/junit.jar \ junit.textui.TestRunner \ mandala.jacob.remote.protocols.rmi.RMICollectionTester
You may also replace textui
by swingui
and
use the graphic interface to choose the class to test.
java.lang.NoClassDefFoundError: jaya/your/ClassName
is
thrown!
This means that you have compiled your.ClassName
using
the Jayac compiler, which has generated classes into a directory but
that the JVM doesn't know where to find those generated classes. Modify
the classpath either by setting the CLASSPATH variable or using the
java -classpath
option.
mandala.util.ThreadPool
throws
java.lang.ExceptionInInitializerError ... Caused by:
java.security.AccessControlException: access denied
(java.util.PropertyPermission java.util.PropertyPermission
mandala.util.ThreadPool.min read)
!
You're using a security manager, which do not allow the
ThreadPool
to read some properties. Modify your
.java.security.policy
so it allows your code to read
mandala properties. If you've never heard about Java security see Permissions
in the JavaTM 2 SDK for an overview of the Java security
mechanism.
You must add the following line to your .java.policy
file
:
grant { // Other permissions // ... permission java.util.PropertyPermission "mandala.*", "read"; // ... };
RAMI is based on the asynchronous reference concept where if you've
o
and o'
two objects, ar(o)
an
asynchronous reference on o
and ar'(o')
an
asynchronous reference on o'
then:
ar(o) == ar'(o') <==> o == o'Hence, comparing two asynchronous references is just a matter of using the
'=='
operators as with java standard synchronous
reference. You don't have to use equals()
for comparing
two asynchronous references! This rule is enforced by the singleton
design provided in Mandala.
This may occurs for many reasons:
You're using a single-threaded semantic to invoke a method
which is calling the Object.wait()
and the corresponding
Object.notify()
is invoked in a method which shares the
same semantic.
Solutions: if both method (the one which calls
wait()
and the one which invokes the corresponding
notify()
) are in the same class, don't use a
single-threaded semantic; otherwise don't share the same
single-threaded semantic across asynchronous references (If you're
using the asynchronous policy provided, this should not happened).
You're using a single-threaded semantic on an object and using
a callback which is calling wait()
, or any RAMI
InvocationEventsWaiter
's method (wait*()
)
either explicitly or implicitly by invoking a synchronous method
invocation using RAMI (a proxy.f()
call where
f()
also have a 'rami_'
prefix).
Solutions: do not use a single-threaded semantic or prevent
every wait*()
call into the callback. If the wait is
implicit, replace you're RAMI synchronous method invocation by an
asynchronous one or, if possible, use a Java standard synchronous
reference
(rami_proxy.getAsynchronousReference().getObject()
returns the synchronous reference).
You're using a threadpooled-policy, the threadpool used by the
policy has a maximum amount of threads set and each asynchronous
method invocation runs a wait*()
method. Each threads of
the threadpool are waiting and no more threads are accepted by it
because it has reached its maximum limits. Hence the
deadlock.
Solutions: use a threaded policy (single-threaded semantics
are worse in this context), but it may not help anymore since you may
reached the maximum number of threads a process are allowed to
create. This limit may be set by the operating system or by the
hardware. A better solution is to redesign you're application so each
of you're method do not invoke a wait*()
method.
Each semantics has its advantages and its inconvenient.
Single-threaded semantic are the best choice for asynchronous references on objects which are not thread-safe. But they are subject to deadlocks.
Fifo policy ensure that the orders in which methods will be executed asynchronously is the same as their invocation order on the related asynchronous reference;
Random policy executes the method asynchronously in a random order;
Concurrent-semantic are the best for performance since they provides concurrency and if the hardware allows it (multiple processors or hyperthreading) parallelism. But they are not recommended for asynchronous references on object which are not thread-safe unless you're invoking only the methods which are thread-safe.
Threaded-policy throws a thread on each asynchronous method invocation which is a costly operation. But the threaded-semantic is the less subject to deadlock;
Threadpooled-policy uses a threads pool to prevent threads
creation on each method invocation. Hence, it is probably the
most efficient for asynchronous references on thread-safe
objects. But be aware that since max-bounded threadspool
are subject to deadlocks (see I've a
deadlock), the threadpooled-policy is too (be relaxed,
ThreadPool.max
bound is set to Integer.MAX_VALUE by
default!).
The callback mechanism allows event-driven programming. For example instead of writing:
FutureClient future = ramiProxy.rami_f(args); doSomethingElse(); try{ handleResult(future.waitForResult()); }catch(Exception e) { handleException(e); }You can write:
rami_proxy.rami_f(args, new Callback() { public void done(InvocationInfo i, MethodResult r) { try{ handleResult(r.getReturnedResult()); }catch(Exception e) { handleException(e); } } }); doSomethingElse();But be aware that in your callback code, you must not invoke any
wait*()
method either implicitly neither
explicitly. You're code would be subject to deadlocks under some
asynchronous semantic otherwise (see I've a
deadlock)!
AsynchronousReferencePair
allows the chaining of
asynchronous references. Usually chain of asynchronous references are
used to provide full asynchronism on an object. See the
documentation for details.
Active container is the concept which has been modeled in
pi-calculus
.
ActiveMap
are a Java implementation of this concept.
A remote active map can be accessed remotely and the stored objects it contains also. An active map which is not remote, allows a developper to develop its applications locally using local active map for testing. Since debugging a multithreaded application is a difficult task, the developper can deal with threads related problems independently of the remote problems. When threads related problems are solved, remote related ones can start to be debugged.
java
mandala.jacob.remote.rmi.RMIActiveMap
but the exception
java.lang.ExceptionInInitializerError ... Caused by:
java.security.AccessControlException: access denied
(java.util.PropertyPermission java.util.PropertyPermission
mandala.util.ThreadPool.min read)
is thrown!
See the RAMI security exception related to ThreadPool above.
You must provide (accept, connect, resolve) actions to both the
remote active map host and its client host within
SocketPermission such as in the following
.java.policy
file:
grant { // Other permissions // ... permission java.util.PropertyPermission "mandala.*", "read"; permission java.net.SocketPermission "*", "accept, connect, resolve"; };
java.io.NotSerializableException:
mandala.rami.impl.BasicFutureFactory$BasicFutureComponents
is
thrown (after probably many other exceptions)
When using remote active map, you must change the future factory to
a factory suited to the protocol used by your remote active map. For
example, when an RMIActiveMap
used, you may set the
FutureFactory
to an RMIFutureFactoryWrapper
instance as in the following code:
mandala.rami.FutureFactory futureFactory = new mandala.jacob.remote.protocols.rmi .RMIFutureFactoryWrapper(SORFactory.getDefaultFutureFactory()); mandala.rami.Framework.setFactory(new mandala.jacob .SORFactory(activeMap, futureFactory));Note that the
SORFactory
automatically wrap the default
FutureFactory
using the
RemoteActiveMap.getDefaultFutureFactoryWrapper()
method
when an active map is remote.
java.rmi.UnmarshalException: error unmarshalling
arguments; nested exception is: java.lang.ClassNotFoundException:
your.ClassName
is thrown (after probably many other
exceptions)
This is not a Mandala issue but an RMI one! But since I'm not an
evil, I'll give you the reason of the problem and its solution. The
RMIActiveMap
runs in a JVM which has its own
classpath. Hence, it doesn't know the class named
your.ClassName
. When you run the client, you must tell the
RMI framework where it shall load the class it doesn't know. This
information is given by the java.rmi.server.codebase
property. If the server and the client shares the same disk, you can
throw your application by the following command:
java -Djava.rmi.server.codebase=file:///PATH/TO/YOUR/CLASSPATH your.ApplicationIf the server and the client don't share the same disk, you must have a web server configured to serve your classes or your jar files and then you run:
java -Djava.rmi.server.codebase=http:///server:port/PATH/TO/YOUR/CLASSPATH your.ApplicationSee Sun RMI tutorials if these doesn't work (and tell me why).
Note that Mandala provides a simple HTTP server preventing end user
from the installation of a real web server. The class is
mandala.util.HTTPServer
. This web server is not to be used
for real applications, it is absolutely not secure! You've been
warn!