Shared application.yml configuration - java

Let's say I have multiple projects:
- - project1
- - project2
...
- pom.xml
With parent pom being defined as:
<packaging>pom</packaging>
<modules>
<module>project1</module>
<module>project2</module>
...
</modules>
I have the same configuration for actuator in all of the application.ymls of the these projects. Is there any way to somehow take out this common configuration maybe in a new project and then use it as dependency or something like that, so it will be in the one place and not replicated in all of the projects?
I tried creating a new project, placed common configuration in application.yml in the resources and then added this new project as dependency to the parent pom, but it seems like it didn't work out because /actuator/health is showing less info (only status: up) than it was showing when this configuration was in the every project's application.yml file (show-details is activated, actuator dependency is in the pom file), so I assume it doesn't work that way, so how do I do that?

Related

How to share protobuf files between maven modules?

I have two services A and B which placed in monorepo in different maven modules, also they have Aggregate pom.xml which contains the next modules:
<modules>
<module>A</module>
<module>B</module>
</modules>
Both services are talking through gRPC and have common protocol which described in the proto files.
The grpc-java manual says, that I must put my proto files into src/main/resourses/proto folder.
It means I have to copy the same proto files bewteen two services:
A/src/main/resourses/proto/somefile.proto
B/src/main/resourses/proto/somefile.proto
Which is code duplication actually.
The main question - How can I share and compile proto files between two maven modules in monorepo?
I have done the next:
Created the separate library which contains only proto files. Let's call it C.
Added C dependency to A and B modules.
Aggregated pom.xml looks like:
<modules>
<module>C</module>
<module>A</module>
<module>B</module>
</modules>
The approach seems quite havy for that case and I don't want to have a separate maven module for that.
Moreover, I will definetley face with a problem, if I use different language for B service (something other than java and maven).
Is there a known solution for this problem? Can I share protofiles without separate library/module? Any examples appreciated.
I've been wrong with
The grpc-java manual says, that I must put my proto files into
src/main/resourses/proto folder.
We can set protoSourceRoot configuration for grpc-java plugin. We can specify any required proto source folder as follows:
<protoSourceRoot>${basedir}/../proto</protoSourceRoot>
It means no need in separate maven module and library.

Overriden application.yml in multi-module Spring Boot app

There is a Spring Boot 2 app with such a structure:
parent-module
module-1
src
main
java
resources
- application.yml
module-2
src
main
java
resources
- application.yml
Also, module-1 depends on module-2, specified in pom.xml dependencies section.
The problem is that when I specify some properties in module-2's application.yml - they are not visible in main module-1's components (via #Value annotation).
As was answered here seems like module-1's application.yml overrides module-2's application.yml. There is a workaround - if I use name application.yaml in module-2 everything works fine, but I'm going to add more modules and, finally, it's dirty hack.
What I'm doing wrong? Should such an hierarchy of property files specified somehow?
I will be happy to provide more details if it's needed.
Thank you!
Spring Boot is a runtime framework. I understand that your modules are not spring-boot applications by themselves (you can't make a dependency on a spring boot application packaged with spring boot maven plugin, because it produces an artifact that is not really a JAR from the Java's standpoint although it does have *.jar extension).
If so, they're probably regular jars. So you should have a "special" module that assembles the application. This special module lists both 'module1' and 'module2' in <dependency> section and should contain a definition of spring-boot-maven-plugin in its build section (assuming you're using maven). But if so you shouldn't really have more than one application.yml - it will be misleading. Instead, put the application.yml to the src/main/resources of that "special" module.
If you really have to for whatever reason work with multiple application.yaml files, make sure you've read this thread
I know, this is already a well-aged post.
I just came accross the same issue and the best solution I found was to import the module-specific configurations with the spring.config.import directive as described here.
In this case you still have your module specific configuration in property or yaml files within that specific module and do not have too much unwanted dependencies in your project setup.
application.yml is, as the name indicates, an application-level file, not a module-level file.
It is the build script that assembles the final application, e.g. the .war file, that needs to include a application.yml file, if any.
If modules need properties, and cannot rely on the defaults, e.g. using the : syntax in #Value("${prop.name:default}"), they need to provide a module-level property file using #PropertySource("classpath:/path/to/module-2.properties").
Note: By default, #PropertySource doesn't load YAML files (see official documentation), but Spring Boot can be enhanced to support it. See #PropertySource with YAML Files in Spring Boot | Bealdung.
Alternative: Have the application-level build script (the one building the .war file) merge multiple module-level build scripts into a unified application.yml file.

How to start two springboot projects at the same time

My project includes a view service and an interface service. The project directory looks like this:
Myproject/
springboot1/
springboot2/
Both springboot1 and springboot2 can be run separately.The way I start them now is to open both terminals and execute the following commands:
springboot1
cd Myproject/springboot1/
mvn spring-boot:run
springboot2
cd Myproject/springboot2/
mvn spring-boot:run
Is there any way to start two projects at the same time?
For example, add a global pom.xml file to the Myproject directory and execute mvn spring-boot:run directly in the Myproject directory.
Yes, as you mentioned need something like global pom xml way, than that you can be achieved by combing two projects as modules to your packing app(Myproject). Let me give you some idea :
Create a new springBoot application with global pom file and move all common (1 & 2 project) jar or dependencies to this global pom file. Also, as each application as main application remove that as its no longer required as separate entity but also ensure if you have any custom code in their respective main file than move that code to main file of packaging project.
Build project 1 and 2 as jar packages and add them into packaging project as dependencies.
Project springboot1 internal pom will look like :
...
<groupId>org.springboot1.module</groupId>
<artifactId>springboot1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
...
Project springboot2 internal pom will look like :
...
<groupId>org.springboot2.module</groupId>
<artifactId>springboot2</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
...
Packaging project pom will look like :
...
<dependency>
<groupId>org.springboot1.module</groupId>
<artifactId>springboot1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springboot2.module</groupId>
<artifactId>springboot2</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
...
In your packing main file add new locations of the #Components, that are coming from the dependencies
#SpringBootApplication
#ComponentScan(basePackages =
{"org.springboot1.module.one.*","org.springboot2.module.two.*"})
public class Myproject {
public static void main( String[] args )
{
SpringApplication.run(Myproject.class, args);
}
}
Run the main class of the packaging application and it will start with the two dependent projects.
Hope above steps will work with some more changes depending your project structure. Also, for some more clarity you can also refer Maven Project_Aggregation
Try this
mvn springboot1/spring-boot:run | mvn springboot2/spring-boot:run
You can create a wrapper Spring Boot application that launches them as separate servlets. They should be in sibling application contexts and share the wrapper application as a parent context. It would look roughly like this:
public static void main(String[] args) {
new SpringApplicationBuilder().parent(WrapperApplication.class).web(WebApplicationType.NONE)
.child(Application1.class).web(WebApplicationType.SERVLET)
.sibling(Application2.class).web(WebApplicationType.SERVLET)
.run(args);
}

Third party API can't see class in multi module Maven project

I have a multi module maven project, and in the dao module, I added the JSON-IO dependency. When I try to deserialize my object, it gives me:
Exception in thread "main" com.cedarsoftware.util.io.JsonIoException: Class listed in #type [hu.kleatech.projekt.model.Employee] is not found
The class name is correct, the Employee is public, and the dao has the module as dependency. What could have gone wrong?
Edit: Since this is an old question and have been answered long ago, I'm deleting the github repository that I made specifically for this question. The solution to the problem is in the accepted answer, the exact code is not relevant.
Please try adding an empty constructor to Employee class.
Edit: Actually, while adding an empty constructor solves the problem, it is not necessarily required. Json-IO "will make a valiant effort to instantiate passed in Class, including calling all of its constructors until successful. The order they tried are public with the fewest arguments first to private with the most arguments."
(copied from MetaUtils.java javadoc)
Also, when calling a multi-argument constructor, the library fills the arguments with nulls and defaults for primitives. Then any exceptions thrown during the constructor call is ignored. In your case, a NullPointerException was thrown, because the constructor is not null-safe. So either modify the constructor so that it can handle nulls, or add an empty constructor.
Maven dependency configuration is hierarchical from <parent> element not from <modules> element.
It means that in the project's pom.xml file where you have dependency on "JSON-IO dependency" you do not have dependency on your dao project or where that class is.
<modules> stands only to define what projects to build. Order of modules definition does not matter, since Maven detects order by required dependencies
So, you can define dependency in <parent> pom.xml either in
<dependencies> element. then all children will have it.
or in <dependencyManagement> - then children who need it can include it in their <dependencies> without common configurations like version, scope etc...
look at quite similar answer here:
How to minimize maven pom.xml
As per your project and modules Pom your main Pom should have modules in following order ....
<modules>
<module>core</module>
<module>controller</module>
<module>service</module>
<module>dao</module>
</modules>
service depends on core so core should be build before service
dao depends on service and core both so dao should be after core and service.
Employee class is available in core and it should be available in core jar.
You should add depencyManagent in main Pom and then add all the module as dependencies in dependencyManagement so whoever adds your main Pom as dependency will be able to access all your jars.
Once you change order build your project again and then update your maven project.
If this code is being used in another project then make sure that you have uploaded jars to repository (mvn deploy) so whoever uses it can download it when they are building their project.
One way to verify whether this jar is downloaded in the main project where it is used or not is check in project explorer there would be a Maven Dependencies section where you can see all dependency jars and check if core is present or not.
I am not sure what controller module is doing in main Pom as I couldn’t find a module by that name in your project so you should either remove it or add a module (folder) for it.

How to architect my project by maven

Thanks all of you to read my question!
Months ago , I had build nexus to manage my maven repository and I build an empty web project.
My goal is to create an architecture for my company. When a new project comes, I can only configure my pom.xml to add my frame dependency. Well, my project's frame is springMVC+velocity+mybatis
I separated my Java source code into four models, groupId, artifectId has been named like below:
groupId is __com.myproject.framework__
parent pom's artifactId is com.myproject.framework-root.
sub models's artifactId are framework-core, framework-utils and so on.
This architecture can be used when I create an empty Java web project. I only configured the pom.xml with :
<dependency>
<groupId>com.myproject.framework</groupId>
<artifactId>framework-core</artifactId>
<version>1.0</version>
</dependency>
It's very good, I can reference this jar package very well!
But framework-core's Java code uses the Spring framework. Source code of myproject-framework-core jar package, is as below:
Action:
package com.hc360.buyer.action
#Controller
public class ActiveRecordAction extends BaseAction {
// ...
}
Service:
package com.hc360.buyer.service
#Service
public class BuyerInfoMainServiceImpl{
...
}
This means that I must configure path into my spring config of the new empty project, such as:
<context:component-scan base-package="com.hc360.buyer.service" />
<context:component-scan base-package="com.hc360.buyer.action" />
My question is how can I design my framework models or jar package?
Goal is that when I create a new Java web project and reference my myproject-framework-core jar package, I needn't have to configure my spring config like below:
<context:component-scan base-package="com.hc360.buyer.action" />
In my mind, the best way is I only need to reference my myproject-framework-core jar package in this new project's pom.xml, and then it works well.

Categories