Flyway and spring integration - spring

How do I properly configure flyway when integrating with Spring? I see there is a configure method that takes properties, but from the spring XML it would take a setter method to provide a way to inject a Properties instance.
I could write my own Pojo to delegate the configuration to the flyway instance, but it somehow feels like I have missed something.
Here is my configuration:
<bean
id="flyway"
class="com.googlecode.flyway.core.Flyway"
init-method="migrate"
lazy-init="false"
depends-on="dataSource"
>
<property name="dataSource" ref="dataSource" />
<property name="locations" value="classpath:/META-INF/migrations" />
</bean>
I would like to provide a dedicated property file for the migration configuration as documented here:
https://github.com/flyway/flyway/blob/master/flyway-commandline/src/main/assembly/flyway.properties
From the javadoc I see that I can set most of the properties. I could work with spring ${} property replacements and loading the property file with the built in mechs, but this would make those properties available to all beans, and I would add each one I need.
My wrapper would provide a setter so I could add the following to my spring xml config:
<property name="configLocations" value="classpath:/META-INF/flyway.properties" />
Any thoughts appreciated.

Spring's MethodInvokingFactoryBean should do what you want.

Alternatively, you can create a migration based on JdbcTemplate using Flyway's SpringJdbcMigration. The following example is copied from the Flyway documentation:
import com.googlecode.flyway.core.api.migration.spring.SpringJdbcMigration;
import org.springframework.jdbc.core.JdbcTemplate;
public class V1_2__Another_user implements SpringJdbcMigration {
#Override
public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
jdbcTemplate.execute("INSERT INTO test_user (name) VALUES ('Obelix')");
}
}

You should use spring annotation and wrap Flyway class, and do whatever you want. For instance, configuring flyway properties. This blog post may give you an example how to do http://esofthead.com/migrate-database-highly-change-environment-multiple-versions-management/

Related

How to inject spring properties into wicket components?

I'm searching for a possibility to inject a property which is defined in a spring context (provided by a propertiesFactoryBean) into a wicket component. I know the way to inject beans into components by using the #SpringBean-Annotation, but whats the corresponding way for properties?
The way my property is defined:
<bean id="myPropertiesFactory" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="mySpringProperty">mySpringProperty</prop>
</property>
</bean>
Things I've tried. The way it works usually with self defined beans:
#Inject
#Value("${mySpringProperty}")
Using the name of the propertiesFactory to access the property value
#Inject
#Value("$myPropertiesFactory.properties.mySpringProperty")
Using the Value Annotation
#Value("#myPropertiesFactory['mySpringProperty']")
Using SpringBean
#SpringBean(name="myPropertiesFactory.mySpringProperty")
None of these solutions works. So to get mySpringProperty injected i use the workaround to create a bean of the type String which get's injected properly by wicket when i annotate the corresponding member of my component with SpringBean but i think there must be a better solution.
<bean id="mySpringPropertyBean" class="java.lang.String">
<constructor-arg type="java.lang.String" value="https://foobar.com" />
</bean>
Annotate
#SpringBean
private String mySpringPropertyBean;
#SpringBean only supports injection of spring beans. I suppose someone could implement a #SpringValue annotation that does what you want, but as far as I know noone ever did.
What I usually do is:
My wicket application class is a spring bean.
It has properties with #Value annotations - as the object is a spring bean, these are evaluated and set properly
I access the actual values by calling MyApplication.get().getXXX() or ((MyApplication)getApplication()).getXXX()
If the app grows and the number of attributes approach a limit, I refactor them into separate Settings or Config classes - each one a spring bean of it's own, accessible from the application class.
In your Wicket class use instead of #Value("${mySpringProperty}"):
#SpringBean
private PropertiesConfiguration propertiesConfiguration;
Create a new PropertiesConfiguration class:
#Component
public class PropertiesConfiguration {
#Value("${mySpringProperty}")
private String mySpringProperty;
//getters & setters
}
Use in your wicket class:
System.out.println("mySpringProperty=" + propertiesConfiguration.getMySpringProperty());

Activiti JNDI Datasource Configuration

I am installing Activiti 5.17.0's Activiti Explorer and would like to use a JNDI-based datasource configuration to connect to an Oracle DB. The documentation I found here: http://www.activiti.org/userguide/#jndiDatasourceConfig is very explicit about making this change but unfortunately the docs seems to be obsolete.
In particular, I found no activiti-standalone-context.xml and no activiti-context.xml at the mentioned places. I assume it got changed to activiti-custom-context.xml, but the whole content of this Spring configuration is commented out (which makes me wonder where the actual Spring config might come from).
I tried to configure the datasource in this file anyway using this approach:
<jee:jndi-lookup id="dataSource"
jndi-name="jdbc/activiti-ds"
expected-type="javax.sql.DataSource" />
and this approach as well:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="proxyInterface" value="javax.sql.DataSource"/>
<property name="jndiName"><value>jdbc/activiti-ds</value></property>
</bean>
but both my attempts ended up in the same ClassCastException, claiming that the generated Proxy class is not an instance of javax.sql.DataSource:
java.lang.ClassCastException: org.springframework.jndi.JndiObjectFactoryBean$$EnhancerBySpringCGLIB$$69ba43af cannot be cast to javax.sql.DataSource
at org.activiti.explorer.conf.ActivitiEngineConfiguration$$EnhancerBySpringCGLIB$$5db7207e.dataSource(<generated>)
at org.activiti.explorer.conf.ActivitiEngineConfiguration.processEngineConfiguration(ActivitiEngineConfiguration.java:91)
Any hints how to accomplish to this task? Maybe a pointer to an up-to-date documentation?
For further reference, I solved the problem by editing the Spring JavaConfig in ActivitiEngineConfiguration.java and replacing the dataSource bean creation there with the following code:
#Bean
public DataSource dataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
DataSource dataSource = dsLookup.getDataSource("jdbc/activiti-ds");
return dataSource;
}
After recompiling the module and deploying, it seems to work flawlessly.
Thanks a lot to Greg Harley above whose questions and commented helped to solve the problem!
The Activiti users guide includes updated instructions for how to configure a JDBC datasource here: http://www.activiti.org/userguide/#jndiDatasourceConfig
You will need to configure a datasource bean in the ActivitiEngineConfiguration class of your web application and update the following line of code to reference your new datasource:
processEngineConfiguration.setDataSource(dataSource());
If you want to continue to use the Spring XML configuration, you can still define your custom beans in the activiti-custom-context.xml.

Spring Rest Controller handling java.util.Optional using Jackson

I have got Spring RestController classes to handle rest services using JSON. For JSON I am using Jackson. There are fields of java.util.Optional type
private Optional<Long> start = Optional.empty();
To enable the handling of Optional type, I am configuring the Spring as follows
<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="modulesToInstall" value="com.fasterxml.jackson.datatype.jdk8.Jdk8Module" />
</bean>
However when I call the webservice, it fails in deserializing the Optional types with following message
org.springframework.http.converter.HttpMessageNotReadableException:
Could not read JSON: Can not instantiate value of type
[simple type, class java.util.Optional<java.lang.Long>]
from Long integral number (3424323423432); no
single-long-arg constructor/factory method
Doing serialization/deserialization from stand alone code works fine. There I register the module directly using the following code
ObjectMapper m = new ObjectMapper();
m.registerModule(new Jdk8Module());
Versions I am using:
Spring : 4.1.5.RELEASE
Jackson: 2.5.1
Thanks in advance
I could figure out this. The solution is to register the object mapper to Message converter as follows
<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="objectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="modulesToInstall"
value="com.fasterxml.jackson.datatype.jdk8.Jdk8Module" />
</bean>
If you are using latest version of Spring-boot then you could achieve this by adding the following dependency in the pom file
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
Spring blog says :
Some well known Jackson modules are automatically registered if they are detected on the classpath:
jackson-datatype-jdk7: Java 7 types like java.nio.file.Path (as of 4.2.1 release)
jackson-datatype-joda: Joda-Time types
jackson-datatype-jsr310: Java 8 Date & Time API data types
jackson-datatype-jdk8: other Java 8 types like Optional (as of 4.2.0 release)
And if you want to use the mapper in your code, auto wire the JacksonObjectMapper.
#Autowired
private ObjectMapper jacksonObjectMapper;
Then use the above Spring container's mapper instance to convert Object to String
jacksonObjectMapper.writeValueAsString(user);
The answer above works for Spring 4.
Just make sure you're using the latest xsd's in your xml configuration.
In my situation it was somehow referencing 'spring-mvc-3.0.xsd' and this version does not know the 'mvc:message-converters' tag yet. Changing it to 'spring-mvc.xsd' solved this issue.

How to do Multiple File Upload in Spring - Java Config

I been trying to find a example of how to do multiple file upload in Spring MVC without using XML only Java Config. So far have found nothing and a lot of people that just either want hits to sites or don't know what java configuration v xml configuration is.
I don't use Spring Boot and don't want to as I want to learn this framework no matter how difficult.
Even advice on how to convert the following line to java config would be appreciated:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1000000" />
</bean>
Please do advise also what JARs i would need for the above multipartResolver.
Thanks a bunch gang
That line translates to
#Bean
public MultipartResolver multipartResolver() {
org.springframework.web.multipart.commons.CommonsMultipartResolver multipartResolver = new org.springframework.web.multipart.commons.CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(1000000);
return multipartResolver;
}
Within a #Configuration class which you'd load in your Servlet context.
You need commons-fileupload library for this to work.

JUnit test in Spring - overriding and ignoring beans from application other configuration classes

We have large application written in Spring 3. I need to write JUnit test checking behavior of some service. It is not a unit but part of a system. There are some services and repositories working together insite it -> lot of injected beans inside. The app also uses aspects.
My question is. How to manage config and beans in this case of tests? I need to use beans defined in app configes and in tests only redefine beans using persistence to work with a embedded db. So I need to use beans from src as they are defined and override only some causing troubles (persistance beans, beans using webservices,...)
In test package I made Config class definying beans for persistance, using datasource for hsql. But I don`t know what next. I tried to annotate Test config class with:
#Configuration
#EnableAspectJAutoProxy
#EnableTransactionManagement(mode = AdviceMode.ASPECTJ, proxyTargetClass = true)
#ComponentScan(basePackages = "com.example.our.app")
public class MyTestConfig implements TransactionManagementConfigurer {
to scan whole application and use configuration of beans from src folder. But this also takes configs from other tests causing problems. Is this whole good strategy or not? What now - use excludeFilters to remove other test configs? Or is this strategy whole bad?
thanks
You can selectively overwrite beans with the context merging functionality supplied by the #ContextHierarchy annotation.
In order to get this working for your use case you will have to create a base context that scans your app for Spring beans:
#Configuration
#ComponentScan({"com.example.our.app"})
public class MyTestConfig implements TransactionManagementConfigurer {
Then create a base class that utilizes this context and names it - this won't work with named contexts!:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextHierarchy( {
#ContextConfiguration(name="testContext", classes = MyTestConfig.class),
})
public class BaseTest {
And finally write a unit test that extends the base class and defines a new context under the same name to overwrite individual beans with a test specific configuration:
#ContextHierarchy(#ContextConfiguration(name="testContext", classes = OneUnitTest.Config.class))
public class OneUnitTest extends AggroBaseTest {
#Configuration
static class Config {
..
}
I think best way here to use is Spring profiles.
Check here now to use H2 for tests with profiles.
You can also override with another import
<beans>
<import resource="classpath*:applocationContext.xml" />
<bean id="dataSourceFactory" class=com.demo.MyNewClass/>
</beans>
And in you class if you
this.applicationContext.getBean("dataSourceFactory");
retrieve the class, you would see the instance of new class
Further
<bean id="dataSourceFactory" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
So there are different ways you can override the default behaviour

Resources