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);
}
Related
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?
I've created small util to wrap MavenCli, which generates a new Maven project, using the quickstart archetype.
When executing the Util as a unit test, it is working quite well (just generating an empty Maven project).
Now I want to integrate this small wrapper into a Maven plugin. But when I execute the mojo (within a third Maven project), the invocation of MavenCli fails with exception:
[ERROR] Error executing Maven.
[ERROR] java.util.NoSuchElementException
role: org.apache.maven.eventspy.internal.EventSpyDispatcher
roleHint:
[ERROR] Caused by: null
The util looks like:
public void createProject() {
final MavenCli cli = new MavenCli();
System.setProperty("maven.multiModuleProjectDirectory", "/usr/share/maven");
cli.doMain(new String[] { "archetype:generate", "-DgroupId=com.my.company",
"-DartifactId=hello-world", "-DarchetypeArtifactId=maven-archetype-quickstart",
"-DinteractiveMode=false" }, "/tmp", System.out, System.out);
}
relevant dependency of the util:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>3.3.9</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.3.9</version>
</dependency>
The mojo code looks like:
#Mojo(name = "custommojo", requiresProject = false)
public class CustomMojo extends AbstractMojo {
#Override
public void execute() throws MojoExecutionException, MojoFailureException {
Util.createProject();
}
}
The POM of the mojo just includes dependencies to relevant Maven artifacts (plugin-api, plugin-annotation, etc.) and the util.
The third project I mentioned, is an empty "maven-quickstart" project which have dependency to the mojo-project and a configuration for the mojo to execute in compile phase.
I have no idea why it works in context of unit test, but not in context of a mojo.
Can anybody help?
This is a class loading issue.
MavenCli will try to load classes from the context classloader of the current thread. Inside of a Maven plugin, there is a special, restricted, classloader, which has access to:
its own classes;
the classes used in its dependencies block;
exported classes as part of a possible build extension of the project;
exported classes from the Maven core and core extensions;
and has the bootstrap classloader as parent.
However, the specific class org.apache.maven.eventspy.internal.EventSpyDispatcher is part of Maven core, but it is not part of the exported APIs (the package org.apache.maven.eventspy is not listed as an exportedPackage). So the plugin cannot load that class. This is also why it works in your tests: you're not inside of a plugin, so the classloader is different and has access to that class.
You won't even be able to get away with adding explictly a dependency on maven-core for the plugin: it will be disgarded since it is supposedly already provided.
There are 2 solutions here:
Don't use the Maven Embedder API from within a plugin, but the Invoker API. The difference between the two is that the Invoker API will launch Maven in a clean environment, completely distinct with regard to the current one. Since it starts everything anew, you won't have any classloading issue.
Use the mojo-executor library, that provides an easy way to invoke other Mojos from within a Maven plugin. You could use it here to invoke the archetype:generate Mojo.
This works for me inside a custom maven plugin (using Maven 3.5.0):
ClassRealm classRealm = (ClassRealm) Thread.currentThread().getContextClassLoader();
MavenCli cli = new MavenCli(classRealm.getWorld());
cli.doMain( ... );
The plexus Launcher sets the context class loader to its ClassRealm, which has access to the "global" ClassWorld.
Not sure how stable that solution is, but so far looking good.
Used imports:
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.apache.maven.cli.MavenCli;
#Alexander:
You answer put me in the right direction, I was getting the mentioned error when trying to run to doMain maven commands subsequently (one command would succeed).
However your code gives me a ClassCast exception :
Exception in thread "main" java.lang.ClassCastException: sun.misc.Launcher$AppClassLoader cannot be cast to org.codehaus.plexus.classworlds.realm.ClassRealm
at com.misys.tools.integration.codegen.cli.cmd.InstallApi.mavenInstallMchApi(InstallApi.java:58)
at com.misys.tools.integration.codegen.cli.cmd.InstallApi.run(InstallApi.java:50)
at com.misys.tools.integration.codegen.cli.OpenApiGen.main(OpenApiGen.java:26)
I managed to rewrite the code to:
MavenCli cli = new MavenCli(new ClassWorld("maven",Thread.currentThread().getContextClassLoader()));
And then 2 subsequent doMain invocations of embedded maven succeed!
I have projects A and B that both have common project as a compile dependency defined in their build.gradle files like this:
dependencies {
compile project(":common")
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-cache')
compile("net.oauth.core:oauth:20090617")
compile("net.oauth.core:oauth-httpclient4:20090617")
compile('org.apache.httpcomponents:httpclient')
compile("com.atlassian.jira:jira-rest-java-client:2.0.0-m2")
compile("com.google.guava:guava:18.0")
compile('org.flywaydb:flyway-core')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
This common project has application.yml file with all kind of common information such as database connection properties, hibernate setup, etc. So I do not want to duplicate these files all over the other projects such as A and B.
In project A the main spring boot file looks like this:
#SpringBootApplication(scanBasePackageClasses = {CommonApp.class,
A.class})
public class A {
public static void main(String[] args) {
SpringApplication.run(A.class, args);
}
}
where CommonApp is a main class in the commmon project. This common main file is the following:
#SpringBootApplication
public class CommonApp {
public static void main(String[] args) {
SpringApplication.run(CommonApp.class, args);
}
}
Projects A and B compile just fine, but all yml files that are in the classpath of the common project are not visible from A and B, so I have not choice but to duplicate them manually in A and B
What is the better approach? Can spring boot common projects share resources with other projects?
Notice that ideally solution should not be gradle dependant as I would like to run unit and integration tests from Intellij IDEA which does not use gradle for running tests.
My app structure is
app
|-A
|-build.gradle
|-web
|-B
|-build.gradle
|-common
|-src/main/resources
|-application.yml
|-database.yml
|-web.yml
|-settings.gradle
|-build.gradle
A, B and common are all spring boot apps (common is a boot app too, but it's only used as a dependency for A, B).
If you want a non-gradle solution, you could always add a DAO-esque file to access the required values in the common project then jar your common project and add it as a dependency to projects A and B.
Edit: I apologize, I did not explain very well. When I say "DAO-esque file", what I mean to say is a file of getter (and setters if needed) that access the properties file. For example, have a getter file that is a singleton. On creation, create a static reference to the property file. When Project A (or B) needs a property, it can call to this file to get the property.
As for a gradle solution, it looks like your above is fairly close with your
compile project(":common")
code. Do you have a settings.gradle file that has the line
includeFlat "common"
and a reference to the common project in the same directory as Project A and B? For example
Project A
(...Project A's files...)
Project B
(...Project B's files...)
Common
(...Common's files...)
How I can add my source code ( java code ) to project SoapUI running by maven? I wrote own assertion class and check response in this class. First i made dir ext and put there .jar file. Now I want do the same, but with source code.
By adding a jar in the \ext folder you made the compiled class available to SoapUI test runner.
Instead of that you could include your code as a maven module in your project and add it as dependency. Your Java code should be a maven project for this to work.
A common approach is to create a "modules" directory in your project's root and add your java code in a subdirectory there, let's call it "assertion_module":
<root>
| - soapui-project.xml
| - pom.xml
| - modules
| - assertion_module
| - src
| - pom.xml
The pom.xml in the folder should have the necessary properties set, like below (sample values):
<groupId>assertion_module</groupId>
<artifactId>assertion_module</artifactId>
<name>assertion_module</name>
<version>0.1</version>
In you master pom.xml, i.e. the one that you use to run the SoapUI tests declare your assertion module, adding the following:
<modules>
<module>modules/assertion_module</module>
</modules>
In the soapui plugin section of this pom add the necessary dependency section:
<plugin>
<groupId>com.smartbear.soapui</groupId>
<artifactId>soapui-maven-plugin</artifactId>
<version>5.1.2</version>
<dependencies>
<dependency>
<groupId>assertion_module</groupId>
<artifactId>assertion_module</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
...
</plugin>
Now when you run your tests, the assertion_module will be compiled and be available to SoapUI test runner.
With this you no longer need to add the compiled jar in the \ext folder, although you still need to have it in the <SoapUI_installtion_directory>\bin\ext.
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.