How to architect my project by maven - java

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.

Related

Java how to use methods from another module in Intellij

I have added two projects as modules in empty intellij project.
Then I added in pom of module B following dependency to first project(module A):
<dependency>
<groupId>Tests</groupId>
<artifactId>Group</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
This allows me to import classes from module A into module B.
But I can't see any method from that module (it looks like classes are empty or they have only private fields/methods).
What am I missing? What should I do to see all public methods/fields from A module?
Thanks
Kamil
If you are adding one of them as a dependency, you can avoid to join them as modules. For local purposes, you can build(mvn clean package) one of them and add that as a dependency to another one. You can check relevant .class file to see the access levels of the class members.
For multi-module projects, please, see: https://www.jetbrains.com/help/idea/creating-and-managing-modules.html

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

Spring Maven project structure pom.xml

I'd like to get help in setting up a multi-module Maven project using Spring Boot.
Correct me if I'm wrong but I've read that Spring-Boot reads the start main Application (Annotated with #SpringBootApplication and ran with SpringApplication.run) and finds the necessary classes through reflection. Which means that it first accesses the start class and then proceeds to find the controllers, models, repositories. If so, how do I set up the dependency in the pom.xml of each module if I had a project structure like this:
app
--src
--pom.xml
core
--pom.xml
--models
----/pom.xml
--controllers
----/pom.xml
--repositories
----/pom.xml
pom.xml
Please have a look complete guide how to create multi module project in spring boot.
https://spring.io/guides/gs/multi-module/
Spring boot will component scan from the package of the class annotated with #SpringBootApplication. Component scannign means that it is looking through the classes under that package recursively, analyzing annotations, and wiring up anything it recognizes. This can include controllers, simple variables with #Value annotations, members with #Autowired, and a host of other things.
You can actually jump into the source for the #SpringBootApplication annotation and see that it expands to numerous other annotations, #ComponentScan being one of them.
If all of your modules are in a sub-hierarchy package wise from there, then they will be scanned properly anyway. Often though, sub-modules will be in a slightly different package hierarchy. In this case, you can explicitly specify #ComponentScan() in your code and inside the () you can list the base packages to component scan from.
Whether or not its a sub-module doesn't matter much at this point; its just like scanning classes in any other library you're including.
General Advice
Also, just FYI - Multi module projects can get a little hard to manage (speaking from numerous separate experiences). They can be very good if used properly though. If you're a beginner to Maven though, it may be wiser to keep separte, well-defined projects with a proper release cycle and just import them as normal dependencies.
So, I'm not for or against them, but just make sure you understand them well going in :).
I have a GitHub project where I configured a multimodule maven project:
https://github.com/cristianprofile/spring-boot-mvc-complete-example
This is Example project maven module structure:
Spring mvc rest maven module ---> service maven module ---> repository maven module
The main module should be configured like this (Spring mvc rest layer):
#SpringBootConfiguration
#EnableAutoConfiguration
//spring mvc module auto scan only its package
#ComponentScan(basePackageClasses = HelloWorldController.class)
//It needs Service bean so it will import ConfigurationService.class from
// Service maven module
#Import({ConfigurationService.class})
Complete class:
https://github.com/cristianprofile/spring-boot-mvc-complete-example/blob/develop/spring-boot-mvc-rest/src/main/java/com/mylab/cromero/controller/Application.java
It will only scan its package :
HelloWorldController.class --> com.mylab.cromero.controller;
This Rest layer use a service maven module so it is necessary to add dependency:
<dependency>
<groupId>com.mylab.cromero.core</groupId>
<artifactId>mylab-core-service-impl</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
Complete pom file:
https://github.com/cristianprofile/spring-boot-mvc-complete-example/blob/develop/spring-boot-mvc-rest/pom.xml#L16
ConfigurationService.class from service maven module autoscan its packages and it will import ConfigurationRepository.class (Repository maven module)
#Configuration
//It needs repository's bean so it will import ConfigurationRepository.class from
// Repository maven module
#Import(ConfigurationRepository.class)
//service layer module auto scan only its package
#ComponentScan(basePackageClasses = ConfigurationService.class)
public class ConfigurationService {
}
Complete Service maven module code:
https://github.com/cristianprofile/spring-boot-mvc-complete-example/blob/develop/mylab-core/mylab-core-service-impl/src/main/java/com/mylab/cromero/service/ConfigurationService.java#L12
Service maven module layer has a dependency with maven repository module:
https://github.com/cristianprofile/spring-boot-mvc-complete-example/blob/develop/mylab-core/mylab-core-service-impl/pom.xml#L38
Repository module will auto configure jpa and domain classed:
#Configuration
#EnableJpaRepositories(basePackages = "com.mylab.cromero.repository")
#EntityScan(basePackageClasses=Base.class)
#ComponentScan(basePackageClasses = BaseRepository.class)
public class ConfigurationRepository {
}

Reuse a Spring-boot submodule in another non Spring project

I'm working on a multi module spring-boot project to build a REST API. Here is my project structure:
Parent project (packaging is pom)
core module (#SpringBootApplication + handle path like / or /status)
restControllerA module (Handle path like /routeA/*)
restControllerB module (Handle path like /routeB/*)
Everything is working in this project :)
In another non Spring project I would like to reuse a service of restControllerB. This service return the result of the request body validation.
First I try to add the restControllerB.jar as a dependency to this new project... But this jar does not contain its depedencies (who are in the fatJAR "core.jar"). When I run the project, I get a lot of ClassNotFoundException.
How can I manage to reuse this service as a dependency ? I thought to create a validator module which implements the validatorService interface, but I'm not sure if it is the best solution.
After few hours googling, It seems that creating an external librairy is the right choice. I create an external module and add it as a dependecy to restControllerB.

Error inheriting a module in a mavenized GWT project

After adding this dependency in my pom.xml:
<dependency>
<groupId>com.eaio.uuid</groupId>
<artifactId>uuid</artifactId>
<version>3.2</version>
</dependency>
I get an error by jetty on the module load event:
no source code available for com.eaio.uuid; did you forget to inherit the module? unable to find com.client.myproject..`
What am I missing?
If you're using any of the classes in that artifact in your GWT compiled code, then the source code needs to be available, either packaged in the jar or as a source jar (remember that's another dependency).
You'll have to look for a .gwt.xml file in the jar, as this will be the name you need to inherit in your own GWT descriptor, eg. if the file is called com/eaio/UUID.gwt.xml you should
...
<inherits name="com.eaio.UUID" />
...
If one isn't available, just create your own with a simple <source path="..." /> and stick in the right package in your own project (still provided the source is actually available!)
Cheers,

Categories