Instanciar classe via reflection estando em outro jar, como fazer?

Oi gente.
Estou com uma tarefa muito difícil e estou com dificuldades, agradeço a todos que puderem me ajudar.

Tenho um projeto A que é uma biblioteca, onde em determinado momento recebo uma lista de objetos do projeto B que é o projeto principal web.

Ao receber essa lista eu consigo pegar o tipo da lista genérica, ou seja, do tipo Pessoa, mas esse objeto pertence ao projeto B, e como a biblioteca não tem import dessa classe, nem tem conhecimento dela, tem somente o nome que eu consegui capturar, dai acontece erro de classe não encontrada.

java.lang.ClassNotFoundException: class modelo.Pessoa

esse erro ocorre aqui:

ParameterizedType genericType = (ParameterizedType)f.getGenericType(); String classe = genericType.getActualTypeArguments()[0].toString(); Class clazz = Class.forName(classe);

É até obvio o erro porque o projeto A que é biblioteca não conhece essa classe, não tem um import.
Baixei o projeto do hibernate pra tentar ver como ele consegue fazer um newInstance() com reflection mesmo sendo uma biblioteca, porém como o projeto hibernate é muito grande não consegui achar onde eles fazem isso.

Alguém me ajudaria como eu poderia fazer isso?

Grata a todos.

a classe tem que estar no classpath da aplicação para o java encontrar ela

põe no classpath que funciona

[quote=zoren]a classe tem que estar no classpath da aplicação para o java encontrar ela

põe no classpath que funciona[/quote]

Concordo que precisar estar no classpath, mas como vou fazer isso se a biblioteca é genérica, ela será usada por projetos que não sei quais são. O cenário é o seguinte:

Projeto B

  • inclui a biblioteca.jar
  • aqui ela tentar acessar um class do projeto B sendo do tipo Usuario

Projeto C

  • incluir a biblioteca.jar
  • aqui ela tenta acessar um class do projeto C sendo do tipo Pessoa

O que tem em comum, que essas classes extendem uma classe minha chama “Model”.

A questão é, eu não sei onde estará o “biblioteca.jar”, mas sei que no projeto que ela estiver, ela terá que acessar uma classe desse projeto.

Então lhe pergunto, como vou colocar no classpath do projeto “biblioteca” uma classe que estará em outro projeto e nem sei qual será essa classe, a única coisa que sei que ela vai ter que ter um “extends Model”. E aí como faço?

Obs: foi como eu disse, é como o hibernate faz, ele não inclui o seu projeto no classpath dele, nem no meu, ele de alguma forma consegue dar um new() numa classe do projeto que esteja com por exemplo com a anotação @Entity, isso que quero saber, como ele cria um novo objeto para depois de selecionar no banco fazer um set nos atributos e devolver um objeto com dados.
Como ele faz esse new() se ele nem sabe qual o projeto em que ele estará? Entendeu o sentido do problema que estou?
Grata peja ajuda.

Para criar um objeto de uma classe que está em um JAR que não está visível no seu CLASSPATH, você pode carregá-la através de um URLClassLoader.

[quote=entanglement]Para criar um objeto de uma classe que está em um JAR que não está visível no seu CLASSPATH, você pode carregá-la através de um URLClassLoader.

[/quote]

Mas no caso o biblioteca.jar vai ter que acessar um .class do outro projeto, mas esse ckass vai estar no pacote normal e não em um jar, tens idéia de como faço pra buscaro arquivo no projeto principal?

Ok.

Vamos por partes, como diria Jack.

Criei três classes pra exemplificar o que você quer de maneira simplificada.

A classe ProjetoA representa o seu projeto que será usado por outros projetos mas não conhece suas classes.

A classe ProjetoB representa um projeto qualquer que utiliza o projetoA. (O projetoA tem que ser incluído no classpath, obviamente).

A classe Pessoa é uma classe interna do ProjetoB que o ProjetoA não conhece, mas vai usar que é uma beleza! (hehehe)

Lá vai o código:



public class Pessoa {
	String nome;

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

}


import java.lang.reflect.Method;


public class ProjetoA {
	@SuppressWarnings("unchecked")
	public <T> T getObjeto(String classe) {
		T meuObjeto = null;
		try {
			meuObjeto = (T) Class.forName(classe).newInstance();
		} catch (Exception e) {
		}
		return meuObjeto;
	}
	
	@SuppressWarnings("unchecked")
	public <T> Object executaMetodo(T t,String metodo, Object[] params) {
		Object obj = null;
		Class[] paramClasses = null;
		
		if (params != null) {
			paramClasses = new Class[params.length];
			for (int i = 0; i < params.length; i++) {
				paramClasses[i] = params[i].getClass();
			}
		}
		
		try {
			if (params != null) {
				Method meuMetodo = t.getClass().getDeclaredMethod(metodo, paramClasses);
				obj = meuMetodo.invoke(t, params);
			} else {
				Method meuMetodo = t.getClass().getDeclaredMethod(metodo);
				obj = meuMetodo.invoke(t);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return obj;
	}
}

public class ProjetoB {

	public static void main(String[] args) {
		// Cria uma instância do projeto A
		ProjetoA a = new ProjetoA();
		
		/*
		 *  O projeto A retorna uma instância de Pessoa,
		 *  apesar de não conhecer a classe Pessoa
		 */
		
		Pessoa p = a.getObjeto("Pessoa");
		
		/*
		 * O projeto A chama o método setNome da classe Pessoa
		 */
		
		Object[] params;
		
		params = new Object[1];
		params[0] = "Pessoa 1";
		a.executaMetodo(p, "setNome", params);
		
		/*
		 * O projeto A finalmente chama o método getNome 
		 * da classe Pessoa e retorna a string desejada
		 */

		params = null;
		System.out.println(a.executaMetodo(p, "getNome", params));
		
	}
}

Editei pra deixar a classe ProjetoA um pouco mais genérica. Tinha um bugzinho. :wink:

E aí moça?

Testou?