2015-03-23 20 views
8

Ho configurato e funzionante l'applicazione REST basata su Spring, ma ora mi piacerebbe convertirlo in Spring-Boot.Convertire l'applicazione Spring esistente in Spring-Boot

La mia applicazione utilizza Primavera-Data-JPA in cima JPA origine dati con Hibernate fornitore:

@Configuration 
@EnableJpaRepositories("foo.bar.web.repository") 
@EnableTransactionManagement 
public class RepositoryConfig { 

    // properties ommited 

    @Bean 
    public DataSource dataSource() { 
     BasicDataSource dataSource = new BasicDataSource(); 
     dataSource.setDriverClassName(className); 
     dataSource.setUrl(url); 
     dataSource.setUsername(userName); 
     dataSource.setPassword(password); 
     return dataSource; 
    } 

    @Bean 
    public EntityManagerFactory entityManagerFactory() { 
     LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); 
     factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 
     factory.setPackagesToScan("foo.bar.web.domain"); 
     factory.setDataSource(dataSource()); 
     factory.setJpaPropertyMap(new HashMap<String, Object>() {{ 
      put("hibernate.dialect", dialect); 
      put("hibernate.hbm2ddl.auto", hbm2ddl); 
     }}); 
     factory.afterPropertiesSet(); 
     return factory.getObject(); 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager() { 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(entityManagerFactory()); 
     return transactionManager; 
    } 
} 

miei endpoint REST implementate utilizzando SpringMVC con seguente configurazione:

@Configuration 
@EnableWebMvc 
@ComponentScan("foo.bar.web.controller") 
public class MvcConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 
     configurer.enable(); 
    } 

    @Bean 
    public MultipartResolver multipartResolver() { 
     return new CommonsMultipartResolver(); 
    } 
} 

Web initializer:

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 

    @Override 
    protected Class<?>[] getRootConfigClasses() { 
     return new Class[]{ 
       ApplicationConfig.class, 
       RepositoryConfig.class 
     }; 
    } 

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

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

Il problema è che non voglio usare Spring-Boo t configurazione automatica perché mi piacerebbe riutilizzare le mie classi di configurazione esistenti con modifiche minime, ma non riesco a trovare il modo corretto per farlo. Ho provato ad implementare la classe di applicazione Spring-boot annotata con @SrpingBootApplication, ma non sono sicuro al 100% che le mie classi di configurazione vengano utilizzate, perché in questo caso ottengo java.lang.ClassCastException: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean$$EnhancerBySpringCGLIB$$ba21071f cannot be cast to javax.persistence.EntityManagerFactory.

Inoltre ho provato a gettare via l'annotazione @EnableAutoConfiguration dalla classe dell'applicazione e aggiungere il bean TomcatEmbeddedServletContainerFactory manualmente al mio contesto, ma in questo caso tomcat incorporato non è configurato correttamente.

Sarebbe bello se qualcuno potesse darmi un suggerimento su come risolvere il mio problema. Credo che tutto ciò che devo fare sia in qualche modo sostituire il mio WebInitilizer con la configurazione di Spring-Boot.

+1

Suggerirei di utilizzare le funzioni di configurazione automatica in quanto ciò consentirebbe sostanzialmente di abbandonare la maggior parte della configurazione o di inserire in 'application.properties'. E il miglior codice gestibile è il codice non scritto. –

+0

Sono assolutamente d'accordo con te sul fatto che l'auto config sia una buona funzionalità, ma questo è il mio progetto educativo e penso che la configurazione manuale sia più utile per capire come funzionano tutte queste funzionalità e come sono correlate a "SpringMVC tradizionale" – Alex

+0

non voglio usare Spring Boot o almeno stai lavorando duramente per usarne il meno possibile. Ma se davvero devi semplicemente eliminare il tuo 'WebInitializer' e sostituirlo con uno che estenda la classe' SpringBootServletInitializer'. –

risposta

6

Dopo aver passato una giornata in una ricerca, ho finalmente trovato una soluzione al mio problema. Prima di tutto ho dovuto modificare i miei fagioli EntityManagerFactory() e transactionManager():

@Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 
     LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); 
     factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 
     factory.setPackagesToScan("foo.bar.web.domain"); 
     factory.setDataSource(dataSource()); 
     factory.setJpaPropertyMap(new HashMap<String, Object>() {{ 
      put("hibernate.dialect", dialect); 
      put("hibernate.hbm2ddl.auto", hbm2ddl); 
     }}); 
     factory.afterPropertiesSet(); 
     return factory; 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager() { 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); 
     return transactionManager; 
    } 

Inoltre ho completamente rimosso la mia classe WebInitializer e rimossi @EnableWebMvc annotazione dal MvcConfig. In Spring-Boot non è possibile estendere la classe da WebMvcConfigurerAdapter in classpath perché se Spring-Boot lo trova, verrà saltata tutta la configurazione automatica relativa a SpringMVC. Ecco la versione finale della mia classe MvcConfig:

@Configuration 
@ComponentScan("foo.bar.web.controller") 
public class MvcConfig { 

    @Bean 
    public MultipartResolver multipartResolver() { 
     return new CommonsMultipartResolver(); 
    } 
} 

ho usato la versione di classe di applicazione Primavera-Boot, che mostrato nel doc:

@SpringBootApplication(exclude = MultipartAutoConfiguration.class) 
public class Application extends SpringBootServletInitializer { 

    public static void main(String[] args) throws Exception { 
     SpringApplication.run(Application.class, args); 
    } 

    @Override 
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 
     return application.sources(Application.class); 
    } 
} 

nota, che nel mio caso ho dovuto escludere MultipartAutoConfiguration dalla configurazione automatica perché ho già configurato questa funzione in MvcConfig. Bun è anche possibile lasciarlo autoconfigurato, ma in questo caso ho dovuto accordare le dimensioni del file consentito nel file di configurazione application.properties o aggiungere un bean MultipartConfigElement al mio classpath.

Problemi correlati