Hi everybody,
me and Simone spent few days trying to obtain a working javaflow again in 
cocoon 2.2, and to understand how it works deeply; we would like to report our 
achievements and problems.

We started trying to obtain a complete system (reloading, runtime 
instrumentation etc..). But then scaled down step by step and arrived to the 
problem which is stopping us right now.

We are working with the flow class instrumented statically, as well as 
AbstractContinuable, FormInstance and the Invoker.

The form shows up correctly, but when we submit the form, ClassCastException :

Caused by: java.lang.ClassCastException:
org.apache.cocoon.samples.flow.java.SimpleFlow
 at org.apache.cocoon.components.flow.java.Invoker.run(Invoker.java)
 at 
org.apache.commons.javaflow.bytecode.StackRecorder.execute(StackRecorder.java:95)
 at org.apache.commons.javaflow.Continuation.continueWith(Continuation.java:170)
 at 
org.apache.cocoon.components.flow.java.JavaInterpreter.handleContinuation(JavaInterpreter.java:182)
 at 
org.apache.cocoon.components.treeprocessor.sitemap.CallFunctionNode.invoke(CallFunctionNode.java:98)

When the form is rendered, the JavaInterprer instanciates an Invoker to pass to 
the Continuation object; the Invoker is responsible to call the Javaflow method 
that has been passed by the JavaInterpreter, using reflection. Since the class 
must be enhanced, also the method.invoke instruction should be, but it seems 
that the BcelClassTransformer doesn't parse this case (In this part we has 
serious difficulties to understand the code because we're not to deep into the 
JVM bytecode specs and stuff like that).

In fact, if we replace the "method.invoke(o)" with "o.method()" (no reflection 
involved) it works correctly.

IIUC the core of the instrumentation is done into the rewrite method, that 
parses the bytecode operations and decides what to do; adding a
block that identifies the invoke operation and adds a method call would work; 
we tried unluckily to implement it, maybe someone could help us to understand 
how to do it.

As I said, we arrived to this error by scaling down our target, our first test 
was to enhance a simple Java class, out of cocoon environment, using the 
FilesystemAlterationMonitor, that monitors a certain folder (in this case the 
folder containing the class file of the Javaflow) and enhance it, if it has 
been changed. We found a ClassFormatException ( java.lang.ClassFormatError: 
Incompatible magic value -272646673 in class file jci/Simple ) trying to read 
the original bytecode of the class; debugging the code we discovered that the 
ReloadingListener is using a FileReader to read the bytecode of the class; the 
FileReader parses the byte stream depending on a certain char encoding. so the 
bytecode is not recognized by the classloader. Using a FileInputStream it works 
(ReloadingClassLoaderTestCase confirms; with the original FileReader 
implementation it fails).

Then we tried to integrate the FilesystemAlterationMonitor with the cocoon 
classloader configuration, in order to automatically reload and enhance the 
Javaflows when changed, but we faced with some problems.

- The FilesystemAlterationMonitor always notifies the changes of those classes 
that are enhanced; the check is based on file.getLastModified() value, but 
every time the value is lower then the last one, so the change notification is 
triggered. We didn't investigate more.

- The FileResourceStore fails trying to get the file by the filesystem:

private File getFile(final String pResourceName) {
 final String fileName = pResourceName.replace('/',File.separatorChar);
 return new File(root, fileName);
}

where pResourceName = "org.apache.cocoon.samples.flow.java.SimpleFlow"; 
changing the return statement to :

return new File(root, fileName.replace('.',File.separatorChar).concat(".class"));

it seems to work correctly.

Before send some patches we'd like to know if we're investigating in the right 
direction or not.

We can also provide our temporary changes to the javaflow poms in order to 
enhance the JavaInterpreter and the javaflow classes at build time, using the 
RewriteAntTask provided by commons-javaflow and some fix to the 
cocoon-javaflow-sample block.

Regards,

 Maurizio and Simone

Reply via email to