2014-11-26 8 views
10

Zgodnie z documentation wiosenna administracja wsadowa jest bardzo łatwa do osadzenia w istniejącej aplikacji. Wystarczy skopiować pliki web.xml i index.jsp, a następnie dodanie potrzebnych zależności wystarcza, aby to zadziałało.Czy istnieje sposób na poprawne włączenie funkcji spring-batch-adm i spring-boot?

Ale jeśli chcę go użyć w istniejącym projekcie wiosennego rozruchu, to gorzej. Według this example konfiguracja jest nieco hacky, ale działa. NIGDY nie próbuję używać adnotacji @EnableBatchProcessing w moim komponencie bean konfiguracji. Następnie otrzymuję następujący wyjątek.

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobBuilders' defined in class path resource [org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.batch.core.configuration.annotation.JobBuilderFactory org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.jobBuilders() throws java.lang.Exception] threw exception; nested exception is java.lang.ClassCastException: org.springframework.batch.core.repository.support.JobRepositoryFactoryBean$$EnhancerBySpringCGLIB$$49fa0273 cannot be cast to org.springframework.batch.core.repository.JobRepository 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:597) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1095) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:990) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) 
    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.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) 
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941) 
    at demo.Application.main(Application.java:35) 
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.batch.core.configuration.annotation.JobBuilderFactory org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.jobBuilders() throws java.lang.Exception] threw exception; nested exception is java.lang.ClassCastException: org.springframework.batch.core.repository.support.JobRepositoryFactoryBean$$EnhancerBySpringCGLIB$$49fa0273 cannot be cast to org.springframework.batch.core.repository.JobRepository 
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:188) 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:586) 
    ... 17 more 
Caused by: java.lang.ClassCastException: org.springframework.batch.core.repository.support.JobRepositoryFactoryBean$$EnhancerBySpringCGLIB$$49fa0273 cannot be cast to org.springframework.batch.core.repository.JobRepository 
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$b5c6eb04.jobRepository(<generated>) 
    at org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.jobBuilders(AbstractBatchConfiguration.java:58) 
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$b5c6eb04.CGLIB$jobBuilders$8(<generated>) 
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$b5c6eb04$$FastClassBySpringCGLIB$$d88bd05f.invoke(<generated>) 
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) 
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312) 
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$b5c6eb04.jobBuilders(<generated>) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166) 
    ... 18 more 

Moja konfiguracja jest bardzo prosta Mam dwie fasoli konfiguracji

@Configuration 
@ImportResource({"classpath:/org/springframework/batch/admin/web/resources/servlet-config.xml", 
     "classpath:/org/springframework/batch/admin/web/resources/webapp-config.xml"}) 
public class BatchAdminConfiguration { 
} 

i

@Configuration 
@EnableBatchProcessing 
public class BatchImporterConfiguration { 
} 

Kiedy usunąć @EnableBatchProcessing i starają się tworzyć miejsca pracy i korzystania z JobBuilderFactory @StepScope adnotacji I Otrzymuję inne Wyrażenia ClassCastExceptions.

Teraz używam konfiguracji opartej na xml do tworzenia zadań, kroków i innych komponentów. Działa dobrze, ale wolałabym wolną konfigurację xml. Czy istnieje sposób na łatwą integrację mechanizmu sprężynowego, sprężynowego i wiosennego?

+0

Czy można utworzyć projekt Github, jeśli udało się rozwiązać problem w końcu, mam podobny problem też –

Odpowiedz

2

Krótka odpowiedź brzmi, że nie będziesz chciał używać @EnableBatchProcessing ze Spring Batch Admin. SBA dostarcza wiele ziaren w skali globalnej, które zapewnia również @EnableBatchProcessing. SBA 2.0 (obecnie w fazie rozwoju) prawdopodobnie zapełni luki między tym, co aktualnie istnieje, a tym, co zapewnia @EnableBatchProcessing (konkretnie podając JobBuilderFactory i StepBuilderFactory).

, aby dostać się z systemem, powinieneś być w stanie (nie mam zmęczony ten sam) skonfigurować w katalogu JobBuilderFactory i StepBuilderFactory globalnego wykorzystania META-INF/spring/batch/override/. Z tego miejsca można korzystać z plików XML w katalogu META-INF/spring/batch/jobs, które nie wykonują niczego poza skanowaniem komponentów dla klas @Configuration. Jednak z powodu powielenia ziaren pozostaw niezauważone @EnableBatchProcessing.

Dla zapisu nie jest to kwestia Spring Boot, ponieważ @EnableBatchProcessing jest adnotacją wiosennej partii, a nie wersją rozruchową.

+0

Dzięki za ogólne wyjaśnienie. Definiowanie konfiguracji xml w META-INF/spring/batch/jobs i dodawanie znaczników i pomaga w korzystaniu z konfiguracji opartej na adnotacjach. Ale nie mogę zdefiniować elementów Job lub Step bean w konfiguracji Java, wciąż dostaję dziwne błędy, dla przykładu Zakres pracy nie jest zdefiniowany. Jeśli utworzę własny komponent bean JobScope, otrzymam ponownie wyjątek od klasy. Zasobów zakresu Singleton można używać bez problemu. Ale fasola o zakresie lub miejscu pracy powinna być zdefiniowana w xml. Dziwne :( –

+0

Wymieniasz kilka spraw osobno, nie krępuj się, by skontaktować się ze mną od tej chwili i mogę Cię przez nie przejść –

+0

Dziękuję za życzliwość, gdy znajdę wolne miejsce, zrób to :) –

1

aby zakończyć odpowiedź, tutaj jest kod, aby utworzyć dwa fasola po wyłączeniu adnotacją @EnableBatchProcessing

@Autowired 
JobRepository jobRepository; 
@Autowired 
PlatformTransactionManager transactionManager; 

@Bean 
public JobBuilderFactory jobBuilderFactory() { 
    return new JobBuilderFactory(jobRepository); 
} 

@Bean 
public StepBuilderFactory stepBuilderFactory() { 
    return new StepBuilderFactory(jobRepository, transactionManager); 
} 
1

Ten ClassCastException jest spowodowane

classpath:/org/springframework/batch/admin/web/resources/servlet-config.xml

załadunku

META-INF/spring/batch/servlet/resources/resource-context.xml

który zawiera

<mvc:annotation-driven />

To powoduje konflikty z konfiguracją mvc w klasie konfiguracji Spring Java. Poniższa klasa może być używana do osadzania Spring Batch Admin w istniejącej aplikacji korzystającej z konfiguracji Java.

@Configuration 
@EnableWebMvc 
@ImportResource({"classpath*:/META-INF/spring/batch/bootstrap/**/*.xml" 
    , "classpath*:/META-INF/spring/batch/override/**/*.xml" 
    , "classpath*:/org/springframework/batch/admin/web/resources/webapp-config.xml" 
    , "classpath*:/META-INF/spring/batch/servlet/manager/**/*.xml" 
    , "classpath:base-menu-config.xml" 
    }) 
public class SpringBatchAdminConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void addResourceHandlers(final ResourceHandlerRegistry registry) { 
     registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/META-INF/");  
    } 

    @Bean 
    public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() { 
     return new SimpleControllerHandlerAdapter(); 
    } 

    @Bean 
    public BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() { 
     return new BeanNameUrlHandlerMapping(); 
    } 

    @Bean 
    public BeanNameViewResolver beanNameViewResolver() { 
     return new BeanNameViewResolver(); 
    } 

    @Bean(name = "defaultResources") 
    public PropertiesFactoryBean defaultResources() { 
     return new PropertiesFactoryBean(); 
    } 

    @Bean(name = "jsonResources") 
    public PropertiesFactoryBean jsonResources() { 
     return new PropertiesFactoryBean(); 
    } 

    @Bean 
    public HomeController homeController() throws IOException { 
     HomeController homeController = new HomeController(); 
     homeController.setDefaultResources(defaultResources().getObject()); 
     homeController.setJsonResources(jsonResources().getObject()); 
     return homeController; 
    } 

    @Bean 
    public MenuManager menuManager() { 
     return new MenuManager(); 
    } 

    @Bean(name = "freemarkerConfig") 
    public HippyFreeMarkerConfigurer hippyFreeMarkerConfigurer() { 
     HippyFreeMarkerConfigurer hippyFreeMarkerConfigurer = new HippyFreeMarkerConfigurer(); 
     hippyFreeMarkerConfigurer.setTemplateLoaderPaths("/WEB-INF/web", "classpath:/org/springframework/batch/admin/web"); 
     hippyFreeMarkerConfigurer.setPreferFileSystemAccess(false); 
     hippyFreeMarkerConfigurer.setFreemarkerVariables(Collections.singletonMap("menuManager", (Object) menuManager())); 
     Properties freemarkerSettings = new Properties(); 
     freemarkerSettings.put("default_encoding", "UTF-8"); 
     freemarkerSettings.put("output_encoding", "UTF-8"); 
     hippyFreeMarkerConfigurer.setFreemarkerSettings(freemarkerSettings); 
     return hippyFreeMarkerConfigurer; 
    } 

    public AjaxFreeMarkerView parentLayout() { 
     AjaxFreeMarkerView ajaxFreeMarkerView = new AjaxFreeMarkerView(); 
     FreeMarkerViewResolver freeMarkerViewResolver = new FreeMarkerViewResolver(); 
     freeMarkerViewResolver.setExposeSpringMacroHelpers(false); 
     freeMarkerViewResolver.setAllowRequestOverride(true); 
     ajaxFreeMarkerView.setViewResolver(freeMarkerViewResolver); 
     Properties attributes = new Properties(); 
     attributes.put("titleCode", "home.title"); 
     attributes.put("titleText", "Spring Batch Admin"); 
     ajaxFreeMarkerView.setAttributes(attributes); 
     return ajaxFreeMarkerView; 
    } 

    @Value("#{resourceService.servletPath}") 
    private String servletPath; 

    @Bean(name="standard") 
    public AjaxFreeMarkerView standard() { 
     AjaxFreeMarkerView standard = parentLayout(); 
     standard.setUrl("/layouts/html/standard.ftl"); 
     standard.setContentType("text/html;charset=UTF-8"); 
     standard.getAttributesMap().put("body", "/layouts/html/home.ftl"); 
     standard.getAttributesMap().put("servletPath", servletPath); 
     return standard;   
    } 

    @Bean(name="standard.rss") 
    public AjaxFreeMarkerView standardRss() { 
     AjaxFreeMarkerView standardRss = parentLayout(); 
     standardRss.setUrl("/layouts/html/standard.ftl"); 
     standardRss.setContentType("text/xml"); 
     standardRss.getAttributesMap().put("body", "/layouts/rss/home.ftl"); 
     standardRss.getAttributesMap().put("servletPath", servletPath); 
     return standardRss;  
    } 

    @Bean(name="standard.json") 
    public AjaxFreeMarkerView standardJson() { 
     AjaxFreeMarkerView standardJson = parentLayout(); 
     standardJson.setUrl("/layouts/json/standard.ftl"); 
     standardJson.setContentType("application/json"); 
     standardJson.getAttributesMap().put("body", "/layouts/json/home.ftl"); 
     standardJson.getAttributesMap().put("servletPath", servletPath); 
     return standardJson;   
    } 

    @Bean(name="home") 
    public AjaxFreeMarkerView home() { 
     return standard(); 
    } 

    @Bean(name="home.json") 
    public AjaxFreeMarkerView homeJson() { 
     AjaxFreeMarkerView homeJson = standardJson(); 
     homeJson.getAttributesMap().put("body", "/layouts/json/home.ftl"); 
     return homeJson; 
    } 


} 

Pojedynczy plik XML jest również wymagane w przypadku abstrakcyjnej menu bazowej, która odwołuje gdzie indziej w projekcie Spring Batch administracyjnej. Jest to wymagane, ponieważ fasola abstrakcyjna nie może być dostarczana z konfiguracji Spring Java.

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 

    <bean id="baseMenu" abstract="true"> 
     <property name="prefix" value="#{resourceService.servletPath}" /> 
    </bean> 

</beans> 

Zależności Mavena. Zadbaj o to, aby Maven tylko jedna wersja podstawowej platformy Spring była wciągnięta.

Pakiet sprężynowy oczekuje również w domyślnej konfiguracji, aby następujące pliki istniały w katalogu głównym ścieżki klasy.

batch-default.properties

# Default placeholders for database platform independent features 
batch.remote.base.url=http://localhost:8080/spring-batch-admin-sample 
# Non-platform dependent settings that you might like to change 
batch.job.configuration.file.dir=/tmp/config 

build.artifactId=1 
build.version=1 
build.buildNumber=1 
build.timestamp=1 
log.enableConsole=true 

batch-hsql.properties

# Placeholders batch.* 
# for HSQLDB: 
batch.jdbc.driver=org.hsqldb.jdbcDriver 
batch.jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true 
# Override and use this one in for a separate server process so you can inspect 
# the results (or add it to system properties with -D to override at run time). 
# batch.jdbc.url=jdbc:hsqldb:hsql://localhost:9005/samples 
batch.jdbc.user=sa 
batch.jdbc.password= 
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer 
batch.schema.script=classpath*:/org/springframework/batch/core/schema-hsqldb.sql 
batch.drop.script=classpath*:/org/springframework/batch/core/schema-drop-hsqldb.sql 
batch.business.schema.script=classpath:/business-schema-hsqldb.sql 

# Non-platform dependent settings that you might like to change 
# batch.data.source.init=true 

business-Plan-hsqldb.sql

DROP TABLE ERROR_LOG IF EXISTS; 
CREATE TABLE ERROR_LOG (
     JOB_NAME CHAR(20) , 
     STEP_NAME CHAR(20) , 
     MESSAGE VARCHAR(300) NOT NULL 
) ; 
3

Wiosna Batch Admin 2.0-build-SNAPSHOT wprowadzić nowy Annoation @EnableBatchAdmin na łatwą integrację z buta sprężyny. Istnieje również przykładowy projekt https://github.com/spring-projects/spring-batch-admin-samples.

+0

Dodałem https://jira.spring.io/browse/BATCHADM-235 * Zwolnij nowy kamień milowy (M2) z najnowszymi zmianami. * Z powodu SNAPSHOT w wersji. Musimy włączyć sprawdzanie migawek. Niestety rozwój Spring Batch zawiesił się. Nie ma nowych zatwierdzeń przez 8 miesięcy ... – gavenkoa

Powiązane problemy