Commit 3af4b74a authored by Lionel Seinturier's avatar Lionel Seinturier

WIP: support for @EndsConversation methods in non @Conversational interface.

parent 677d8787
/***
* OW2 FraSCAti Tinfi
* Copyright (C) 2010 INRIA, USTL
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: frascati@ow2.org
*
* Author: Lionel Seinturier
*/
package org.ow2.frascati.tinfi;
import org.osoa.sca.annotations.EndsConversation;
/**
* Interface implemented by components for testing callbacks with the
* conversation scope policy.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
* @since 1.3.2
*/
public interface ScopeConvCallbackItf {
/**
* Notify a callback message.
*/
public void onMessage( String msg );
/**
* Notify a callback message and end the conversation just after.
*/
@EndsConversation
public void onMessageEndsConversation( String msg );
}
......@@ -26,39 +26,38 @@ package org.ow2.frascati.tinfi;
import org.osoa.sca.annotations.Reference;
import org.osoa.sca.annotations.Scope;
/**
* Component implementation used for testing the conversational scope policy.
* Component implementation for testing the conversation scope policy.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
*/
@Scope("COMPOSITE")
public class ScopeConvClientImpl implements ScopeConvItf {
public class ScopeConvClientImpl implements ScopeConvItf, ScopeConvCallbackItf {
@Reference
public ScopeConvItf s;
/**
* Return the content instance implementing the component.
*
* @param millis the length of time in milliseconds before returning the call
* @return the instance implementing the component
*/
public Object first( long millis ) {
return s.first(millis);
}
/**
* Return the content instance implementing the component.
*/
public Object second() {
return s.second();
}
/**
* Return the content instance implementing the component.
*/
public Object third() {
return s.third();
}
public void callback() {
s.callback();
}
public void callbackEndsConversation() {
s.callbackEndsConversation();
}
public void onMessage( String msg ) {}
public void onMessageEndsConversation( String msg ) {}
}
......@@ -23,12 +23,12 @@
package org.ow2.frascati.tinfi;
import org.osoa.sca.annotations.Callback;
import org.osoa.sca.annotations.ConversationAttributes;
import org.osoa.sca.annotations.Scope;
/**
* Component implementation used for testing the conversational scope policy.
* Component implementation for testing the conversation scope policy.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
*/
......@@ -36,12 +36,9 @@ import org.osoa.sca.annotations.Scope;
@ConversationAttributes(maxAge="2 seconds", maxIdleTime="1 seconds")
public class ScopeConvImpl implements ScopeConvItf {
/**
* Return the content instance implementing the component.
*
* @param millis the length of time in milliseconds before returning the call
* @return the instance implementing the component
*/
@Callback
public ScopeConvCallbackItf cb;
public Object first( long millis ) {
try {
Thread.sleep(millis);
......@@ -53,17 +50,19 @@ public class ScopeConvImpl implements ScopeConvItf {
return this;
}
/**
* Return the content instance implementing the component.
*/
public Object second() {
return this;
}
/**
* Return the content instance implementing the component.
*/
public Object third() {
return this;
}
public void callback() {
cb.onMessage("");
}
public void callbackEndsConversation() {
cb.onMessageEndsConversation("");
}
}
......@@ -23,23 +23,26 @@
package org.ow2.frascati.tinfi;
import org.osoa.sca.annotations.Callback;
import org.osoa.sca.annotations.Conversational;
import org.osoa.sca.annotations.EndsConversation;
/**
* Interface implemented by components used for testing the conversational scope
* Interface implemented by components for testing the conversation scope
* policy.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
*/
@Conversational
@Callback(ScopeConvCallbackItf.class)
public interface ScopeConvItf {
/**
* Return the content instance implementing the component.
*
* @param millis the length of time in milliseconds before returning the call
* @return the instance implementing the component
* @param millis
* the time duration in milliseconds before returning the call
* @return the instance implementing the component
*/
public Object first( long millis );
......@@ -53,4 +56,16 @@ public interface ScopeConvItf {
*/
@EndsConversation
public Object third();
/**
* Invoke the {@link ScopeConvCallbackItf#onMessage(String)} method on the
* callback interface.
*/
public void callback();
/**
* Invoke the {@link ScopeConvCallbackItf#onMessageEndsConversation(String)}
* method on the callback interface.
*/
public void callbackEndsConversation();
}
......@@ -24,7 +24,7 @@
package org.ow2.frascati.tinfi;
/**
* Interface implemented by components used for testing scope policies.
* Interface implemented by components for testing scope policies.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
*/
......@@ -35,19 +35,18 @@ public interface ScopeItf extends Runnable {
* given amount of time before returning to simulate concurrent calls.
*
* @param millis
* the length of time in milliseconds before returning the call
* the time duration in milliseconds before returning the call
* @return the instance implementing the component
*/
public Object getContent( long millis );
/**
* Invoke the {@link #getContent(long)} operation on itself using the
* loopback reference c.
* Invoke the {@link #getContent(long)} operation on itself.
*
* @return
* an array of two elements with the instance implementing the
* component as the first element, and the value returned by {@link
* #getContent(long)} as a second element.
* #getContent(long)}=0 as the second element.
*/
public Object[] loop();
}
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE definition PUBLIC "-//objectweb.org//DTD Fractal ADL 2.0//EN" "classpath://org/objectweb/fractal/adl/xml/standard.dtd">
<definition name="org.ow2.frascati.tinfi.ScopeConversation" >
<definition name="org.ow2.frascati.tinfi.ScopeConversation">
<interface name="r" role="server" signature="org.ow2.frascati.tinfi.ScopeConvItf" />
<component name="client">
<interface name="r" role="server" signature="org.ow2.frascati.tinfi.ScopeConvItf" />
<interface name="s" role="client" signature="org.ow2.frascati.tinfi.ScopeConvItf" />
<content class="org.ow2.frascati.tinfi.ScopeConvClientImpl"/>
<content class="org.ow2.frascati.tinfi.ScopeConvClientImpl" />
<controller desc="scaPrimitive" />
</component>
<component name="server">
<interface name="s" role="server" signature="org.ow2.frascati.tinfi.ScopeConvItf" />
<content class="org.ow2.frascati.tinfi.ScopeConvImpl"/>
<content class="org.ow2.frascati.tinfi.ScopeConvImpl" />
<controller desc="scaPrimitive" />
</component>
......
......@@ -26,6 +26,9 @@ package org.ow2.frascati.tinfi;
import org.junit.Assert;
import org.junit.Test;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.factory.InstantiationException;
import org.objectweb.fractal.util.Fractal;
import org.osoa.sca.ConversationEndedException;
import org.osoa.sca.annotations.Scope;
......@@ -189,7 +192,7 @@ public class ScopeTestCase {
Object[] contents = itf.loop();
Assert.assertEquals(
"loop() should return an array of lenght 2",
"loop() should return an array of length 2",
2, contents.length);
Assert.assertSame(
"Reentrant calls on a request-scoped component should be handled by the same instance",
......@@ -217,7 +220,7 @@ public class ScopeTestCase {
itf.third();
try {
itf.first(0);
Assert.fail("Conversation should have been ended");
Assert.fail("Conversation should have ended");
}
catch( ConversationEndedException cee ) {}
}
......@@ -285,4 +288,28 @@ public class ScopeTestCase {
}
catch( ConversationEndedException cee ) {}
}
/**
* @since 1.3.2
*/
public void testScopeConversationCallback()
throws
ClassNotFoundException, InstantiationException, IllegalAccessException,
IllegalLifeCycleException, NoSuchInterfaceException,
java.lang.InstantiationException {
String adl = getClass().getPackage().getName()+".ScopeConversation";
String service = "r";
ScopeConvItf itf =
TinfiDomain.getService(adl,ScopeConvItf.class,service);
itf.first(0);
itf.callback();
itf.callbackEndsConversation();
try {
itf.first(0);
Assert.fail("Conversation should have ended");
}
catch( ConversationEndedException cee ) {}
}
}
......@@ -126,7 +126,7 @@ extends AbstractProxyClassGenerator {
/*
* Push the request context on the thread local stack and get the
* content instance which correspond to the current scope policy.
* content instance which corresponds to the current scope policy.
*/
mv.visit (" ");
mv.visit (it.getFcItfSignature());
......
......@@ -137,12 +137,22 @@ extends AbstractProxyClassGenerator {
OneWay oneWayMeth = proxym.getAnnotation(OneWay.class);
EndsConversation end = proxym.getAnnotation(EndsConversation.class);
Conversational conversationalItf = proxycl.getAnnotation(Conversational.class);
if( oneWayMeth != null ) {
mv.visitln(" }");
mv.visitln(" }.start();");
}
if( end != null ) {
if( conversationalItf == null ) {
/*
* For cases where @EndsConversation appears in non
* @Conversation annotated interfaces which can be the case for
* example for callback interfaces associated with conversation
* scoped components.
*/
mv.visitln(" "+ConversationImpl.class.getName()+" conv = getConversation();");
}
mv.visitln(" conv.end();");
mv.visitln(" popConversation();");
}
......
......@@ -242,6 +242,15 @@ extends AbstractProxyClassGenerator {
EndsConversation end = proxym.getAnnotation(EndsConversation.class);
if( end != null ) {
if( conversationalItf == null ) {
/*
* For cases where @EndsConversation appears in non
* @Conversation annotated interfaces which can be the case for
* example for callback interfaces associated with conversation
* scoped components.
*/
mv.visitln(" "+ConversationImpl.class.getName()+" conv = getConversation();");
}
mv.visitln(" conv.end();");
}
if( conversationalItf != null ) {
......
......@@ -408,7 +408,7 @@ public abstract class AbstractScopeManager implements ScopeManager {
Class<?>[] params = method.getParameterTypes();
if( params[0].isAssignableFrom(businessItf) ) {
// initFcController checked that this was a setter
method.invoke(content,new Object[]{cr.getService()});
method.invoke(content,cr);
break;
}
}
......@@ -416,7 +416,7 @@ public abstract class AbstractScopeManager implements ScopeManager {
Field field = (Field) ao;
Class<?> type = field.getType();
if( type.isAssignableFrom(businessItf) ) {
field.set(content,cr.getService());
field.set(content,cr);
break;
}
}
......
......@@ -58,12 +58,6 @@ public class CallableReferenceImpl<B> implements CallableReference<B> {
return callbackID;
}
/**
* Returns the current conversation associated with this reference.
*
* @return the current conversation associated with this reference; null if there is no active conversation
* @throws IllegalStateException if this reference is not conversational
*/
public ConversationImpl getConversation() throws IllegalStateException {
if( ! isConversational() ) {
String msg = "This reference is not conversational";
......@@ -120,7 +114,6 @@ public class CallableReferenceImpl<B> implements CallableReference<B> {
ConversationManager cm = ConversationManager.get();
cm.push(conv);
}
/**
* @since 1.1.1
*/
......@@ -129,4 +122,14 @@ public class CallableReferenceImpl<B> implements CallableReference<B> {
ConversationImpl conv = cm.pop();
return conv;
}
/**
* @since 1.3.2
*/
protected ConversationImpl peekConversation() {
ConversationManager cm = ConversationManager.get();
ConversationImpl conv = cm.peek();
return conv;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment