Enforce class only once in jar/ear/rar with maven build - java

In light of a recent problem I had, I would like to make sure it does not happen again. Kind of like a regression test for my build system.
I need a way to scan an ear (or other jar style package) to make sure a class is only once in it.
Example:
- test.ear
| - lib (folder)
| | - api.jar (zipped file)
| | - packageName
| | - ClassName.class
| - connector.rar (zipped file)
| - api.jar (zipped file)
| - packageName
| - ClassName.class
| - ejbs.jar
The pom.xml of ejbs.jar has a dependency on the api that brings the api.jar to the lib folder. The pom.xml of the connector.rar also has a dependency on the api that brings the api.jar to the connector.rar file, so while the reference to the same dependency, it still causes the above result.
As I have a maven build I'm looking for a way that integrates well there (if possible).

There's this enforcer rule you can use. Have a look at http://www.mojohaus.org/extra-enforcer-rules/banDuplicateClasses.html

Related

How to put custom Gradle plugins on an another projects build classpath?

I have a published gradle plugin which looks something like this:
|__root
| |
| |
| |__java
| | |__SomeJavaClass.java
| | |__SomeJavaClass2.java
| |
| |__kotlin
| |__MyPluginClass.kts
| |__MyTaskClass.kts
| |__Utils.kts
I would like to include this plugin as a project in my multi project build instead of publishing it to a repo for easier developement.
This plugin has 3 Kotlin files Project A is using. MyPluginClass.kts has my own plugin class, MyTaskClass.kts has my own task class and Utils.kts contains only kotlin functions. The java classes are used in MyPlugin and MyTask.
It is being put on Project A's build.gradle.kts classpath as
classpath("com.my:custom.plugin:version")
A very simplified project structure I would like to achieve:
root
|
|__Project A
| |
| |__build.gradle.kts
| |__x.gradle.kts
| |__y.gradle.kts
| |__settings.gradle
|
|__Project build-logic
| |
| |__build.gradle.kts
| |
| |__java
| | |__SomeJavaClass.java
| | |__SomeJavaClass2.java
| |
| |__kotlin
| |__MyPluginClass.gradle.kts
| |__MyTaskClass.gradle.kts
| |__Utils.gradle.kts
I'm trying to create plugins from those kotlin files and include them in my main build because i need them precompiled, but i cant seem to find a way to put them on Project A's classpath when build.gradle is running there. Is it even possible? what would be the proper solution?
I'm using gradle 7.3
You can combine multiple, independent, Gradle projects using composite builds. The same is also true for Gradle plugins.
Including a Gradle plugin from another directory is documented in the Testing Gradle plugins section.
So if you have a shared-build-logic project that provides a Gradle plugin with an ID my.shared-build-logic, and you want to use that in project-a.
my-projects/
├── shared-build-logic/
│ ├── src/
│ │ └── ...
│ ├── build.gradle.kts
│ └── settings.gradle.kts
└── project-a/
├── src/
│ └── ...
├── build.gradle.kts
└── settings.gradle.kts
Then you need to include shared-build-logic in your project-a Gradle settings file.
// my-projects/project-a/settings.gradle.kts
rootProject.name = "project-a"
pluginManagement {
includeBuild("../shared-build-logic")
}
Now, so long as shared-build-logic correctly provides a Gradle plugin, in project-a you can reference that plugin.
// my-projects/project-a/settings.gradle.kts
plugins {
id("my.shared-build-logic")
}
Finnaly figured out. I didn't create plugins from build-logic, left them as kotlin files. Since it is a separate gradle project, i can just build the project and point project A's classpath to the produced jar file like
buildscript {
dependencies {
classpath(files("path.to.the.jar"))
}
}
this way i can access methods and the MyTask from Project A.
The other issue was that i wanted to apply MyPlugin like
plugins{
id("my-plugin-name")
}
which wasnt working, i guess because it is a class. But now since i had the whole project jar on my build classpath, i can do this:
apply<my-plugin-name>()

Integrate spring projects and EJB projects within a gradle(or maven) multiple projects

I have a gradle multiple projects. The structure is like below:
|--MyProject
| |--ejb-project
| | --build.gradle
| |--spring-project
| --com.mine.demo
| --Test.java
| | --build.gradle
| |--build.gradle
| |--settings.gradle
in the settings.gradle
include: ':ejb-project'
include: ':spring-project'
I defined a Test.java in the spring-project.
Now, if I wanna use Test.java in the EJB projects, How can I use it? Are there configurations to be configured?
Questions can be simplfy as this: Can I use a class from spring project in a ejb project within a gradle(or maven) multiple projects? If can, How can I use it?
I've never done this before, so barely know how to integrate spring in ejb. HELP!

Spring Boot application with part of JSP files from other Maven module

Let's assume that we have Spring Boot based web application using JSP templates. It can be even as simple as in the following example (from official Spring Projects repository)
Project structure:
|-src/main/java/
| |-sample.tomcat.jsp
| |-SampleTomcatJspApplication.java
| |-WelcomeController.java
|-src/main/resources/
| |-application.properties
|-src/test/java/
| |-...
|-src/main/webapp/
| |-WEB-INF
| |-jsp
| |-welcome.jsp
|-pom.xml
Properties file contains view prefix /WEB-INF/jsp/ and suffix .jsp and when requesting / we see properly rendered content of welcome.jsp.
WelcomeController.java
application.properties
Changes
Now let's make the following changes
Duplicate WelcomeController.java as WelcomeController2.java and change a bit request mapping, model attributes and returned view name, e.g.:
#RequestMapping("/2")
public String welcome2(Map<String, Object> model) {
model.put("message", "Hi from Welcome2");
return "welcome2";
}
Duplicate welcome.jsp as welcome2.jsp so that src/main/webapp will be like this:
|-src/main/java/
| |-sample.tomcat.jsp
| |-SampleTomcatJspApplication.java
| |-WelcomeController.java
| |-WelcomeController2.java
...
|-src/main/webapp/
| |-WEB-INF
| |-jsp
| |-welcome.jsp
| |-welcome2.jsp
Then when requesting /2 we can see properly rendered content of welcome2.jsp.
The question
What is the way of splitting such project into two maven projects, so that both WelcomeController2.java and welcome2.jsp could be moved to other project (maven dependency) and still be successfully resolved when /2 URL is requested?
Note that with Spring Boot web-fragment.xml (that could be placed in META-INF directory of dependency) is ignored.
Unfortunately, I don't know of an easy way to do this but one approach I've used is to create a Maven artifact just like normal for the main project, in your case probably a WAR artifact. This project will need to have a dependency upon your second project. Then your second project would consist of two components:
A standard Maven JAR artifact containing the compiled class files.
A Maven assembly ZIP consisting of the JSP files that need to be included in the WAR archive as well. This will be generated from the second project during the package phase, but will need to be included as a separate dependency on the main project using a zip classifier.
When the first project is built, you'll need to unpack the assembly dependency as part of the packaging process for the WAR archive. If you want this to work in an IDE, you'll probably need to unpack it in a fairly early phase, such as process-resources or generate-sources.

build.sbt configuration to add external java files using sbt packageSrc

I am using sbt-xjc plugin to generate java classes from XSD files. The plugin generates these classes under project/target/scala-2.10/xjc directory.
I need to create 2 jar files one with all .class files and another with all .java source files.
I am able to generate the jar file that has all .class files using sbt package but the issue is with sbt packageSrc, this command is looking only for folder those are in project/src/java folder and not considering files those are generated by sbt-xjc plugin under project/target/scala-2.10/xjc. Is there any configuration that i can provide that could help?
To know why this happens the command inspect tree packageSrc is helpful, it will also tell you what to change to have your sources included.
When executed should show you something like this:
> inspect tree packageSrc
[info] compile:packageSrc = Task[java.io.File]
[info] +-compile:packageSrc::packageConfiguration = Task[sbt.Package$Configuration]
[info] | +-compile:packageSrc::mappings = Task[scala.collection.Seq[scala.Tuple2[java.io.File, java.lang.String]]]
[info] | | +-compile:unmanagedSources = Task[scala.collection.Seq[java.io.File]]
[info] | | +-compile:unmanagedResources = Task[scala.collection.Seq[java.io.File]]
[info] | | +-compile:unmanagedResourceDirectories = List(/tmp/q-23437043/src/main/resources)
[info] | | +-*:baseDirectory = /tmp/q-23437043
[info] | | +-compile:unmanagedSourceDirectories = List(/tmp/q-23437043/src/main/scala, /tmp/q-23437043/src/main/java)
// more stuff but not relevant for us
You can see from there that SBT is using mappings key to know from where to take the files.
Knowing that we can take the generated files and add them to the mappings in packageSrc in your build.sbt:
import Path.flat
xjcSettings
def xjcSources(base: File) = base ** "*"
mappings in Compile in packageSrc ++= xjcSources((sourceManaged in (Compile, xjc)).value) pair flat
You can read more about Mappings and Paths to customize / control the result.

Unit tests must locate in the same package?

A JUnit book says " protected method ... this is one reason the test classes are located in the same package as the classes they are testing"
Can someone share their experience on how to organize the unit tests and integration tests (package/directory wise)?
I prefer the maven directory layout. It helps you separate the test sources and test resources from your application sources in a nice way and still allow them to be part of the same package.
I use this for both maven and ant based projects.
project
|
+- src
|
+- main
| |
| +- java // com.company.packge (sources)
| +- resources
|
+- test
|
+- java // com.company.package (tests)
+- resources
in my build process, the source directories are
java/src
java/test/unit
java/test/integration
The test and the source code are in different paths, but the packages are the same
java/src/com/mypackage/domain/Foo.java
java/test/unit/com/mypackage/domain/FooTest.java
java/test/integration/com/mypackage/domain/FooTest.java

Categories