Define in Spring Boot Configuration Bean from groovy file - java

I want to know if it is possible in Spring Boot 2.x to define a class annotated with #Configuration in a groovy file and load the class as a normal annotated java class.
What I've done is define a class inside a groovy file annotated and then load it using xml bean definition of Spring, but it doesn't work.
SpringBoot main class annotated with #ImportResource("classpath:beans.xml")
xml file (beans.xml)
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">
<lang:groovy id="jpaconfig" script-source="classpath:JpaConfig.groovy">
</lang:groovy>
</beans>
The groovy file
#Configuration
public class JpaConfig {
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
#Bean(name = "primaryDataSource")
#Primary
#ConfigurationProperties("spring.datasource.hikari")
public DataSource primaryDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder().build();
}
}

Related

Java : How to load content of .properties file into Properties using spring annotation?

I am using Java 8 on spring framework. I have a properties file which has "=" separated values in it. I am trying to load the values of the properties file into a Property directly using spring annotation.
For example :
my Application.properites has:
cat=250
dog=560
lama=1000
donkey=650
And I have declared this properties file in my context.xml as :
<util:properties id="app_props"
location="classpath*:/application.properties" />
Now in my main class I am trying to load all of the values in Application.properites into
private Properties properties;
So that properties.getProperty("cat") will return "250"
Not sure how to do it. May I get any help on that?
Register your properties file as follows
XML Config
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<context:property-placeholder location="classpath:foo.properties" />
</beans>
Java Config
#Configuration
#PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
//...
}
Using your properties as follows
#Value( "${jdbc.url}" )
private String jdbcUrl;
You can find a complete working solution in my GitHub repository
https://github.com/mirmdasif/springmvc/tree/master/springproperties

Spring doesn't instantiate bean at start

I'm stuck with the following problem. My application doesn't create my Services at startup and I end up with a NullPointerException when I try to use them in my Maven Tests after Inject them with #Autowired.
I don't understand where it comes from. I have done some research but I still don't understand why it doesn't work.
Here is the class where my Autowired administrationActionService is null:
public class AdministrationActionTests extends EntityTests {
#Autowired
AdministrationActionService administrationActionService;
#Test
public void equalsTests() {
administrationActionService.getExample();
[...]
The class :
package com.bloombooking.services;
#org.springframework.stereotype.Service
public class AdministrationActionService extends ServiceEntity{
#Autowired private AdministrationActionDao administrationActionDao;
[...]
And my ApplicationContext.xml. I've placed it in src/ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.bloombooking.services, com.bloombooking.dao"/>
</beans>
I really don't know what I could have done wrong. Can someone help me? Thanks!
To make it work you have to make the following changes:
add #RunWith(SpringJUnit4ClassRunner.class) to your class.
add #ContextConfiguration("path_to_you_spring_beans.xml")
So your class becomes:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("path_to_you_spring_beans.xml")
AdministrationActionTests {
}

Spring: define custom #Transactional behavior in Java config

I would like Spring to rollback a transaction on methods annotated with #Transactional in case the method throws a checked exception. An equivalent of this:
#Transactional(rollbackFor=MyCheckedException.class)
public void method() throws MyCheckedException {
}
But I need this behavior to be default for all #Transactional annotations without the need to write it everywhere. We are using Java to configure Spring (configuration classes).
I tried the configuration suggested by spring documentation, which is only available in XML. So I tried to create this XML file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" rollback-for="com.example.MyCheckedException" />
</tx:attributes>
</tx:advice>
</beans>
... and import it via #ImportResource. Spring did recognize and parse the file (I had some errors in it at first), but it doesn't work. The behavior of #Transactional has not changed.
I also tried defining my own transaction property source, as suggested in this answer. But it also used the XML configuration so I had to transform it into Java like this:
#Bean
public AnnotationTransactionAttributeSource getTransactionAttributeSource() {
return new RollbackForAllAnnotationTransactionAttributeSource();
}
#Bean
public TransactionInterceptor getTransactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource);
return transactionInterceptor;
}
#Bean
public BeanFactoryTransactionAttributeSourceAdvisor getBeanFactoryTransactionAttributeSourceAdvisor(TransactionAttributeSource transactionAttributeSource) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
return advisor;
}
This also didn't work - Spring kept using its own transaction property source (different instance than the one which was created in the configuration).
What is the correct way to achieve this in Java?
You should rather implement own annotation - reference
#Target({ElementType.METHOD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Transactional(rollbackFor=MyCheckedException.class)
public #interface TransactionalWithRollback {
}

Java Spring Scheduled job not working

I have a web application which is supposed to run a scheduled code:
package com.myproject.daemon.jobs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
public class MyDaemonJob {
private static final Logger log = LoggerFactory.getLogger(MyDaemonJob.class);
#PostConstruct
public void init() {
log.info("MyDaemonJob is intialized " );
}
#Scheduled(fixedDelay = 1000)
public void startDaemon() {
try {
log.info("MyDaemonJob is running ...");
} catch (Exception e) {
log.error("Encountered error running scheduled job: " + e.getMessage());
}
}
}
It surely is recognized as a Spring bean and initialized, as I can see from the PostConstruct log. However the method with the #Scheduled annotation never runs although it is supposed to run every 1 second.
Here is app context xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="
com.myproject.daemon.jobs,
com.myproject.product" />
</beans>
Thank you ALL for quick help. This is really helpful.
The code started working, once I added config class with annotations as shown below --
package com.myproject;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
#Configuration
#EnableScheduling
public class AppConfig {
// various #Bean definitions
}
To use the #scheduled annotation it is necessary to include the spring task name space in spring bean configuration xml file. You can update the following namespac e in your xml configuration file.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.1.xsd">
Otherwise if you use the spring-boot application you can include the #EnableScheduling in your configuration file

Unit testing ONE piece of JSR 303 validator class in Spring

I would like to unit test one validator class in Spring. There are 6 other existing validator classes but they don't have unit tests so I only want to test my validator class.
My problem is that when I run my unit test (which tests only my class) "somehow" an other validator class is being tested... (it doesn't have unit test).
Is it possible that this is the default behaviour of the LocalValidatorFactoryBean to scan all the validator classes and to run their isValid method?
Can I specify the validator classes somehow that have to be tested? Like defining a ConstraintValidatorFactory?
Java test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"/applicationContext-test-validator.xml"})
public class MyValidatorTest {
#Autowired
private Validator validator;
#Test
public void testIsValid_true() {
...
Set<ConstraintViolation<Record>> violations = validator.validate(data);
...
}
}
application context XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
</beans>
Thanks,
V.

Categories