How to use call answer outside the domain of web apps

0 views
Skip to first unread message

peter

unread,
Nov 14, 2007, 11:58:03 AM11/14/07
to rife-users
I am exploring rife continuations for use in an embedded event driven
environment (J2ME, foundation profile, which is java 1.3 based). I can
now run a small app using just pause() but have problems doing call-
answer.

The purpose is to perform a sequence of blocking calls:

public static class Sequence extends AbstractContinuableObject
{
public void execute()
{
String reply = (String) call(CallTarget.class);
System.out.println("reply=" + reply);

reply = (String) call(CallTarget.class);
System.out.println("reply=" + reply);

reply = (String) call(CallTarget.class);
System.out.println("reply=" + reply);
}
}

where CallTarget (which does the blocking call) looks like this:

public static class CallTarget extends AbstractContinuableObject
{
static int count = 0;

public void execute()
{
pause();
answer("hello " + count++);
}
}

The Sequence is started like this:

MyContinuableRunner runner = new MyContinuableRunner();
String id = runner.start("CallAnswerTest$Sequence"/
*Sequence.class.getName()*/);


I wrote an URLContinuableClassloader derrived from URLClassloader and
which does about the same thing as BasicContinuableClassLoader. The
jvm uses URLContinuableClassloader as application class loader so it
will load all my application classes.

When attempting to load Sequence I get following stacktrace:

transforming CallAnswerTest$Sequence
Exception in thread "main" java.lang.ClassNotFoundException:
CallAnswerTest$Sequence
java.util.EmptyStackException
at java.util.Stack.pop(Stack.java:77)
at
com.uwyn.rife.continuations.instrument.ResumableMethodAdapter.visitMethodInsn(ResumableMethodAdapter.java:
378)
at com.uwyn.rife.asm.ClassReader.accept(ClassReader.java:1340)
at com.uwyn.rife.asm.ClassReader.accept(ClassReader.java:395)
at
com.uwyn.rife.continuations.instrument.ContinuationsBytecodeTransformer.transformIntoResumableBytes(ContinuationsBytecodeTransformer.java:
68)
at
com.uwyn.rife.continuations.basic.URLContinuableClassLoader.loadClass(URLContinuableClassLoader.java:
195)
at
com.uwyn.rife.continuations.basic.BasicContinuableRunner.run(BasicContinuableRunner.java:
171)
at
com.uwyn.rife.continuations.basic.BasicContinuableRunner.start(BasicContinuableRunner.java:
85)
at CallAnswerTest.go(CallAnswerTest.java:59)
at CallAnswerTest.main(CallAnswerTest.java:50)

I guess I am missing something basic regarding the use of call-answer.
Who can give me some pointers on how to use call-answer outide the
domain of web apps?

Geert Bevin

unread,
Nov 14, 2007, 2:51:51 PM11/14/07
to rife-...@googlegroups.com
Hi Peter,

I created a similar project, called RIFE/Workflow. You can check it
out from SVN:
http://svn.rifers.org/rife-workflow/trunk/

It uses continuations for a workflow engine and also has renamed
'call' to 'waitForEvent', which makes more sense.

In your case, "CallAnswerTest$Sequence" is not a valid classname in
the Java language. Inner classes are also referenced with a dot, hence
I think that "CallAnswerTest.Sequence" should work.

Hope this helps,

Geert

--
Geert Bevin
Terracotta - http://www.terracotta.org
Uwyn "Use what you need" - http://uwyn.com
RIFE Java application framework - http://rifers.org
Music and words - http://gbevin.com

peter

unread,
Nov 15, 2007, 6:49:20 AM11/15/07
to rife-users
Hi Geert,

Thanks for your help.

1. There should really be a $ in the inner class name as it is a
string passed to loadClass(), not a class name in java source code.

2. The exception was thrown during bytecode rewrite of my
Sequence.execute() method. This snippet of ResumableMethodAdapter
throws the exception:
...
else if (mConfig.getCallMethodName().equals(name) && ...
{
// store the call target
debugMessage("CONT: call : storing call target");
mMethodVisitor.visitVarInsn(ASTORE, mCallTargetIndex);

// pop the ALOAD opcode off the stack
debugMessage("CONT: call : undoing method call");
mMethodVisitor.visitInsn(POP);

TypesContext context = mTypes.nextPauseContext();
Stack<String> stack = context.getStackClone();
stack.pop(); <-------
debugMessage("CONT: call : saving operand stack");
saveOperandStack(stack);
...

I interpreted this as me using call() in a location where it is not
allowed. (and maybe it is not allowed)

Allthough I have not enough understanding of the code I tried
modifying it like this:
if(!stack.empty())
stack.pop();

This made my call-answer sample run!
Could you comment on what is happening?

3. About the rife-workflow project: I was surprised to see that it
uses multiple threads. What is the rationale for this? My goal is to
perform a sequence of blocking calls, all on the same thread to avoid
synchronization issues due to preemtive thread switching. I guess the
threads in rife-workflow don't have a lot of interaction because they
just run until a blocking action is performed and then they exit.
Still I would think using just one thread is also possible.
> Terracotta -http://www.terracotta.org
> Uwyn "Use what you need" -http://uwyn.com
> RIFE Java application framework -http://rifers.org
> Music and words -http://gbevin.com- Hide quoted text -
>
> - Show quoted text -

Geert Bevin

unread,
Nov 15, 2007, 7:07:11 AM11/15/07
to rife-...@googlegroups.com
Hi Peter,

I made a fix related to this last week, can you please try with the
last snapshot of RIFE/Continuations?
http://rifers.org/downloads/rife/snapshots/rife-1.6.2-snapshot-20071110/

If you still get the exception, would it be possible to provide an
archive of your project (possibly in private email), so that I can
reproduce the exception here?

> 3. About the rife-workflow project: I was surprised to see that it
> uses multiple threads. What is the rationale for this? My goal is to
> perform a sequence of blocking calls, all on the same thread to avoid
> synchronization issues due to preemtive thread switching. I guess the
> threads in rife-workflow don't have a lot of interaction because they
> just run until a blocking action is performed and then they exit.
> Still I would think using just one thread is also possible.

I suppose this depends on what your use-case is, the purpose of the
multi-threading is that in a workflow system you can have several long
running tasks that are active at once, without necessarily being
dependent on other tasks. I merely pointed you to the project so that
you could see an example of call/answer outside of a web app context.
However, it would be cool to figure out a way to add the single-
threaded behavior to RIFE/Workflow since if you need this, others
might too. Maybe the task class can contain a String getThreadName()
method with a default implementation of 'null'. When that's not null,
tasks with the same thread name are all executed in the same single
thread.

What do you think? Care to have a shot at adding this to RIFE/Workflow?

Take care,

Geert

Reply all
Reply to author
Forward
0 new messages