I'm struggling to load my configuration in my simple SpringBootApplication. When I attempt to print out the variables in my configuratrion class, they are always null.
Initially I had my configurable variables in WatchApplication.java. However, all of the variables I thought would be read from configuration were still null. The configuration was at /main/resources/application.properties. I've since added a class just to hold the configuration that I plan to read in WatchApplication called WatchConfiguration.
I'm new to Spring and am feeling terminally stupid
The Structure of my classes is:
-main
|--java
| |--WatchApplication.java
| |--WatchConfiguration.java
|
|--resources
|--application.properties
Here's WatchApplication.java
#SpringBootApplication
public class WatchApplication {
private WatchConfiguration configuration;
public static void main(String[] args)
{
SpringApplication.run(WatchApplication.class, args);
}
/**
* Initialize the application
*/
#PostConstruct
public void initialize()
{
configuration = new WatchConfiguration();
System.out.println(configuration.getVideoDirectory());
}
}
Here is what my WatchConfiguration.java looks like
#Configuration
public class WatchConfiguration {
#Value("${video.output.directory}")
private String videoDirectory;
#Value("${target.sites}")
private List<String> targetSites;
public WatchConfiguration getWatchConfiguration ()
{
return new WatchConfiguration();
}
public String getVideoDirectory() {
return videoDirectory;
}
public void setVideoDirectory(String videoDirectory) {
this.videoDirectory = videoDirectory;
}
public List<String> getTargetSites() {
return targetSites;
}
public void setTargetSites(List<String> targetSites) {
this.targetSites = targetSites;
}
}
And my application.properties
video.output.directory = C:\\Users\\Alex\\Desktop\\output
# Target Sites
target.sites[0] = https://youtube.com
target.sites[1] = https://bing.com
Here is the output. Note the 'null' in the console that is supposed to be the video.output.directory property value.
[2019-09-04 20:09:00.752] - 16812 INFO [restartedMain] --- com.pirate.baywatch.BaywatchApplication: Starting BaywatchApplication on DESKTOP-ULP9VBQ with PID 16812 (C:\Users\Alex\IdeaProjects\baywatch\target\classes started by Alex in C:\Users\Alex\IdeaProjects\baywatch)
[2019-09-04 20:09:00.765] - 16812 INFO [restartedMain] --- com.pirate.baywatch.BaywatchApplication: No active profile set, falling back to default profiles: default
[2019-09-04 20:09:00.792] - 16812 INFO [restartedMain] --- org.springframework.boot.devtools.env.DevToolsPropertyDefaultsPostProcessor: Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
null
[2019-09-04 20:09:01.142] - 16812 WARNING [restartedMain] --- org.springframework.context.annotation.AnnotationConfigApplicationContext: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baywatchConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'target.sites' in value "${target.sites}"
[2019-09-04 20:09:01.148] - 16812 INFO [restartedMain] --- org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
[2019-09-04 20:09:01.154] - 16812 SEVERE [restartedMain] --- org.springframework.boot.SpringApplication: Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baywatchConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'target.sites' in value "${target.sites}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:380)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:743)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:390)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1214)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1203)
at com.pirate.baywatch.BaywatchApplication.main(BaywatchApplication.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'target.sites' in value "${target.sites}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:237)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:211)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:851)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1171)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
... 21 more
Solution
Solved by adding #Autowired to the member variable and removing the initialization of the configuration class from the initialize method
#SpringBootApplication
public class WatchApplication {
#Autowired
private WatchConfiguration configuration;
public static void main(String[] args)
{
SpringApplication.run(WatchApplication.class, args);
}
/**
* Initialize the application
*/
#PostConstruct
public void initialize()
{
System.out.println(configuration.getVideoDirectory());
}
}
The problem is that you are creating configuration by yourself, with new. You should #Autowired it from context in to your application class.
Remove this line configuration = new Watch Configuration and add #Autowired to definition of configuration. I would also suggest you to use configuration properties instead.
Related
I am implementing simple camel application using camel 3.14.0.
I start using modelcamelcontext.
But there is below exception during setting custom tracer.
2022-04-29 17:04:18.474 INFO 10264 --- [ main] target.atom.engine.EngineApplication : Started EngineApplication in 14.158 seconds (JVM running for 16.177)
2022-04-29 17:04:18.540 ERROR 10264 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: Cannot set tracer on a started CamelContext
at org.apache.camel.impl.engine.AbstractCamelContext.setTracer(AbstractCamelContext.java:4601) ~[camel-base-engine-3.14.0.jar:3.14.0]
at target.atom.common.config.TargetAtomConfig.reloadRoutes(TargetAtomConfig.java:54) ~[classes/:na]
at target.atom.common.config.TargetAtomConfig$$FastClassBySpringCGLIB$$7b88810d.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.1.jar:5.3.1]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.3.1.jar:5.3.1]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.1.jar:5.3.1]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.3.1.jar:5.3.1]
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89) ~[spring-aop-5.3.1.jar:5.3.1]
How do I set tracer in modelCamelContext?
source code
ModelCamelContext modelCamelContext = camelContext.adapt(ModelCamelContext.class);
TraceFormatter formatter = new TraceFormatter();
modelCamelContext.setTracer(formatter.getTracer(modelCamelContext));
modelCamelContext.setTracing(true);
…
Assuming that you are using Camel Spring Boot, the CamelContext can be customized thanks to a bean of type CamelContextConfiguration that is meant to be used to add custom logic before and after Spring Boot and the CamelContext have been fully started.
In your case, the idea is to add custom logic before the start up, so your code should look like this:
#Bean
CamelContextConfiguration contextConfiguration() {
return new CamelContextConfiguration() {
#Override
public void beforeApplicationStart(CamelContext context) {
// Configure the tracer before starting up the camel context
TraceFormatter formatter = new TraceFormatter();
context.setTracer(formatter.getTracer(modelCamelContext));
context.setTracing(true);
}
#Override
public void afterApplicationStart(CamelContext camelContext) {
// Nothing to do
}
};
}
Spring boot application works fine on my local but when I deploy it to K8s it shows error. Some context below:
Controller:
#RestController
#RequestMapping(path = "/v1/brightspot")
#AllArgsConstructor(onConstructor_ = {#Autowired})
#CrossOrigin
public class BrightspotController {
#Autowired
protected BrightspotService brightspotService;
/**
* Hello world.
*
* #return the hello world
*/
#GetMapping(value = "/helloWorld", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(HttpStatus.OK)
public String getHelloWorld() {
return "Hello, World!!";
}
.
.
<more_methods>
}
Service:
#Service
#NoArgsConstructor
public class BrightspotService {
public static final String DISPLAY_IMAGE_URL = "displayImageUrl";
public static final String AUTHOR_IMAGE_URL = "authorImageUrl";
public static final String URL = "url";
private static final Logger log = LoggerFactory.getLogger(BrightspotService.class);
#Autowired
protected BrightspotHelper brightspotHelper;
/**
* Get all articles via site search.
*
* #return response
*/
public SearchResultModel getAllArticles() throws Exception {
log.info("Received getAllArticles request");
try {
// TODO: Store searchResults in cache with expiry time of max 5 minutes
String searchResults = brightspotHelper.makeBrightspotRequest(
BrightspotHelper.SITE_SEARCH_URI, BrightspotHelper.SITE_SEARCH_QUERY);
JSONObject searchResultsObj =
brightspotHelper.appendImageUrl(new JSONObject(searchResults));
SearchResultModel searchResultModel =
ObjectMapperUtils.mapJson(searchResultsObj.toString(), SearchResultModel.class);
log.info("Response {}", searchResultsObj.toString());
return searchResultModel;
} catch (Exception e) {
log.warn(e.getMessage(), e);
throw new Exception(e);
}
}
.
.
<more-methods>
Helper:
#Component("BrightspotHelper")
#NoArgsConstructor
public class BrightspotHelper {
private static final Logger log = LoggerFactory.getLogger(BrightspotHelper.class);
.
.
<more-methods>
}
Error:
2021-03-23 23:14:19.493 WARN 1 --- [ main]
ConfigServletWebServerApplicationContext : Exception encountered
during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'brightspotService': Unsatisfied
dependency expressed through field 'brightspotHelper'; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'BrightspotHelper': Lookup method
resolution failed; nested exception is
java.lang.IllegalStateException: Failed to introspect Class
[com.wayfair.projectphoenix.utils.BrightspotHelper] from ClassLoader
[org.springframework.boot.loader.LaunchedURLClassLoader#529c2a9a]
2021-03-23 23:14:19.694 INFO 1 --- [ main]
o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2021-03-23 23:14:20.193 INFO 1 --- [ main]
ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report
re-run your application with 'debug' enabled. 2021-03-23 23:14:20.595
ERROR 1 --- [ main] o.s.boot.SpringApplication
: Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'brightspotService': Unsatisfied
dependency expressed through field 'brightspotHelper'; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'BrightspotHelper': Lookup method
resolution failed; nested exception is
java.lang.IllegalStateException: Failed to introspect Class
[com.wayfair.projectphoenix.utils.BrightspotHelper] from ClassLoader
[org.springframework.boot.loader.LaunchedURLClassLoader#529c2a9a] at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
at
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1415)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:608)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531)
at
org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:923)
at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
at
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
at
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
at
org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
at
org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1311)
at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
at
com.wayfair.projectphoenix.ExampleApplication.main(ExampleApplication.java:12)
at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method) at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown
Source) at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown
Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at
org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at
org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'BrightspotHelper': Lookup method
resolution failed; nested exception is
java.lang.IllegalStateException: Failed to introspect Class
[com.wayfair.projectphoenix.utils.BrightspotHelper] from ClassLoader
[org.springframework.boot.loader.LaunchedURLClassLoader#529c2a9a] at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:289)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1286)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:571)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531)
at
org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at
org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
... 28 common frames omitted Caused by:
java.lang.IllegalStateException: Failed to introspect Class
[com.wayfair.projectphoenix.utils.BrightspotHelper] from ClassLoader
[org.springframework.boot.loader.LaunchedURLClassLoader#529c2a9a] at
org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:481)
at
org.springframework.util.ReflectionUtils.doWithLocalMethods(ReflectionUtils.java:321)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:267)
... 40 common frames omitted Caused by:
java.lang.NoClassDefFoundError:
org/springframework/boot/configurationprocessor/json/JSONObject at
java.base/java.lang.Class.getDeclaredMethods0(Native Method) at
java.base/java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.base/java.lang.Class.getDeclaredMethods(Unknown Source) at
org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463)
... 42 common frames omitted Caused by:
java.lang.ClassNotFoundException:
org.springframework.boot.configurationprocessor.json.JSONObject at
java.base/java.net.URLClassLoader.findClass(Unknown Source) at
java.base/java.lang.ClassLoader.loadClass(Unknown Source) at
org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source) ... 46
common frames omitted
I also added qualifiers for service and helper class but was still having the same error.
You are missing a that contains org.springframework.boot.configurationprocessor.json.JSONObject.
That is what the exception java.lang.NoClassDefFoundError: org/springframework/boot/configurationprocessor/json/JSONObject is telling you.
You either are missing a dependency or included to wrong version.
Tried adding many versions of JSON dependency but it did not work, the dependency which worked for me to resolve the issue is spring-boot-configuration-processor
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
I am trying to connect to mysql for the same requirement using RefreshScope and it throws the following error
Could not obtain connection to query metadata : Error creating bean with name 'scopedTarget.userDataSource' defined in class path resource [com/concretepage/UserConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'userDataSource' threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [default driver]
2018-02-14 02:24:05.844 WARN 8920 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userEntityManager' defined in class path resource [com/concretepage/UserConfig.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
2018-02-14 02:24:05.846 INFO 8920 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2018-02-14 02:24:05.859 WARN 8920 --- [ost-startStop-1] o.a.c.loader.WebappClassLoaderBase : The web application [ROOT] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43)
2018-02-14 02:24:05.890 INFO 8920 --- [ main] utoConfigurationReportLoggingInitializer :
Below is the code where I have initialized the properties in userDataSource bean
#Configuration
//#PropertySource({ "classpath:application.properties" })
#EnableJpaRepositories(basePackages = "com.concretepage", entityManagerFactoryRef = "userEntityManager", transactionManagerRef = "userTransactionManager")
public class UserConfig {
#Value("${jdbc.driverClassName: default driver}")
private String driver;
// Properties
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean userEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(userDataSource());
em.setPackagesToScan(new String[] { "com.concretepage" });
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", hbm2ddl);
properties.put("hibernate.dialect", dialect);
em.setJpaPropertyMap(properties);
return em;
}
#Primary
#Bean
#RefreshScope
public DataSource userDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(usename);
dataSource.setPassword(password);
return dataSource;
}
#Primary
#Bean
public PlatformTransactionManager userTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(userEntityManager().getObject());
return transactionManager;
}
}
This code works with out using RefreshScope. Did I do anything wrong with the configuration?
When my springboot application startup, I have the following exception. I didn't found where is problem, if someone has an idea... thanks by advance
2015-05-18 14:50:49,313 DEBUG c.q.q.Application:50 - Running with Spring Boot v1.2.3.RELEASE, Spring v4.1.6.RELEASE
2015-05-18 14:50:51,848 DEBUG o.j.logging:33 - Logging Provider: org.jboss.logging.Slf4jLoggerProvider
2015-05-18 14:50:51,991 DEBUG c.q.q.c.AsyncConfiguration:36 - Creating Async Task Executor
2015-05-18 14:50:52,126 INFO c.q.q.Application:60 - Running with Spring profile(s) : [dev]
2015-05-18 14:50:52,752 DEBUG c.q.q.c.MetricsConfiguration:71 - Registring JVM gauges
2015-05-18 14:50:54,870 ERROR o.s.b.c.e.t.TomcatStarter:62 - Error starting Tomcat context: org.springframework.beans.factory.BeanCreationException
2015-05-18 14:50:54,914 WARN o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext:487 - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133) [spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474) ~[spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) [spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686) [spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) [spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at com.qwam.qes.Application.main(Application.java:84) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
at org.springframework.boot.maven.RunMojo$LaunchRunner.run(RunMojo.java:418) [spring-boot-maven-plugin-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]
Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:98) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:75) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:378) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:155) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:157) [spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130) [spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
... 11 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.setFilterChainProxySecurityConfigurer(org.springframework.security.config.annotation.ObjectPostProcessor,java.util.List) throws java.lang.Exception; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.setAuthenticationConfiguration(org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration); nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.setGlobalAuthenticationConfigurers(java.util.List) throws java.lang.Exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'springBootAuthenticationConfigurerAdapter' defined in class path resource [org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.boot.autoconfigure.security.SecurityProperties]: : Error creating bean with name 'securityProperties': Could not bind properties to [unknown] (target=security, ignoreInvalidFields=false, ignoreUnknownFields=false, ignoreNestedProperties=false); nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'token[key]' of bean class [org.springframework.boot.autoconfigure.security.SecurityProperties]: Cannot access indexed value in property referenced in indexed property path 'token[key]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'token[key]' of bean class [org.springframework.boot.autoconfigure.security.SecurityProperties]: Bean property 'token[key]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityProperties': Could not bind properties to [unknown] (target=security, ignoreInvalidFields=false, ignoreUnknownFields=false, ignoreNestedProperties=false); nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'token[key]' of bean class [org.springframework.boot.autoconfigure.security.SecurityProperties]: Cannot access indexed value in property referenced in indexed property path 'token[key]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'token[key]' of bean class [org.springframework.boot.autoconfigure.security.SecurityProperties]: Bean property 'token[key]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
this is my application class:
#ComponentScan (basePackages = { "com.test" })
#EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class})
#Domain(basePackages = { "com.test.domain" })
public class Application {
private final Logger log = LoggerFactory.getLogger(Application.class);
#Inject
private Environment env;
#PostConstruct
public void initApplication() throws IOException {
if (env.getActiveProfiles().length == 0) {
log.warn("No Spring profile configured, running with default configuration");
} else {
log.info("Running with Spring profile(s) : {}", Arrays.toString(env.getActiveProfiles()));
}
}
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setShowBanner(false);
SimpleCommandLinePropertySource source = new SimpleCommandLinePropertySource(args);
// Check if the selected profile has been set as argument.
// if not the development profile will be added
addDefaultProfile(app, source);
}
/**
* Set a default profile if it has not been set
*
* #param app
* #param source
*/
private static void addDefaultProfile(SpringApplication app, SimpleCommandLinePropertySource source) {
if (!source.containsProperty("spring.profiles.active")) {
app.setAdditionalProfiles(Constants.SPRING_PROFILE_DEVELOPMENT);
}
}
/**
*
* #return
*/
#Bean
public HttpMessageConverter<String> responseBodyConverter() {
return new StringHttpMessageConverter(Charset.forName("UTF-8"));
}
#Bean
public Filter characterEncodingFilter() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return characterEncodingFilter;
}
/**
*
* #return
*/
#Bean
public BeanNameAutoProxyCreator lazyInitAutoProxyCreator() {
BeanNameAutoProxyCreator autoProxyCreator = new BeanNameAutoProxyCreator();
TargetSourceCreator[] targetSourceCreators = {lazyInitTargetSourceCreator()};
autoProxyCreator.setCustomTargetSourceCreators(targetSourceCreators);
return autoProxyCreator;
}
#Bean
public LazyInitTargetSourceCreator lazyInitTargetSourceCreator() {
return new LazyInitTargetSourceCreator();
}
}
Try to add the #Configuration annotation to your Application class
#Configuration
#ComponentScan (basePackages = { "com.test" })
#EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class})
#Domain(basePackages = { "com.test.domain" })
public class Application {
//some code
}
According to the documentation spring batch admin is very easy to embed into the existing application. Simply copying web.xml and index.jsp then adding needed dependencies is enough getting it to work.
But if I want to use it in an existing spring boot project it getting worse. According to this example the configuration is a bit hacky but it works. UNTIL I try to use #EnableBatchProcessing annotation in my configuriton bean. Then I get the following exception.
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
My configuration is quite simple I have two configuration beans
#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 {
}
and
#Configuration
#EnableBatchProcessing
public class BatchImporterConfiguration {
}
When I remove #EnableBatchProcessing and try to create jobs with JobBuilderFactory and use #StepScope annotation I'm getting other ClassCastExceptions.
Now I'm using xml based configuration to create jobs, steps and other beans. It work well but I would actually preffer xml free configuration. Is there a way to easily integrate spring boot, spring batch and spring batch admin ?
Spring Batch Admin 2.0-BUILD-SNAPSHOT introduce a new Annoation #EnableBatchAdmin for easy to integrate with spring boot.
There is also a samples project https://github.com/spring-projects/spring-batch-admin-samples.
The short answer is that you won't want to use #EnableBatchProcessing with Spring Batch Admin. SBA provides a number of beans on a global scale that the #EnableBatchProcessing also provides. SBA 2.0 (currently in development) will probably fill the gaps between what is currently there and what #EnableBatchProcessing provides (specifically providing the JobBuilderFactory and StepBuilderFactory).
To get yourself running, you should be able to (I haven't tired this myself) configure in the META-INF/spring/batch/override/ directory a JobBuilderFactory and a StepBuilderFactory for global use. From there, you can use XML files in the META-INF/spring/batch/jobs directory that do nothing more than component scan for your #Configuration classes. However, leave off the #EnableBatchProcessing because of the duplication of beans.
For the record, this isn't an Spring Boot issue since #EnableBatchProcessing is a Spring Batch annotation, not a Boot one.
to complete the answer, here is the code to create the two beans once you disable the #EnableBatchProcessing annotation
#Autowired
JobRepository jobRepository;
#Autowired
PlatformTransactionManager transactionManager;
#Bean
public JobBuilderFactory jobBuilderFactory() {
return new JobBuilderFactory(jobRepository);
}
#Bean
public StepBuilderFactory stepBuilderFactory() {
return new StepBuilderFactory(jobRepository, transactionManager);
}
I've a working version here based on the same example (I forked the original one): https://github.com/vesperaba/spring-batch-admin-spring-boot.
I followed Michael Minella advice and I overwrote the SpringBatch property holder with a custom one.
I also added a job to check it's working now
This ClassCastException is caused by
classpath:/org/springframework/batch/admin/web/resources/servlet-config.xml
loading
META-INF/spring/batch/servlet/resources/resource-context.xml
which contains
<mvc:annotation-driven />
This conflicts with the mvc configuration in the Spring Java configuration class. The following class can be used to embed Spring Batch Admin within an existing application that uses Java configuration.
#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;
}
}
A single XML file is also required for the abstract base menu which is referenced elsewhere in the Spring Batch Admin project. This is required as abstract beans can not be provided from a Spring Java configuration.
<?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>
Maven dependencies. Take care to ensure only a single version of the base Spring framework is pulled in by Maven.
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-admin-manager</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
<version>1.8.0.10</version>
</dependency>
Spring batch also expects in a default configuration for the following files to exist at the root of the classpath.
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-schedule-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
) ;