Como devo fazer para escanear meu modelo a partir de um jar externo, para assim poder usa-lo para autowired
Como devo fazer para escanear meu modelo a partir de um jar externo, para assim poder usa-lo para autowired
Fala ai Anderson, de boa ?
Você pode usar a anotação @ComponentScan
passando o pacote no qual ela deve ler a sua dependência.
Não sei se isso vai dar ruim no seu projeto, dado que nunca precisei fazer isso.
Boa tarde Matheus, já utilizei esta anotação, entretanto continuo a receber um erro
Caused by: java.lang.IllegalArgumentException: Not a managed type: class package.modelo
at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:473) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:73) ~[spring-data-jpa-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:181) ~[spring-data-jpa-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:119) ~[spring-data-jpa-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:102) ~[spring-data-jpa-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:298) ~[spring-data-commons-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$3(RepositoryFactoryBeanSupport.java:287) ~[spring-data-commons-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:141) ~[spring-data-commons-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.util.Lazy.get(Lazy.java:63) ~[spring-data-commons-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:290) ~[spring-data-commons-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:102) ~[spring-data-jpa-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1765) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1702) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
... 29 common frames omitted
obrigado.
Você precisa colocar o nome completo do pacote.
Outro detalhe importante, é que para você injetar algo no spring, o objeto tem que ser um @Component
se não for, ai não vai rolar a injeção.
utilizo essa abordagem, esse é meu modelo:
package package.modelo;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.springframework.stereotype.Component;
@Component
@Entity
public class Cliente {
@Id
private String cpf;
private String nome;
private int idade;
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public int getIdade() {
return idade;
}
public void setIdade(int idade) {
this.idade = idade;
}
}
e este é o projeto onde desejo importa-lo:
package package.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@EnableAutoConfiguration
@EnableDiscoveryClient
@SpringBootApplication
@EnableEurekaClient
@ComponentScan(basePackages={"package.demo","package.modelo","package.controller","package.dao"})
@EntityScan(basePackages={"package.modelo"})
@EnableJpaRepositories(basePackages={"package.dao"})
public class ClienteApplication {
public static void main(String[] args) {
SpringApplication.run(ClienteApplication.class, args);
}
}
ainda assim, o erro supracitado persiste
Anderson..
Não faz mais sentido você simplesmente fazer a busca do banco ou dar um new na mão ?
Dado que não há nenhuma regra de negócio que está precisando fazer e tudo mais
pensei nesta abordagem, mas gostaria de manter a injeção provida pelo spring, também porque a utilizo em uma interface que estende JpaRepository
import org.springframework.data.jpa.repository.JpaRepository;
import package.modelo.Cliente;
public interface ClienteInterface extends JpaRepository<Cliente, String> {
}
Fala pessoal, blz ?
Anderson, imagino que essa não seja uma abordagem interessante para classes de modelo. Quando se anota uma classe com @Component, por padrão no Spring, ele vai instanciar esse objeto, e gerenciar seu ciclo de vida, sendo um singleton com escopo de aplicação. Ou seja, uma única instância será utilizada pelo Spring sobre esse objeto, um risco grande, dado que nos objetos de modelo em geral há manutenção de estado inerente as suas regras de negócio, e como ele vai aproveitar essa instancia pra toda a aplicação (para todos os usuários) você pode ter problemas com a concorrência à esse estado, inconsistência, etc, etc.
Da forma como está sendo feito, suas classes de modelo podem sofrer com esse acoplamento aos detalhes da gestão do conteiner do Spring. Faz mais sentido usar esse objeto sendo instanciado de forma direta pelo seu código, ou mesmo pelo Spring só que no escopo de requisição* (quando pedimos como parâmetro de uma action de um rest controller, por exemplo).
CarrinhoDeCompras
por exemplo que representa algo do domínio que deve seu único por usuário.Outra coisa que podemos pensar é, pra que esse objeto vai ser gerenciado pelo container? Não há nada interno nesse objeto que sugira o uso desse recurso, não existe em geral nenhuma dependência sendo injetada nesse objeto (em geral uma composição com outra classe de modelo resolve). Ou também, em nenhum ponto precisamos injetar esse objeto em outro componente para que possamos utilizá-lo.
Na sua interface que representa o repositório Spring Data, você pode normalmente usar sua classe de modelo mesmo que ela não seja gerenciada como componente do container Spring. Lembre-se que a única diferença entre uma classe que foi definida no seu projeto e uma classe compilada dentro de um jar externo importado é o pacote (endereço). Uma vez que os .class estão no classpath, você pode usar da mesma forma como fosse uma classe definida por você.
import org.springframework.stereotype.Repository;
import org.springframework.data.jpa.repository.JpaRepository;
// tente usar a convenção de nomes de pacotes definida pelo Java para evitar problemas de conflito com classes de terceiros ao longo do tempo
// package em geral deve ser palavra reservada, e não nome de um pacote base da aplicação
import br.com.seudominio.seuprojeto.modelo.Cliente;
@Repository
public interface ClienteRepository extends JpaRepository<Cliente, String> {
}
Espero ter ajudado. Abraço!