4
respostas

Aula9: Video 1: Quebra apos alterar ServletSpringConfiguration

Foi dado esse erro após inserir JPAProductionConfiguration.class e comentar onStartup no ServletSpringMvc.java

INFORMAÇÕES: Initializing Spring root WebApplicationContext
jun 21, 2017 11:09:40 AM org.apache.catalina.core.StandardContext listenerStart
GRAVE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactory' defined in class br.com.casacodigo.loja.conf.JPAConfiguration: Unsatisfied dependency expressed through constructor argument with index 0 of type [javax.sql.DataSource]: : No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:751)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:466)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1113)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1008)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:505)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:956)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:747)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4937)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3954)
    at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426)
    at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1345)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1530)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1519)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1261)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1009)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:904)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:815)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:743)
    ... 26 more

jun 21, 2017 11:09:40 AM org.apache.catalina.core.StandardContext startInternal
GRAVE: Error listenerStart
jun 21, 2017 11:09:40 AM org.apache.catalina.core.StandardContext startInternal
GRAVE: Context [/casacodigo] startup failed due to previous errors
jun 21, 2017 11:09:40 AM org.apache.catalina.core.ApplicationContext log
INFORMAÇÕES: Closing Spring root WebApplicationContext
jun 21, 2017 11:09:40 AM org.apache.catalina.core.StandardContext reload
INFORMAÇÕES: Reloading Context with name [/casacodigo] is completed
package br.com.casacodigo.loja.conf;

import java.net.URISyntaxException;
import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement
public class JPAConfiguration {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSouce, Properties aditionalProperties) {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setPackagesToScan("br.com.casacodigo.loja.models");

        factoryBean.setDataSource(dataSouce);


        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        factoryBean.setJpaVendorAdapter(vendorAdapter);                
        factoryBean.setJpaProperties(aditionalProperties);


        return factoryBean;
    }

    @Bean
    @Profile("dev")
    private Properties aditionalProperties() {
        Properties props = new Properties();
        props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        props.setProperty("hibernate.show_sql", "true");
        props.setProperty("hibernate.hbm2ddl.auto", "update");
        return props;
    }

    @Bean
    @Profile("dev")
    public DataSource dataSouce() throws URISyntaxException {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUsername("root");
        dataSource.setPassword("geografia");
        dataSource.setUrl("jdbc:mysql://localhost:3306/casacodigo");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        return dataSource;
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory emf){
        return new JpaTransactionManager(emf);
    }
}



package br.com.casacodigo.loja.conf;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

@Profile("prod")
public class JPAProductionConfiguration {

       @Autowired
       private Environment environment;

       @Bean
       public Properties additionalProperties() {
           Properties props = new Properties();
           props.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
           props.setProperty("hibernate.show_sql", "true");
           props.setProperty("hibernate.hbm2ddl.auto", "update");
           return props;
       }

       @Bean       
       public DataSource dataSource() throws URISyntaxException{
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName("org.postgresql.Driver");

          URI dbUrl = new URI(environment.getProperty("DATABASE_URL"));
          dataSource.setUrl("jdbc:postgresql://" + dbUrl.getHost() + ":" + dbUrl.getPort() + dbUrl.getPath());
          dataSource.setUsername(dbUrl.getUserInfo().split(":")[0]);
          dataSource.setPassword(dbUrl.getUserInfo().split(":")[1]);
          return dataSource;
       }

}



package br.com.casacodigo.loja.conf;

import javax.servlet.Filter;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class ServletSpringMVC extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {AppWebConfiguration.class , JPAConfiguration.class, 
            SecurityConfiguration.class, JPAProductionConfiguration.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] {};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        encodingFilter.setEncoding("UTF-8");
        return new Filter[] { encodingFilter, new OpenEntityManagerInViewFilter() };
    }

    @Override
    protected void customizeRegistration(Dynamic registration) {
        registration.setMultipartConfig(new MultipartConfigElement(""));
    }

//    @Override
//    public void onStartup(ServletContext servletContext) throws ServletException {
//        super.onStartup(servletContext);
//        servletContext.addListener(RequestContextListener.class);
//        servletContext.setInitParameter("spring.profiles.active", "dev");
//    }


}
4 respostas

Fala Wellington, tudo bem ?

A exception diz que não foi encontrado um bean do tipo DataSource, por isso não foi satisfeita uma injeção de dependencia.

Provavelmente está ocorrendo porque não está passando a propriedade spring.profiles.active, imagino que nesse caso, apontando o profile como dev. Apontamos o profile como dev na sobrescrita do método onStartup() da classe ServletSpringMvc, portanto o código não pode estar comentado.

Dê uma olhada nisso. Creio que já resolve. Espero ter ajudado. Abraço!

Olá Boa tarde, muito obrigado por ajudar ! Então ... mas para deployar no heroku devo comentar certo? isso nao faz com que no heroku o projeto nao funcione? pois o meu projeto no heroku so mostra essa tela com essa mensagem:

" Application error

An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details. "

Wellington, você provavelmente está usando o Tomcat correto ? Sim, é verdade no heroku o datasource a ser utilizado é o de produção e não e o de "dev". Logo você deve comentar ou excluir este código do onStartup e fazer o deploy da aplicação para o heroku utilizando o datasource "prod" e a aplicação conseguirá subir lá com as configurações do datasource correto.

No entanto ao fazer isso, a aplicação deixa de rodar localmente pois a mesma vai tentar subir utilizando o datasource "prod", o que não contém as configurações corretas para rodar no mysql.

O que você deve fazer é passar o mesmo parâmetro que antes você passava através desse método:

//    @Override
//    public void onStartup(ServletContext servletContext) throws ServletException {
//        super.onStartup(servletContext);
//        servletContext.addListener(RequestContextListener.class);
//        servletContext.setInitParameter("spring.profiles.active", "dev");
//    }

só que agora via argumento nas configurações do tomcat. Seleciona o servidor na aba "Servers" e tecla F3 que vai abrir a Overview do servidor, clica em "Open launch configuration" > "Arguments" > VM Arguments adiciona o argumento -Dspring.profiles.active="dev" ao final da lista de argumentos ok?

Como é só para desenvolvimento, da certo você ficar subindo o seu tomcat com este parâmetro, se houver necessidade você pode criar um servidor só para essa sua aplicação e deixar ele com esse parâmetro, mudar a porta do server, etc

Davi, obrigado por me ajudar a solucionar o problema.

Existe a possibilidade de definir o perfil pela inicialização do Spring?

Grande abraço!