How can I change the value of #PropertySource in run time when the junit test case runs. For example,
I want to replace the value of below,
#PropertySource(value = "file:${app.deploy.env}/sample/mine.properties", ignoreResourceNotFound = true)
with
value = "classpath:sample/mine.properties"
when junit test runs.
You can do that if you really want to but I'd not recommend you to do that this way. You first need to figure out which PropertySource contains the value. Since you have that annotation in your example, a PropertySource will be added to the regular ones, probably as the first instance.
You can inject the Environment in a managed bean where you want to make that change as a ConfigurableEnvironment and retrieve the PropertySource via un call to getMutablePropertySources() on the environment.
Having said that. Why? How is changing such fundamental property of your application is representative of what is going to happen in your app. It looks like you are using the Spring runner and you'd like to start your app with different settings in different test methods. If that's what you want to do, do not use the runner but manage the context yourself, it's really not that hard.
For instance, here are JMS-related tests that change the Environment to test various scenarios. You can easily load the context with a specific set of keys and a #After method makes sure to shutdown the context for each test.
We use this pattern quite a lot in Spring Boot. As a matter of a fact, I have a JUnit rule that facilitates all that on my todo list for months now.
Related
I was wondering about this question by having some trouble writting unit tests for my spring application.
Let's take the following example:
#SpringBootTest
#RunWith(SpringRunner.class)
public class AlbumDTOConverterTest {
#Autowired
private AlbumDTOConverter albumDTOConverter;
#Test
public void ToEntity_ReturnValue_NotNull() {
AlbumDTO albumDTO = new AlbumDTO("Summer album", new Date(), "This summer, we have made some wonderfull photos. Have a look!", null);
assertNotNull(albumDTOConverter.toEntity(albumDTO));
}
}
In order to make #Autowired work properly, I am launching a container with annotating the test class with #SpringBootTest.
The thing is that I think I am doing this wrong. In my opinion, I'll rather just create a new instance of AlbumDTOConverter by just using the new operator instead of using Spring's IoD.
What do you guys think about this ?
For unit tests you don't need a whole container to start. By definition, such units should be tested in isolation. Creating an instance of a class with the new keyword is perfectly fine. Even if the class has dependencies on other classes, you can also create them manually and pass to an appropriate constructor of the class.
Note that the unit is not the same as the class. The term of the unit is commonly confused among developers, especially beginners. You don't have to rely on the dependency injection in your unit tests. The container will only increase the time needed to execute the tests and the long execution time is the main reason why developers avoid running them very often. There is nothing wrong in manually building your dependency tree for a unit under tests.
In the long run, creating similar inputs for different tests might lead to duplication in the test code, but fortunately there are best practices for this problem, e.g. shared fixture.
If you are doing unit test then you should not use #Autowire every time.
Unit test basic says "Unit tests are responsible for testing a specific piece of code, just a small functionality (unit) of the code"
Now question is when to use spring capabilities ?
Sometimes, you'll need to do some unit tests relying on Spring framework like web service call, repository call etc. For example, if you have a repository that has a custom query using the #Query annotation, you might need to test your query. Also, if you are serialising/deserialising objects, you'd want to make sure that your object mapping is working. You might want to test your controllers as well, when you have some parameter validation or error handling. How can you be sure that you are using Spring correctly? In these situations you can take advantage of the new Spring Boot's test annotations.
I thinks this will give better idea.
I have been using Xml configuration for Spring Batch for a while, and feel it is simpler and concise. However, nowadays, people are suggesting to use javaconfig over xml. I googled this topic.
This site tells us why javaconfig is better https://blog.codecentric.de/en/2013/06/spring-batch-2-2-javaconfig-part-1-a-comparison-to-xml/
Top reasons to choose javaconfig over xml:
We want to do some basic configurations in the framework. People add
a dependency to our framework library and import those
configurations according to their needs. If these configurations
were written in XML, they would have a hard time opening them to
look what they are doing. No problem in Java.
There’s no navigability in XML. That may be okay as long as you
don’t have too many XML files and all of them are in your workspace,
because then you can take advantage of the Spring IDE support. But a
framework library usually should not be added as a project to the
workspace. When using Java based configuration you can perfectly
jump into framework configuration classes. I will talk more about
this subject in a following blog post.
In a framework you often have requirements
the user of the library has to fulfill in order to make everything
work, for example the need for a DataSource, a
PlatformTransactionManager and a thread pool. The implementation
doesn’t matter from the perspective of the framework, they just need
to be there. In XML you have to write some documentation for the
users of framework, telling them they need to add this and this and
this Spring bean under this name to the ApplicationContext. In Java
you just write an interface describing that contract, and people
using the library implement that interface and add it as a
configuration class to the ApplicationContext. That’s what I did
with the interface.
This site tells us why xml is better https://dzone.com/articles/consider-replacing-spring-xml
Top reasons to choose xml over javaconfig
Configuration is centralized, it’s not scattered among all different components so you can have a nice overview of beans and their wirings in a single place.
If you need to split your files, no problem, Spring let you do that. It then reassembles them at runtime through internal tags or external context files aggregation.
Only XML configuration allows for explicit wiring – as opposed to autowiring. Sometimes, the latter is a bit too magical for my own taste. Its apparent simplicity hides real complexity: not only do we need to switch between by-type and by-name autowiring, but more importantly, the strategy for choosing the relevant bean among all eligible ones escapes but the more seasoned Spring developers. Profiles seem to make this easier, but is relatively new and is known to few.
Last but not least, XML is completely orthogonal to the Java file: there’s no coupling between the 2 so that the class can be used in more than one context with different configurations.
I concluded that xmls can still be used, if you are creating standalone batch jobs and if you are not creating any new frameworks by integrating with Spring Batch.
Any disadvantage of xmls that I am missing out ?
Let me add a couple of additional thoughts on the topic.
What I really like when using javaconfig is the ability to create your jobs dynamically. E.g., you could have an inputparameter with filenames and then create a job that executes reading and processing this files in parallel by creating a step for every received filename. (using a MultiResourceItemReader would do this sequentially). Moreover, depending on inputparameter, you could also define the job flow differently.
My thoughts on your reasons why choosing xml over javaconfig:
point 1: this doesn't really count in my opinion. You can have your own configuration classes, you can define your own packages. You could even put them in own modules. This is just a matter, how you organize your code.
point 2: again, this doesn't count as well. You can split your configuration in as many classes as you'd like. You can use the #Import and #ContextScan annotation in order to integrate what you want into your context.
point 3: autowiring can also be very explicitly, if you do it by class and not by interface. Moreover, you can also call directly the method annotated with #Bean. An example:
#Configuration
public MyBeanFactory {
#Bean
public MyBeanInterface bean1() {
return ...;
}
#Bean
public MyBeanInterface bean2() {
return ...;
}
}
#Component
public MyBeanuser {
#Autowired
private MyBeanFactory beanFactory;
#PostConstruct
public void afterPropertiesSet() {
// this will actually set the bean that was created an registered in the
// spring context and not simply call the the method and create a new
// instance. So this wiring is very explicitly
setProperty1(beanFactory.bean1());
setProperty2(beanFactory.bean2());
}
In the end, I guess it is also a matter of taste. I was using xml-configuration for over 5 years in the context of spring batch. Two years ago, we completely switched to use javaconfig instead of xml. And honestly, I haven't found one single reason why I should want to go back to use xml. However, this is my "matter of taste".
I'm in the middle of a massive refactoring project, the code has a 5000 line main class which was injected into everything, stored everything and had all of the common code.
I'm no expert on analysis and design but I've separated out things to the best of my ability and I'm about 80% through refactoring the classes that depend on the main class to use the new classes I've created.
There are some types of data which are initialised when the application starts and accessed by pretty much everything throughout the life of the application. For instance there is a Config class which holds hundreds of parameters.
The approach I've taken is to create several singletons the two most central are GUIData and ClientData. GUIData contains a reference to the mainframe of the application and clientdata maintains references to the config and other similar classes.
This allows me to call ClientData.getInstance().getConfig().getParam("param") from anywhere in the code but I don't feel like this is the best approach.
I considered individual static classes instead of these data singletons which contain instances of the classes but some of the classes do need constructors.
I've been googling on and off for a week trying to find a better way to do this but somehow I always end up on threads talking about database caching
Immutable (configuration) instances provide "thread-safe application-wide data access".
Typesafe's config (as suggested in a comment by Brian Kent) does exactly that.
Note that this does not involve static classes or singletons. Static classes and singletons may serve your purposes now,
but they could prove bothersome in the future. They can be handy ofcourse, but try limiting their use.
Initialization will have to be done after reading and parsing the configuration data. It is typically done at application startup, before other processing threads are started. The initialization will have to validate the configuration data as much as possible in order to fail fast and terminate the program if the configuration data is no good.
Having a lot of configuration data bundled together can create "hidden lines of communication". E.g. you update one value and the application fails because it required updates to other values as well. It's perfectly fine to put all configuration data in one file and load it from there, but your application (with hundreds of configuration options) should divide the configuration data in sets that are used by different parts of your application. This improves isolation, helps unit-testing and makes it possible to change the application in the future without getting too many nasty surprises.
There are two ways to use a set of configuration data:
from within an object call a singleton Settings.getInstance().getConfigForThisModule().
provide each object that uses configuration data with the configuration data via the constructor or via setConfig(ConfigForThisModule config).
The first approach depends on a convention not to call Settings.getInstance().getConfigForACompletelyUnrelatedModule() which could be a weakness. The second approach is more in line with "dependency injection" and could be more future proof.
You could mix both approaches while you are refactoring, just make sure to be consistent (e.g. only use the singleton approach for configuration data that is used in all parts of the application).
To further improve your design for using the configuration data, keep the following (likely) future functional requirement in mind: when the configuration file is updated, configuration data is reloaded and used in the application. Most logging frameworks manage to support this functional requirement without affecting the performance of multi-threaded applications. Among other things, it requires the following of your application:
if the new configuation data is no good, the program is not terminated but an error is logged instead and the old configuration data remains in use. Your initialization procedure will need to handle both "load at fresh start" and "reload" scenarios. The main thing to take away from this is that your initialization procedure needs to be re-usable and should not affect other (running) parts of your application (isolation, again).
long-lived objects may not keep a local copy of configuration data or a reference to an instance of ConfigForThisModule, instead Settings.getInstance()... (or some other method that can return an updated instance) should be called regurarly.
replacing old configuration with new configuration may not result in errors. Technically, replacing the configuration is as simple as updating an AtomicReference with a new configuration instance returned with Settings.getInstance().... But this is also where the isolation of the configuration data sets are tested: there should be no problem using an old set in one module and a new set in another module at the same.
Configuration data can be seen as a sort of "global state". With that in mind, further design points on what to do and what to avoid (partially blatantly copied to this answer) are discussed in the following two questions:
Why is Global State so Evil?
How are globals any different from a database?
Sorry, the question is a bit vague, are you looking to store the config or the cached objects used by other parts of your program ?
Since you have 100s of params, start with splitting up the config into manageable blocks
1) Split up your configuration parameters into logical blocks that have 1:1 correspondence with a simple properties file -its going to take some time
2) These property files must be externalized so that you can change them at any point in time, make sure that you pass in the base location via a env variable to the program
3) Write a utility class (singleton) that wraps Apache commons configuration to hold your config. (read *.properties from the base location and merge the properties into one configuration object) this must be done before any threads are kicked off.
4) Refer to the configuration param in your code using config.getXXXX() methods
Apache commons config also has ability to reload the config when your properties file changes on the filesystem.
Once this is done, use a DI container like Spring or Guice to cache the configured objects.
If it's just String property values you need, you don't even need a class for that - a global facility exists for you already: System.getProperties()
All you need do is first load the property values on start up:
System.setProperty("myKey", "myValue"); // see below how load properties from a file
Then read it anywhere in your code:
String myValue = System.getProperty("myKey");
or
String myValue = System.getProperty("myKey", "my desired default");
If your container doesn't support property loading out of the box, to load properties from an external file that looks like this:
key1=value
key2=some other value
etc...
you can use this code:
Files.lines(Paths.get("path/to/file"))
.filter(line -> !line.startsWith("#") || !line.contains("=")) // ignore comment/blank
.map(line -> line.split("=", 2)) // split into key/value
.forEach(split -> System.setProperty(split[0], split[1])); // load as property
you can use the Java Properties class util, basically its a HashTable
reference : https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html
you create a file fileName.properties and store your data in key value pairs, for example:
username=your name
port=8080
then you load it into Properties Object and get the data like the following:
Properties prop = new Properties();
load the file...
String userName = prop.getProperty("username")
String port = prop.getProperty("port")// you can parse it to int if needed
what i suggest is to create a property file for each type of configuration like:
clientData.properties
appConfig.properties
you can follow this simple tutorial
http://www.mkyong.com/java/java-properties-file-examples/
I am currently in the middle of some performance testing using contiperf, annotation based performance testing, with JUnit.
I am loading JUnit tests from a properties file and wanted to be able to also load annotations values from these properties file.
I have searched online and cannot find a way to dynamically create annotation values for Contiperf. If anyone knows how to do this, can they point me in the right direction?
Thank you in advance!
I would first check out this link and understand how contiperf works internally:
It is essentially a JUnit rule that creates its own threadpool based on the extracted annotation values, with each test invocation running on a single thread. It reads these annotation values from the FramworkMethod reference in the apply method.
A hack to go around this is to understand this link
Then you change the contiperf rule itself by creating a constructor to the rule taking in your "property values", updating the annotation values of the "Framework method" before it is passed into the PerfTestStatement().
I hope this small workaround is what you were looking for!
So, I have an environment property that is supposed to reflect what environment my app is running in.
#Value("${environment}")
private String environmentName; //This will be set as sandbox, staging, production
I also have a feature flag (feature is called 'superFeature.enable') that should be set based on what environment the app has been deployed in.
//Config file
superFeature.enable.sandbox=true
superFeature.enable.staging=false
superFeature.enable.production=false
//#Service annotated class containing call to configuration
#Value("${superFeature.enable.{environment}:false}")
private boolean isSuperFeatureEnabled;
At the moment, when I run my app in my sandbox environment, isSuperFeatureEnabled is always false. Is my syntax correct for the above code snippet? Is there something I'm missing?
Shouldn't you have put
#Value("${superFeature.enable.{environmentName}:false}")
there?
This is just a guess, I'm afraid. It looked like an inconsistency there. But then, I don't know in which context and order these two statements above are executed, so I don't know where which variables are known.
I would suggest getting some more information first. Like, what happens if you replace the {environment} with the expected string for your environment, can you get the environment value in your code at that point. I don't know if it is even possible to have this kind of double indirection at all.
It should be the following(environment also enclosed within placeholder syntax starting with $) :
#Value("${superFeature.enable.${environment}:false}")