How to make Spring Boot only scan and validate imported entities? - spring

I have separated my project in multiple modules using Maven. On of the modules is used as a 'common' module which shares entities and other code between modules. I have imported this module within the other modules. A problem arises when launching a module which uses the 'common' module. The module seems to scan for all entities in the common package and tries to validate the schema. This module does not have the SQL permission to access some tables, which results in a validation error.
Is there a way to disable this feature and only validate the schema based on the actually used entities in the code (based on imports)?

A somewhat vague explanation, I would like to see an immediate problem.
But the first thing that comes to mind: exclude auto jpa support. For your application class:
#SpringBootApplication(exclude = {JpaRepositoriesAutoConfiguration.class})
Possible, you can exclude also class DataSourceAutoConfiguration.

Related

Multimodule Spring boot application Flyway migration scripts

I have a multi-module Spring boot application (for simplicity it is just moduleA and moduleB). Both modules access the same DB. Also, I use flyway to initialise the tables and populates initial data to the DB.
When I use the naming schema of flyway I run into the problem that
V1_0__init.sql in moduleA clashes with V1_0__init.sql in moduleB.
I know that I could rename one of the files to V1_1__init.sql and it works. But the idea is that the modules can co-exist without knowing how the migration-scripts are named in the other module. Is this possible with flyway?
Names cannot conflict as Flyway is creating a historical log and two files of the same name with different definitions would create a non-idempotent execution of the log.
But let's get back to the real problem...why are you writing two modules with one database? This is more problematic than the Flyway naming abuse. I can envision ways around this problem but I don't want to mention any idea when the foundation is flawed. If one module needs data from the other you need to build interfaces between them (or pull out into a third) as you are violating the modular separation of concerns. Simply put: don't do this.

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 ;)

Spring boot application.properties maven multi-module projects

We are using spring boot in a multi-module project.
We have a Domain access module which has the common domain object classes, repositories, together with configuration for the datasource, JPA, Hibernate, etc. These are configured using a application.properties. We put all this configuration into the common module to save duplicating these common configurations in the higher level modules.
This all works fine when building the domain module, so the configurations are loaded correctly in the test units.
However the problems start when we try to use the domain module in the higher layer modules; they have their own application.properties which means Spring loads them and not the the Domain module application.properties, which this means the data source is not configured because only the higher module application.properties are loaded.
What we would like is both the domain module and higher level application properties to be loaded by Spring. But we can't see any easy way to do this.
I'm thinking this must be a common problem, and wonder if there any recommended solutions for this problem?
As we are using spring-boot the solution should ideally use annotations instead of applictionContext.xml.
Maybe you should only use application.properties in the top-level aggregator project?
You can always use #PropertySource in the child projects to configure them with a name that is specific to their use case.
Or you can use different names for each project and glue them together in the top-level project using spring.config.location (comma-separated).
I agree with #Dave Syer. The idea of splitting an application into multiple modules is that each of those is an independent unit, in this case a jar file. Theoretically you could split each of those jar files into their own source repositories, and then use them across multiple projects. Let's say you want to reuse these domain classes in both a web and batch application, if all the APPLICATION level configuration is stored within each of the individual modules, it severely reduces their reusability.
IMO only the aggregating module should contain all of the configuration necessary to run as an application, everything else is simply a dependency that can be remixed and reused as necessary.
Maybe another approach could be to define specific profiles for each module and use the application.properties file just to specify which profiles are active
using the spring.profiles.include property.
domain-module
- application.properties
- application-domain.properties
app-module
- application.properties
- application-app.properties
and into the application.properties file of app-module
spring.profiles.include=domain,app
Another thing you can do (besides only using application.properties at the top-level as Dave Syer mentions) is to name the properties file of the domain module something like domainConfig.properties.
That way you avoid the name clash with application.properties.
domainConfig.properties would contain all the data needed for the domain module to be able to tested on it's own. The integration with the rest of the code can easily be done either using multiple #PropertySource (one for domainConfig.properties and one for application.properties) or configuring a PropertySourcesPlaceholderConfigurer bean in your Java Config (check out this tutorial) that refers to all the needed property files
in spring-boot since 2.4 support spring.config.import
e.g
application.name=myapp
spring.config.import=developer.properties
# import from other module
spring.config.import=classpath:application-common.properties
or with spring.config.activate.on-profile
spring.config.activate.on-profile=prod
spring.config.import=prod.properties
ref: https://spring.io/blog/2020/08/14/config-file-processing-in-spring-boot-2-4

How to generate JPA metamodel to another module

In my 3 layer maven application (enterprise application archetype with an extra module for domain-related classes) I'd like to keep the domain module as clean as possible. My persistence.xml, for example, is in the ejb module. Following that train of thought, I'd like to generate the JPA static metamodel classes also on the EJB module, even though the entities are not there, but I can't make it work.
Is it possible to do that kind of setup? I'm using eclipselink, btw.

Grails domain class creation from database

I would like to create grails domain classes from an existing database, normally i was creating database from domain classes now i need to create it from an existing database schema. Please help me if there is any command available for that.
I'm on the same problem and I've found this Grails plugin. It works perfectly: it inspects the existent database and creates domain classes, all ready to go. Just follow the steps showed in the example and you're done.
There is a tool called GRAG: http://grag.sourceforge.net
Perhaps this might help.
add plugin (runtime ':db-reverse-engineer:3.0.0') in buildconfig.groovy
Change Hibernate version from hibernate4:4.3.6.1 to hibernate:3.6.10.18
Define package config in config.groovy to generate domain class grails.plugin.reveng.packageName="com.app.promotion"
List the tables, you want to generate domain classes in config.groovy grails.plugin.reveng.includeTables=["promotion","event","promotionexecutionstrategy"]
Define the shcema config in config.groovy grails.plugin.reveng.defaultSchema=”t0006”
Then execute the command “grails -Dgrails.env=development db-reverse-engineer”. Here development is the environment in the datasource.
After complete these steps we can see the domain classes in the package as we defined list items.

Resources