Dúvidas duvidosas e não sintetizáveis para um título de tópico

Oi pessoal, boa tarde.

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:

  1. 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
	}
}
  1. 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?

Valeu pessoal.

Na questão 1 vc pretende fazer diversas operações(chamadas) num único método? Se sim eu fazeria mais ou menos desse jeito:

class...

public Object execute(Object bean, int operation) {
Object retorno = null;
if(operation == 1){
retorno = create(bean);
} else if(operation == 2){
retorno = save(bean);
}
return retorno;
}

private Boolean create(Bean)...
private Boolean save(Bean)...
private Boolean delete(Bean)...
private Boolean update(Bean)...
private List select(Bean)...

...

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.

Sem mais, Rodrigo.

LIPE, ao invés de RemoteInterceptor, vc não poderia utilizar um Proxy? Assimi vc faria este mesmo trabalho em um InvocationHandler.

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 :smiley:

Valeu pelos replies pessoal.

Eu nao entendi muito, mas em (1) voce poderia utilizar um agregate de commands, acho

ixprica meió aê

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?

Quase…

Você intercepta uma chamada a Person.create() e executa este Command?

Se for, porque você não faz um command.getResult()?

Ah, e não adicione commands assim, use um composite.

Boa idéia do composite, bem melhor.

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

Bosta, não tem como manter isso transparente :expressionless:

Primeiro: não era mais fácil usar o genesis não? :smiley:

Segundo, para fazer o que você quer com as transações, não é mais fácil escrever um método @Remotable que chame os outros?

E o aprendizado, fica onde? :smiley:

Não entendi a sua idéia Mister, pode explicar um pouco melhor?

Valeu :smiley:

Em aprender a usar o genesis :mrgreen:

Se você tem:

public class Anything {
   @Remotable
   public void methodA() {
       // ...
   }

   @Remotable
   public int methodB() {
       // ...
   }
}

Não seria mais fácil fazer:

public class Anything {
   @Remotable
   public int methodsFacade() {
       methodA();
       return methodB();
   }

   @Remotable
   private void methodA() {
       // ...
   }

   @Remotable
   private int methodB() {
       // ...
   }
}

hehe espertinho :smiley:

Entendi sua sugestão, mas queria fugir disso para evitar proliferação de métodos que funcionam apenas como façade.

Será que tem jeito?

Esses métodos deveriam ser mais ou menos 1:1 com os casos de uso. Isso é ruim? Acho que fica muito mais claro, na verdade

Depende. Qual a boundary natural da tua transação?

Hum, pensando por este lado parece bom. Gostei :smiley:

Quando ao boundary natual de minha transação eu vou estudar, depois te respondo hehe :smiley:

Valeu cara \o/