IntelliJ IDEA and Maven: creating a test resource in the same package - maven

I'm using IntelliJ IDEA and my project has a default Maven structure.
I often run into the scenario where I need to create a new class or resource in the same package, but in different folder (one of src/main/java, src/main/resources, src/test/java, src/test/directory). The case where I'm editing a class in src/main/java and I need to create a test in src/test/java is covered by the Create Test command.
What about the other scenarios?
Often I find myself writing a unit test and I'd like to create a test resource in the same package in test resources folder. Is there a quick way how to achieve that?

What you can do at least is to copy the path of your package, and then (in the test resources dir) say new directory, and paste the path there. You then need to delete the absolute prefix, but can keep the package definition. With deep package structures, this at least helps a bit.

To the best of my knowledge (via 10 years of use) there is not a built in way to do this. It is something I've recently been desiring for creating default Spring Test Context files. Your post has promoted me to open a Feature Request for auto-generating the spring text context. I'd recommend you either add a comment to that request, or open a separate feature request.

Related

How to read properties file in resources folder of buildSrc module?

I need to read properties file located inside resources folder of buildSrc special module to create kotlin object which will be accessible by other project modules.
I tried to put this properties file
in the root project folder(this case sometimes works sometimes not, so I look for more reliable case)
inside of buildSrc folder directly
and now trying by putting inside "conventional" resources folder inside buildSrc which even highlighted by ide as recognized resources folder
But during assembling of modules I get Exception file not found on the line load()
So 2 questions:
where properties file should be located
how to read it from kotlin inside buildSrc module.
Gradle has a somewhat complex class-loading hierarchy, and I don't know enough of it to be able to explain what is going on under the hood. However, I can give you some hints.
First of all, the methods getResource and getResourceAsStream is present in both a Class and a ClassLoader, and they behave differently.
On a Class, if you don't prefix it with a slash, it will look for resources relative to the package of the class. With a slash, it looks at the root of the hierarchy. As you don't know the package of the compiled script as done by Gradle, the correct way to reference the file is javaClass.getResourceAsStream("/file.properties") (notice the slash).
If you use the methods from a ClassLoader instead, a leading slash is meaningless. So here, Thread.currentThread().contextClassLoader.getResource("file.properties")) is correct.
The last thing to consider is when you can use the methods from the class and when you have to use a ClassLoader. From what I can tell, you can use the class method when in the same project (or plugin). So this should work from within buildSrc. But if you want to get the resource outside buildSrc, I believe you need to go through the context classloader.
After trying different variants I have found 100% stable and working variant - instead of reading a properties file, parsing it and validating input - just use kotlin objects as ready to use configuration! With this approach the problem of a current folder and accessibility of resources is gone which is what I needed.

Spring Boot Multi Module and Fat jar with Shared Features

Experts,
I need some expert advice on how to approach the below use case in spring boot.
I need to have a maven multi-module approach to my project.
I need to have a single jar as output of the final build process.
There are to be common modules for controllers, data access and other functionality
Other modules are to be created based on functionality domain for eg a module for Payroll, a module for Admin etc etc.
Each domain functional module will then have their own controllers extending the common controller, exception handler and so on.
Each module will also have its own set of thyme leaf pages.
The reason for following such an approach is we have development in phases and we will be rolling out based on functional modules.
Here are the issues that I can sense using this approach.
Where do I add the spring web dependency? If I add to the parent pom - it gets replicated across the children and there will be port conflict issues as each module loads. the same issue will also be there the moment I add it to two child modules.
How do I build the fat jar which has all the jars from all modules and works as the final deployment?
All the text that I read i can't see anything even close to what I am trying to achieve.
AD1. They will not unless you are trying to setup independent application context in each module. Of course you can do that(it might be complicated but I believe it's achievable), but for me it's an overkill. Personally I think it's better to have one application context and rely on scanning components that are present in classpath.
AD2. The structure in maven might be a little bit complicated and overwhelming at first glance but it makes sense. Here's how I see it:
Create a parent module that will aggregate each module in project and will declare library/plugin dependencies for submodules.
Create 1-N shared submodules that will be used in other modules. With come common logic, utils, etc.
Create 1-N submodules that will be handling your business logic
Create an application submodule that creates application context and loads configuration and components from classpath
Create a submodule that will be responsible for packaging process, either to war, jar, uber-jar or whatever else you desire. Maven jar plugin should do that for you. For executable uber-jar, you have dedicated tool from spring.
Now you can choose three ways(these ways I know) of loading your modules.
1. Include some modules in maven build based on the build configuration via maven profiles and let spring IoC container load all the components he finds in the classpath
2. Include all of the modules in maven build and load them depending on spring active profiles - you can think about it as of feature flag. You annotate your components or configuration class with #Profile("XYZ") telling spring IoC container whether to instantiate component or not. You will need (most flexible solution) to provide a property file which tells spring which profiles are active and thus which modules should be loaded
3. Mix of these two above.
Solution 1 pros:
build is faster (modules that are not included will be skipped during build)
final build file is light (modules that are not included are... not included ;))
nobody can run module that is not present
Solution 1 contras:
project descriptor in maven may explode as you might have many different profiles
Solution 2 pros:
it's fairly easy and fun to maintain modules from code
less mess in project descriptor
Solution 2 contras:
somebody can run module that is not intended to be run as it's present in classpath, but just excluded during runtime via spring active profiles
final build file might be overweight - unused code is still present in code
build might take longer - unused code will be compiled
Summary:
It's not easy to build well structured project from scratch. It's much more easier to create a monolith and then split it into modules. It's because if you already created a project, you've probably already identified all the domains and relations between them.
Over past 8 years of using maven, I honestly and strongly recommend using gradle as it's far more flexible than maven. Maven is really great tool, but when it comes to weird customization it often fails as it's build capabilities rely on plugins. You can't write a piece of code on the fly to perform some custom build behaviour while buidling your project, you must have a dedicated plugin for doing that. If such plugin exists it's fine, if it's not you will probably end up writing your own and handling its shipment, so anyone in your company can easily perform project build.
I hope it helps. Have fun ;)

Dependency excluding only one class from maven surefire plugin

My question is really simple, thought I haven't found anything online related to it.
Is the maven-surefire-plugin able to have a dependency excluded but at class level and not at group-id:artifact-id level?
My problem:
I have a web project, related to a plain java project A. This A project contains hundred of classes that do a variety of things (connects to the database, sends web services, calculates stuff, manages the logs, context, sessions, etc...) and the dependency is quite strong. Since all unit testing on the web project will be hard to do without this A project I need to have it as a dependency even for the testing. But of course I cannot use some of the classes in there (mainly the DB connection and the session stuff). So I thought that instead of mocking them (because there are like a few dozens of them and I want to do different things with the functions (like writing to a file that it tried to connect or read the "session" from an xml file)) I can create a A-test project and include the classes I want from this new project and exclude the classes I don't need from the A project.
I know I can copy/paste all the project and then replace the classes I want, but if something changes in project A, I then have to maintain it in A-test (and I am very lazy and don't like to work twice). I thought that maybe I could have some kind of plugin in maven that will copy all the other classes (the one I am not... let say 'overriding'), every time. But it seems a waste of time if I just can tell the plugin which classes to use during the test step.
Thanks for your help!

spring configuration XML files location in multiple projects - what's the best practice?

We have multiple projects, and there are spring configuration XMLs in all of them. We're contemplating 2 options:
A) Loading the spring files from the classpath, by using import "classpath:a.xml". In this option our springjunit4classrunner and our main console application both happily find the files. However, when you need to change or inspect some XML, it's well hidden in some obscure jar.
B) Creating a "conf" folder, and by using some maven magic gathering all the XML files from all the projects there. This is good for the main application, but the unittests don't like this setting, as obviously we don't build the "conf" folder before running unittests, and they fail to find the dependent projects XMLS...
(This is a spring re-take on Is it bad practice to include properties/configuaration files within jars?)
In the past, I've gone with <import resource="classpath*:beans.xml"/> or similar, i.e. import every beans.xml file the classloader can find in the root of the classpath. In turn, those beans.xml files import their own specific config files as required.
It requires discipline, so that you don't get big spider webs of Spring configs, but if you keep it simple, then it makes integration very easy, so that you don't need to maintain complex lists of config file imports, and the build process stays simple also.
It's interesting that you mention that prior question, because I don't consider Spring beans files to be "configuration". Rather, they're part of the application - they cannot and should not be separated from the Java code, because they're intimately coupled with it.
If those beans files require genuine configuration, e.g. from a properties file, then yes, those probably should be kept separate.

Ibatis2 and test context

I'm having a stupid configuration issue with Ibatis in my Spring project. Please don't jump on me about how all this was setup, I'm just following the "in house project structure policy".
So here is the structure, we have the "src/main/resources/META-INF/" folder that contains all of our config files used by the application, and then there is a "src/test/resources/META-INF/" that contains only the config files that have different settings to run unit testing.
Well in our case that's only one file, the src/main/resources/META-INF/spring/application-config.xml became the src/test/resources/META-INF/spring/test-application-config.xml. I'm am not going to outline the small differences between the two, because that part works fine.
The test-application-config.xml imports the src/main/resources/META-INF/spring/data-access-config.xml file just fine, which in turns use the src/main/resources/META-INF/ibatis/sqlmap-config.xml successfully... After that is when it goes to Hell.
See up until now we're using Spring to find the next config files in the classpath, but when we hit sqlmap-config.xml we leave the spring framework for the ibatis framework I believe, which loads the resource files defined inside it relative to the classpath (that's taken from the doc, whatever that means).
Inside the sqlmap-config.xml are defined a few resource files we're using that live inside the src/main/resources/META-INF/ibatis/mapping folder.
They are referenced like this:
<sqlMapConfig><sqlMap resource="/META-INF/ibatis/mapping/MyObject.xml"/></sqlMapConfig>
That works fine when I run the app normally, but when I run my JUnit test cases I get an IO exception stating that it can't find the file /META-INF/ibatis/mapping/MyObject.xml.
I've tried to change the path in the sqlmap-config.xml to "mapping/MyObject.xml" but that didn't help. I've also tried to use the Spring classpath prefix "classpath:META-INF/ibatis/mapping/MyObject.xml", didn't work either.
Anyone would have any idea on how to set that Ibatis properly so it works for both the app and the junit?
Thanks.
To solve this problem, I removed all the the Ibatis files and folders from the src/test/resources/META-INF folder.
The sqlmap-config.xml in src/main/resources/META-INF/ibatis/mapping file now maps like this:
<sqlMapConfig><sqlMap resource="META-INF/ibatis/mapping/MyObject.xml"/></sqlMapConfig>
Please note that compared to my initial post the leading "/" is gone... I think that's what made the difference here.
Hopes this helps anyone running into similar issues.
Just to see whether what you are saying is actually the problem.. you might want to place your mappings (MyObject.xml) in the same folder as sqlmap-config.xml. I say this because I've had my fair share of spring + ibatis + unit testing problems. (see resolved question asked by me)
Also, you might be getting IO exception because the mappings file does not exist outside the container (when you run tests).
You should also post definition for bean created from SqlMapClientFactoryBean. This should have configLocation property that contains path to sqlMapConfig xml
I had the same problem and could not find a (quick) solution that explained what exactly could be going wrong. Hence my answer.
As Spring documentation for Ibatis says:
Remember that iBATIS loads resources from the class path, so be sure
to add the 'Account.xml' file to the class path.
In your case by adding META-INF to your webproject build path i.e. if you used Eclipse, set <classpathentry kind="src" path="META-INF"/> in your projects' .classpath (This will be visible under Navigator view in Eclipse)

Resources