[Resolvido] Exception ao injetar um @Component numa classe @AplicationScoped

bom, se vc já tem o construtor de string, é só passar “/param.properties” no construtor da PropertiesLoader… deveria funcionar

Mas o VRaptor aceita uma classe @AplicationScoped injetada em outra @AplicationScoped?

sim…

não pode colocar um Request (nem Session) scoped dentro de um App scoped, o resto pode

Posso injetar um @Component dentro de outro @Component? Parece que a zica aqui é referente a injeção de dependência mesmo…

sim, pode, desde que os escopos sejam compatíveis

Escopos compatíveis seria o que?

Você só pode injetar um componente cujo escopo seja maior que o do objeto atual. Por exemplo, se você tem um objeto request você pode tranquilamente injetar um objeto application. Porém o inverso não pode.

prototype < request < flash < session < application

Opa, valeu Garcia, mas o @Component entra aonde nessa hierarquia?

na verdade o prototype é meio mágico… ele pode ser injetado no application, desde que ele só dependa de application…
prototype pode ser injetado em qqer um, desde q as dependências dele sejam compatíveis

@Component sem anotação de escopo é request (escopo padrão do VRaptor)

Poxa, não sabia que existia essa hierarquia, parece que aqui o problema é em relação a isso, pois tenho:

MyFirstApplicationTask que é @Component e @ApplicationScoped.

ParameterLoader que é @Component.

Imagens que é @Component.

News que é @Component.

A zica está na hora da aplicação instanciar o MyFirstApplicationTask, pois no construtor dele está injetado o News e ParameterLoader, por sua vez, o News possui injetado o ParameterLoader e Imagens e a classe Imagens possui o ParameterLoader.
Sacaram o drama? Um dependendo do outro…=/

Vou revisar isso aqui e tentar resolver.
Obrigado pelas dicas. o/

Uma olhada rápida na situação, se o MyFirstApplicationTask é @ApplicationScoped todos os outros tb deverão estar anotados com ApplicationScoped, pois mesmo que Imagens não esteja injetado no MyFirstApplicationTask, o News está e traz automaticamente o Imagens. O News estando como @ApplicationScoped obriga a classe Imagens estar anotada tb com @ApplicationScoped, ou seja, uma classe anotada como @ApplicationScoped faz com que toda a hierarquia de injeções tb sejam anotadas com @ApplicationScoped. É isso?

tem outra solução:

basicamente sua Task vai chamar uma URL da sua aplicação que vai fazer o serviço de verdade. Assim quem trata essa URL vai poder ser request scoped :wink: (vai ser um Controller)

Lucas, consegui colocar sua dica aqui pra rodar, está funcionando na classe Imagens e News, só não está rodando na classe MyFirstApplicationTask. =/

@Component
@ApplicationScoped
public class MyFirstApplicationTask implements ApplicationTask {
	
	private News news;
	private ParameterLoader parameterLoader;

	public MyFirstApplicationTask(TaskScheduler scheduler, News news, ParameterLoader parameterLoader) {
	        this.schedule(scheduler);
	        this.news = news;
                this.parameterLoader = parameterLoader;
	    }
	
	    public void schedule(TaskScheduler scheduler) {
	    	String agenda = this.parameterLoader.getParameter("scheduler.mail");
	        scheduler.schedule(this, new CronTrigger("agenda"));
	    }
	    
		public void run(){				
		news.enviar();
	}
}

O problema agora é nesta classe, pq nas outras está rodando, veja a stacktrace:

Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.imobiliaria.component.MyFirstApplicationTask]: Constructor threw exception; nested exception is java.lang.NullPointerException
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:141)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:105)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:278)
	... 39 more
Caused by: java.lang.NullPointerException
	at br.com.imobiliaria.component.MyFirstApplicationTask.schedule(MyFirstApplicationTask.java:25)

Esse NPE é justamente na linha:

String agenda = this.parameterLoader.getParameter("scheduler.mail");

Por alguma razão que desconheço, ele não esta injetando o ParameterLoader.
Vou ver esse link que vc postou…
Valeu!!

Acho que descobri o motivo de não injetar, faltou o construtor necessário exigido pelo Spring Security:

protected MyFirstApplicationTask() {
	}

A aplicação sobe, mas a MyFirstApplicationTask tá morta, nada acontece.
Sabe como posso contornar isso?

É zica na injeção mesmo, instanciei o objeto ParameterLoader dentro do método de execução e a classe enviou o email:

@Component
@ApplicationScoped
public class MyFirstApplicationTask implements ApplicationTask {
	
	private News news;
	
	public MyFirstApplicationTask(TaskScheduler scheduler, News news) {
	        this.schedule(scheduler);
	        this.news = news;
	    }
	
	    public void schedule(TaskScheduler scheduler) {
	    	ParameterLoader parameterLoader = new ParameterLoader(); // instanciando o objeto
	    	String agenda = parameterLoader.getParameter("scheduler.mail");
	        scheduler.schedule(this, new CronTrigger(agenda));
	    }
	    
		public void run(){				
		news.enviar();
	}
}

Não sei pq não rodou injetando o ParameterLoader, mas pelo menos enviou o email. Pelo menos não está mais usando servletContext, tá pegando o param.properties de dentro da /src.
Valeu Lucas e Garcia, vou dar por resolvido. =)
Abraço!

btw, aquele Nullpointer era pq vc fez o schedule antes de fazer

this.parameterLoader = parameterLoader;

:wink:

pode voltar a colocá-lo no construtor

Putzzzzzzzzzzzzz, era isso! Aprendi mais uma! :lol:
A ordem no construtor faz diferença, eu nem tinha percebido isso, agora foi, tá td no esquema! :slight_smile:
Valeu Lucas!!! \o/

muito provavelmente aquela história de usar o @PostConstruct funcionaria, então… mas enfim, funcionando :wink:

Entendi! =)
Em relação ao que eu tinha postado lá em cima, é aquilo mesmo?

Valeu!!