I have a Maven project with several submodules inside of it. They are packaged up so that I can reuse the code across several microservices. I can generate my Java classes in the parent project as I would like them to be, however, when I attempt to generate a class in a subdirectory my a package declaration that looks like:
package ${target.javaPackageFromFolder(${SRC})};
In a template will resolve to:
package error.folder.not.started.with.the.given.src.folder.activities;
In the .java class. This is understandable since my $SRC is at src/main/java and not service-core/src/main/java.
All of my modules are organized the same way, with $SRC at src/main/java, if I could just inform Telosys about the existence of these modules, I would be able to generate the code in the right place without needing to move it after generation.
I would just init Telosys in the service-core module, but I would also like to support generating DTOs in dto-public and controllers/tests in my api-public. Is there any way to support this in Telosys?
Things I've tried:
Adding a parent .vm file that calls $generator.generate with a different directory. This configuration produces the above result.
Changing the generated directory in the templates.cfg to include service-core/${SRC}/${ROOT_PKG}/model/. This configuration also produces the above result.
To generate a multi-modules Maven project I recommend the following approach :
At Telosys project level define a specific global variable for each module in the file "telosys.cfg" and define the "root package" variable
Example:
# Root package (will be used as "root folder" in targets)
ROOT_PKG = org.demo.orders
# Maven project / parent :
ProjectVariable.MODULE_PARENT = orders-parent
# Maven project / modules :
ProjectVariable.MODULE_MICROSERVICE = orders-microservice
ProjectVariable.MODULE_DOMAIN = orders-domain
ProjectVariable.MODULE_INFRA_MYBATIS = orders-infra-mybatis
ProjectVariable.MODULE_INFRA_ELASTIC = orders-infra-elastic
ProjectVariable.MODULE_INFRA_RABBITMQ = orders-infra-rabbitmq
You can keep the usual values for the standard variables:
SRC = src/main/java
RES = src/main/resources
WEB = src/main/webapp
TEST_SRC = src/test/java
TEST_RES = src/test/resources
DOC = doc
TMP = tmp
At Telosys templates level (in each bundle) use the global variables to define the target folder in the file "templates.cfg"
You can combine $SRC, $MODULE_XXX and $ROOT_PKG to build the destination directory
Example (project modules initialization):
# "microservice" module
; pom.xml ; ${MODULE_MICROSERVICE} ; microservice/microservice-pom_xml.vm; 1
; README.md ; ${MODULE_MICROSERVICE} ; microservice/README_md.vm ; 1
; SpringBootApp.java ; ${MODULE_MICROSERVICE}/${SRC}/${ROOT_PKG} ; microservice/SpringBootApp_java.vm ; 1
; application.properties ; ${MODULE_MICROSERVICE}/${RES} ; microservice/application_properties.vm ; 1
; application-dev.properties ; ${MODULE_MICROSERVICE}/${RES} ; microservice/application-dev_properties.vm; 1
# Other modules initialization
; pom.xml ; ${MODULE_DOMAIN} ; modules/domain-pom_xml.vm ; 1
; pom.xml ; ${MODULE_INFRA_MYBATIS} ; modules/infra-mybatis-pom_xml.vm ; 1
; pom.xml ; ${MODULE_INFRA_ELASTIC} ; modules/infra-elastic-pom_xml.vm ; 1
; pom.xml ; ${MODULE_INFRA_RABBITMQ}; modules/infra-rabbitmq-pom_xml.vm ; 1
; pom.xml ; ${MODULE_REST_APP} ; modules/rest-app-pom_xml.vm ; 1
; pom.xml ; ${MODULE_REST_DTO} ; modules/rest-dto-pom_xml.vm ; 1
Other example (in the bundle for "domain" module):
pom.xml file ; pom.xml ; ${MODULE_DOMAIN} ; domain-pom_xml.vm ; 1
readme file ; README.md ; ${MODULE_DOMAIN} ; domain-readme_md.vm ; 1
Entity ; Entity.java ; ${MODULE_DOMAIN}/${SRC}/${ROOT_PKG}/domain/common ; domain-common/Entity_java.vm ; 1
AggregRoot ; AggregateRoot.java ; ${MODULE_DOMAIN}/${SRC}/${ROOT_PKG}/domain/common ; domain-common/AggregateRoot_java.vm ; 1
AggregRootRepo; AggregateRootRepository.java ; ${MODULE_DOMAIN}/${SRC}/${ROOT_PKG}/domain/common ; domain-common/AggregateRootRepository_java.vm ; 1
With multiple source folders the Java package can be determined in 2 ways
in templates (.vm files):
using $target.javaPackageFromFolder() with the composite source folder,
example:
package ${target.javaPackageFromFolder("${MODULE_DOMAIN}/${SRC}")} ;
using the ${ROOT_PKG} variable and adding the specific part of the package,
example:
package ${ROOT_PKG}.my.sub.pkg ;
the ending part of the package name is not supposed to change, but if you want you can also use a global variable to define it. Example:
package ${ROOT_PKG}.${DOMAIN_PKG} ;
Seems like you may be looking for $target
$target.javaPackageFromFolder(String srcFolder)
My current solution involves a distribution.sh script that copies out of the src folder to the appropriate destinations. This works fairly well as the packages that I'm writing to are unique across my modules. But if two of my modules have the same module, I'll be out of luck.
#!/bin/bash
cp -rv src/main/java/my/company/model/* service-core/src/main/java/my/company/model
cp -rv src/main/java/my/company/dao/* service-core/src/main/java/my/company/dao
cp -rv src/main/java/my/company/service/* service-core/src/main/java/my/company/service
cp -rv src/main/java/my/company/dto/* dto-public/src/main/java/my/company/dto
cp -rv src/main/java/my/company/web/v6/* api-public/src/main/java/my/company/web/v6
cp -rv src/main/java/my/company/web/integration/v6/* common-test/src/main/java/my/company/web/integration
cp -rv src/test/java/my/company/web/integration/v6/* api-public/src/test/java/my/company/web/integration/v6
Related
I am not able to read test data from outside the src folder of project using java code. I am using bazel for testing java code.
The project hierarchy is as below:
Parent
Project1
Project2
Project3
Subproject1
Subproject2
data
Subfolder
Xyzzy.spi
Xyzzy.spl
BUILD.bazel
Src/main/java
Src/test/java
Com.test.sometest
Test1.java
Test2.java
BUILD.bazel
data/subfolder/BUILD.bazel:
exports_files(["Xyzzy.spi", "Xyzzy.spl"])
src/test/java/Com/test/sometest/BUILD.bazel:
load(
"//bazel:defs.bzl",
"java_library",
"java_test",
"java_binary",
)
java_test(
name = “subproject2”,
test_library = "subproject2_lib",
)
java_binary(
name = "example",
data = [
“//project3/subproject2/data/subfolder: Xyzzy.spi",
“//project3/subproject2/data/subfolder: Xyzzy.spl”,
],
runtime_deps = [":subproject2_lib"],
)
java_library(
name = "subproject2_lib",
testonly = True,
srcs = glob(
[
"*.java",
],
),
deps = [
"//:lombok",
“Path to point to build bazel of main java code”,
"#maven//:com_google_guava_guava",
"#maven//:commons_io_commons_io",
"#bazel_tools//tools/java/runfiles:runfiles",
"#maven//:junit_junit",
],
)
And java code to get path to file:
private static File CURRENT_INDEX_FILE=Paths.get("data/subfolder/Xyzzy.spi").toFile();
I am getting FileNotFoundException when running bazel test. Not sure where am doing it wrong. I tried google about this but no similar cases i found, mostly they have Maven Standard hierarchy but what should i change for this folder structure to work with.
Thanks
I have a multi-module Java(Spring) project, which build by Gradle 6.7.1. And I use in Jetbrain IDEA to develop. The file Structure like this:
root
|--orm
| +---hibernates
|
|--web
|--mvc
|--rest
And then, I have tried some codes in my module project like below, what I get all are root path (/home/user/IdeaProjects/root/), not module path (/home/user/IdeaProjects/root/web/mvc). How can I get module path (/home/user/IdeaProjects/root/web/mvc) ?
new File("").getAbsolutePath()
Assuming for instance that your mvc project is setup like this in setting.gradle, in the root folder :
include 'mvc'
project(':mvc').projectDir = new File('./web/mvc')
Then, to get the path /home/user/IdeaProjects/root/web/mvc, just try this :
println project(':mvc').projectDir
Will prints :
/home/user/IdeaProjects/root/web/mvc
based on the answer of #ToYonos. We can do that by this:
settings.gradle gets the project path of every module.
write a key value into the info.properties in every module.
Spring Project read this properties file.
Code
Because struct of my project is:
root
|--orm
| +---mybatis
| +---jpa
| +---...
|--web
+--mvc
+--rest
+--...
So, I should loop twice to get the module name. And I exclude project without build.gradle.
file("${rootDir}").eachDir {
it.eachDirMatch(~/.*/) {
if (it.list().contains("build.gradle")) {
def moduleName = "${it.parentFile.name}:${it.name}"
println " ${moduleName}"
include moduleName
}}}
And then, read and write info.properties.
import java.nio.file.Paths
// read
def project_dir = project(":${moduleName}").projectDir
def propFile = Paths.get("${project_dir}", "src", "main","resources","info.properties").toFile()
propFile.createNewFile()
Properties props = new Properties()
propFile.withInputStream {
props.load(it)
}
// write
props.setProperty("project.dir","$project_dir")
props.store propFile.newWriter(), null
I want to include Java source code from multiple directories (which are shared between projects) in a Qt for Android project. On http://imaginativethinking.ca/what-the-heck-how-do-i-share-java-code-between-qt-android-projects/ an approach is described which copies the Java source files:
# This line makes sure my custom manifest file and project specific java code is copied to the android-build folder
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
# This is a custom variable which holds the path to my common Java code
# I use the $$system_path() qMake function to make sure that my directory separators are correct for the platform I'm compiling on as you need to use the correct separator in the Make file (i.e. \ for Windows and / for Linux)
commonAndroidFilesPath = $$system_path( $$PWD/../CommonLib/android-sources/src )
# This is a custom variable which holds the path to the src folder in the output directory. That is where they need to go for the ANT script to compile them.
androidBuildOutputDir = $$system_path( $$OUT_PWD/../android-build/src )
# Here is the magic, this is the actual copy command I want to run.
# Make has a platform agnostic copy command macro you can use which substitutes the correct copy command for the platform you are on: $(COPY_DIR)
copyCommonJavaFiles.commands = $(COPY_DIR) $${commonAndroidFilesPath} $${androidBuildOutputDir}
# I tack it on to the 'first' target which exists by default just because I know this will happen before the ANT script gets run.
first.depends = $(first) copyCommonJavaFiles
export(first.depends)
export(copyCommonJavaFiles.commands)
QMAKE_EXTRA_TARGETS += first copyCommonJavaFiles
With later Qt versions the code has to be changed to this:
commonAndroidFilesPath = $$system_path($$PWD/android/src)
androidBuildOutputDir = $$system_path($$OUT_PWD/../android-build)
createCommonJavaFilesDir.commands = $(MKDIR) $${androidBuildOutputDir}
copyCommonJavaFiles.commands = $(COPY_DIR) $${commonAndroidFilesPath} $${androidBuildOutputDir}
first.depends = $(first) createCommonJavaFilesDir copyCommonJavaFiles
export(first.depends)
export(createCommonJavaFilesDir.commands)
export(copyCommonJavaFiles.commands)
QMAKE_EXTRA_TARGETS += first createCommonJavaFilesDir copyCommonJavaFiles
Is this the standard way to go, or is there some built-in functionality for including multiple Java source directories in Qt for Android projects?
Regards,
A much cleaner solution is this one:
CONFIG += file_copies
COPIES += commonJavaFilesCopy
commonJavaFilesCopy.files = $$files($$system_path($$PWD/android/src))
commonJavaFilesCopy.path = $$OUT_PWD/android-build
I'm creating a JVM within my C++ application for windows, and I'm unable to convince it to load multiple jars.
My C++ code:
MyClass::MyClass(std::string & classPath) {
classPath = "-cp "+classPath; // <-- Won't work with any path or single jar
//classPath = "-Djava.class.path="+classPath; <-- Only works with single jar
jvmOptions[0].optionString = (char *)classPath.c_str();
jvmOptions[1].optionString = "-Xms8m";
jvmOptions[2].optionString = "-Xmx24m";
jvmArgs.version = JNI_VERSION_1_6;
jvmArgs.options = jvmOptions;
jvmArgs.nOptions = 3;
jvmArgs.ignoreUnrecognized = JNI_TRUE;
int jvmInitResult = CreateJavaVM( &jvm, (void**)&environment, &jvmArgs);
if( jvmInitResult >= 0 ) {
jclass loadedClass = environment->FindClass( MyClassName.c_str() );
.....
If I pass a path via my classPath variable to a single JAR, such as "C:\path\myjar.jar", the jclass variable is located fine. However, my Java class requires additional JARs to function, so I need to pass more than one JAR to the jvmOptions. When I try to pass the second, or third JAR, in any of the following ways, the FindClass call now fails.
C:\path\myjar.jar <--------- FindClass SUCCESS; can't use due to missing jars
C:\path\myjar.jar;C:\path\secondjar.jar <-----FindClass FAIL
C:\path\myjar.jar:C:\path\secondjar.jar <-----FindClass FAIL
C:\path\* <-----FindClass FAIL
C:\path\*.jar <-----FindClass FAIL
"C:\path\myjar.jar;C:\path\secondjar.jar" <-----FindClass FAIL
"C:\path\myjar.jar:C:\path\secondjar.jar" <-----FindClass FAIL
I assume there is another option I'm not thinking of, but this is driving me nuts.
You should use -cp to set the class path. I suspect -Djava.class.path= won't do what you think it should.
The solution is to not use windows file separators when passing the argument to the program. The \ ends up getting escape sequenced with one or more \ . Changing the argument to unix style file separators correctly loads all of the jars within a directory.
eg:
MyApp "classpath"
MyApp C:\pathtojars\ <-- fails
MyApp C:/pathtojars/ <-- works
Fixed code:
MyClass::MyClass(std::string & classPath )
{
classPath = "-Djava.class.path="+classPath;
jvmOptions[0].optionString = (char *)classPath.c_str();
jvmOptions[1].optionString = "-Xms8m";
jvmOptions[2].optionString = "-Xmx24m";
jvmArgs.version = JNI_VERSION_1_6;
jvmArgs.options = jvmOptions;
jvmArgs.nOptions = 3;
jvmArgs.ignoreUnrecognized = JNI_TRUE;
int jvmInitResult = CreateJavaVM( &jvm, (void**)&environment, &jvmArgs);
if( jvmInitResult >= 0 )
{
jclass loadedClass = environment->FindClass( MyClassName.c_str() );
.....
Maven can be invoked with a -f option which allows you to specify an arbitrary pom.xml file.
From within a custom Maven plugin mojo, is it possible to determine whether Maven was invoked this way or using the default pom.xml from the current working directory?
I'm looking for something along the lines of:
this.project.isInvokedWithNonDefaultPom()
The Maven source code related to this option are:
./maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
./maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
(Look for keyword ALTERNATE_POM_FILE)
The source code can be obtained via git:
git clone https://git-wip-us.apache.org/repos/asf/maven.git
One part of the code uses following
if (commandLine.hasOption(CLIManager.ALTERNATE_POM_FILE))
Never tried this before but maybe there's a way you can do the same via plugin Mojo
Further to gerrytan's answer, there is an object called MavenExecutionRequest which gets populated with commandline information by org.apache.maven.cli.MavenCli, and which is available inside a plugin Mojo, via MavenSession.getRequest().
However, as the following code snippet from inside org.apache.maven.cli.MavenCli shows, the fact of being invoked with '-f' or not is lost, as the Pom file gets fully resolved as part of populating the MavenExecutionRequest.
So the answer is: No, it is not possible to know, from within a Maven plugin mojo, how the pom.xml was specified.
private MavenExecutionRequest populateRequest( CliRequest cliRequest )
{
MavenExecutionRequest request = cliRequest.request;
.....
String alternatePomFile = null;
if ( commandLine.hasOption( CLIManager.ALTERNATE_POM_FILE ) )
{
alternatePomFile = commandLine.getOptionValue( CLIManager.ALTERNATE_POM_FILE );
}
.....
if ( alternatePomFile != null )
{
File pom = resolveFile( new File( alternatePomFile ), workingDirectory );
request.setPom( pom );
}
else
{
File pom = modelProcessor.locatePom( baseDirectory );
if ( pom.isFile() )
{
request.setPom( pom );
}
}
.....
}
Version is maven-embedder 3.0.x