Dada a seguinte estrutura, que está funcionando muito bem:
public class Person {
public boolean isUnderAge() {
return false;
}
@Remotable
public Integer create() {
return persistenceStrategy.create( this );
}
@Remotable
public void load() {
persistenceStrategy.load( this );
}
}
public class RemoteInterceptor {
// ...
@Around( "execution( @my.package.local.Remotable * my.package.entities...*.*(..) )" )
public Object around( JoinPoint point ) throws Throwable {
Object target = point.getTarget();
Signature signature = point.getSignature();
String methodName = signature.getName();
MethodRtti methodRtti = ( MethodRtti ) point.getRtti();
Object[] args = methodRtti.getParameterValues();
Object returnValue = null;
try {
returnValue = remoteProcedureCaller.call( target, methodName, args );
}
catch( Exception e ) {
e.printStackTrace();
}
return returnValue;
}
}
public class RemotingTest {
public static void main( String[] bananinha ) {
Person p = new Person( "lipe", 20 );
p.create();
Person p2 = new Person( 1 );
p2.load();
}
}
Como eu faria para:
poder encapsular diversas chamadas remotas num objeto só, enviar este objeto para o servidor, executar os métodos e retornar para o cliente os valores de retorno da execução dos métodos para os chamadores. Algo como
// this object should be sent to the server and executed there
public class Command {
public void addCommand( Object target, String methodName, Object .. params ) {
// add to the list
}
public void execute() {
// etc
}
}
criar uma transação, algo como
public class RemotingTest {
public static void main( String[] bananinha ) {
Person p = new Person( "lipe", 20 );
Person p2 = new Person( 1 );
Transaction.begin();
p.create();
p2.load();
Transaction.commit();
}
}
Quanto a 2, louds sugeriu utilizar ThreadLocal para demarcação das transações, mas AspectWerkz infezlimente não suporta mais um per-thread model dos interceptors.
Alguém tem alguma luz? Algo que deveria estudar? Ou devo desistir pois é impossível?
Sobre a questão 2 eu criei uma classe(bem simples) que usa uma única transação(do hibernate) para diversas regras(e consequentemente daos), uso essa classe sempre na última camada(web ou desktop) do sistema, caso queira posso disponibilizar parte do fonte.
Rodrigo, não é este o objetivo. O necessário é encapsular diversas chamadas ao servidor em uma só. Algo como um TO.
Sobre as transações, não entendi como aplicar sua sugestão no contexto que falei, pode explicar melhor?
Maikon, testei esta possibilidade e constatei que a geração de proxies é um tanto lenta quando comparada ao uso de AOP. Mas o resultado final é o mesmo
Vou explicar melhor a 1.
Em dado momento do software, em determinada classe mágica, faria o seguinte:
Command command = new Command();
//intercepta a chamada de person.create()
command.addCommand( person, "create" );
//intercepta a chamada de person.load()
command.addCommand( person, "load" );
// neste momento o objeto 'command' é enviado para
// o servidor e todos os métodos são executados
command.execute();
Contudo, quem chamou person.create() está esperando um Integer como retorno. Como separar os diferentes métodos adicionados ao Command e retornar os valores para quem chamou cada método?
Contudo, não seria a classe chamadora que criaria o composite.
Agora, pensando melhor, as duas idéias se complementam.
Melhorando o RemoteInterceptor:
public class RemoteInterceptor {
// ...
@Around( "execution( @my.package.local.Remotable * my.package.entities...*.*(..) )" )
public Object around( JoinPoint point ) throws Throwable {
// ...
if( Transaction.isOpen() ) {
// cria um objeto Composite se ainda
// não estiver criado e adiciona este método
}
else { // executa o método ou o Composite que reside no ThreadLocal
// ...
return returnValue;
}
}
}
edit: acabei de pensar. Minha idéia é impossível hehe não tem como:
Transaction.begin();
person.create(); // adiciona este método no composite e ainda não é executado
person2.load(); // adiciona este método no composite e ainda não é executado
Transaction.commit(); // ambos os métodos são executados e magicamente o valor de retorno é retornado