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

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.

Related

Properties in spring boot project as dependency

I have a Spring Boot Web project that has a Spring Boot JPA project as a dependency like so:
spring_boot_web
|__.../application.yml
|
|__spring_boot_jpa
| |__.../data.properties
| |__.../data-test.properties
| |__.../data-dev.properties
| \__pom.xml
|
|__pom.xml
Web project uses the default application.yml file and jpa uses a properties file as yml are not supported by #PropertySource annotation.
I can run them alone flawlessly but when I try to include the jpa inside web there are problems creating the beans related to db. Is there any way to have those project running their own config files?
I just got it working. As the JPA project does not stand on its own (only for testing purposes) I just left some properties for the profiles I want that project to run standalone and then the main properties file under the web project. The structure is as follows:
spring_boot_web
|__.../application.yml
|
|__spring_boot_jpa
| |__.../application-test.yaml
| |__.../application-dev.yaml
| \__pom.xml
|
|__pom.xml
And then I made sure that there was only one #SpringBootApplication in between both projects altogether.
Also keep in mind that the main #SpringBootApplication has to be in a package in common for both projects:
spring_boot_web
|__foo.bar.core
| \__SpringWebApplication.java <- main #SpringBootApplication
|
|__foo.bar.core.web
| \__...
|
\__spring_boot_jpa
\__foo.bar.core.services
\__...

Log4j2 environment variables are not applied

My project depends on a jar that (among other things I need) includes common logging configurations for a number of projects. I can update the jar, but I can't break compatibility with existing consumers. The jar contains:
src
|-- main/resources
| |-- log4j2-bad.xml // not actually named `-bad` but a config I want to overwrite for a unique use case without losing the other classes in the jar
| `-- log4j2.component.properties //contents=`log4j2.configurationFile=log4j2-bad.xml,log4j2.xml`
`-- test/resources
`-- log4j.xml // normally the consumer provides their own `log4j2.xml` file.
I want to provide an opt-in alternative file (e.g. log4j2-good.xml) in src/main/resources. Since the documentation says that environment variables (and specifically LOG4J_CONFIGURATION_FILE) should take precedence over log4j2.component.properties, it seems like I could just add log4j2-good.xml to the jar, and consumers that want to opt-in could arrange for the LOG4J_CONFIGURATION_FILE environment variable to be log4j2-good.xml,log2j2.xml at runtime.
However, this does not seem to work.
I added a Main class to the jar for testing. It contains some logging statements and this static block:
static {
System.out.println("LOG4J_CONFIGURATION_FILE: " + System.getenv().get("LOG4J_CONFIGURATION_FILE"));
}
When I set $env:LOG4J_CONFIGURATION_FILE=log4j2-good.xml,log4j2.xml and run it, I get:
2021-11-17 21:39:32,091 main DEBUG Apache Log4j Core 2.14.1 initializing configuration org.apache.logging.log4j.core.config.composite.CompositeConfiguration#6ee52dcd [configurations=[XmlConfiguration[location=C:\<snip>\bin\main\log4j2-bad.xml], XmlConfiguration[location=C:\<snip>\bin\test\log4j2.xml]], mergeStrategy=org.apache.logging.log4j.core.config.composite.DefaultMergeStrategy#4493d195, rootNode=null, listeners=[org.apache.logging.log4j.core.LoggerContext#2781e022], pluginPackages=[], pluginManager=org.apache.logging.log4j.core.config.plugins.util.PluginManager#57e1b0c, isShutdownHookEnabled=true, shutdownTimeoutMillis=0, scriptManager=null]
<snip>
LOG4J_CONFIGURATION_FILE: log4j2-good.xml,log4j2.xml
So log4j2 uses the bad config, but my Main says the environment variable specifies the good config.
When I open Windows system properties and set the system environment variable...same thing.
When I run a gradle task:
task runGoodConfig(type: JavaExec) {
classpath = sourceSets.test.runtimeClasspath
main = 'com.my.sample.Main'
environment(['LOG4J_CONFIGURATION_FILE':'log4j2-good.xml,log4j2.xml'])
}
same result.
What am I missing!?
This is a confirmed bug in version 2.14.1 (at least).

How to get only required dependency from parent dependency maven pom file

Can I include only the required dependencies from parent pom(like we have exclude)?
I need this to achieve one scenario
Project A with hibernate and spring as my dependencies(there are
many other)
Project B with only hibernate and spring
Project C with A and B as dependencies
Problem statement : when I run maven install in project C, hibernate and spring are again downloaded separately. This I observed because of the increase in final jar size.
As a work around I included project A as dependency in project C so that I don't need to mention hibernate and spring explicitly.
To avoid this is there a way to include only spring and hibernate from project A?
It sounds like you are guessing what's in the project C jar just based on size. Unzip the final jar (rename to .zip) and look inside to see what jars are actually being packaged to figure that out.
Jars, wars, ears are just zip files with a manifest (more or less).
So, your all dependencies should be defined in parent pom and all your projects here in case A, B and C should be child projects of the parent pom.
In all child poms, you can define all dependencies needed without versions, so that they will be resolved from parent pom.
Interdependency of child projects should be defined only in case of needed. This, to get just dependencies from project A, C should not depends on A.
| - - A
| - - | - - pom.xml
| - - B
| - - | - - pom.xml
| - - C
| - - | - - pom.xml
| - - pom.xml (parent pom)
If you could get this structure as github project, then I can create a pull request with the changes.
To Get Spring Hibernate from you need to make Child Parent relationship A(Parent) and B, C as Child.
Jar file increment mustn't be the case. POM.xml does provide reference of dependencies downloaded in .m2 repo.
For further investigation we need POM.xml

How to change contents of .properties in Gradle upon war creation

I'm experimenting with Gradle's war plugin. At this point project is still using Ant. Its a standard webapp layout:
| - project
| ---- src/main/java
| ---- src/main/resource
| ---- src/main/webapp
| ---- src/main/webapp/WEB-INF/classes
In src/main/webapp/WEB-INF/classes there's a properties file containing key jawr.debug.on. For development purposes, it is usually set to true. During release phase this property is changed to false using Ant's propertyfile task.
I'm unable to find similar way of performing this in Gradle. I did find snippet below, but its not changing said file inside the resulting war:
ant.propertyfile(
file: "jawr.properties") {
entry( key: "jawr.debug.on", value: "false")
}
What would be the proper way to achieve this?
One way would be to filter it during war creation
war {
rootSpec.eachFile {
if (it.name == 'UserMessages.properties') {
filter { line ->
line.replace('#build.label#', "${buildLabel}-${stage}")
}
}
}
}

Configuring angular 2 with spring mvc project without spring boot

I am configuring spring mvc project to use angular 2 without spring boot.
my directory structure is :
Project
|
+--src
|
+--resources
| |
| +--css
| |
| +--js
| |
| +--angular
| |
| +--app/
| |
| +--node_modules/
| |
| +--package.json,systemjs.config.js,tsconfig.json
|
|
+--WEB-INF
|
+--pages
|
+--index.jsp
I have included the follwing lines in index.jsp
<!-- 1. Load libraries for angular 2 setup -->
<!-- Polyfill(s) for older browsers -->
<script src="${pageContext.request.contextPath}/resources/angular/node_modules/core-js/client/shim.min.js"></script>
<script src="${pageContext.request.contextPath}/resources/angular/node_modules/zone.js/dist/zone.js"></script>
<script src="${pageContext.request.contextPath}/resources/angular/node_modules/reflect-metadata/Reflect.js"></script>
<script src="${pageContext.request.contextPath}/resources/angular/node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="${pageContext.request.contextPath}/resources/angular/systemjs.config.js"></script>
<script>
System.import('${pageContext.request.contextPath}/resources/angular/app').catch(function(err){ console.error(err); });
</script>
I have followed the angular 2 quick start
https://angular.io/guide/quickstart
All the files contain the same code mentioned in the above link. The only thing i have changed is:
Copied app directory, node_modules directory and configuration files to resources directory and modified index.jsp to load it from there.
It is throwing the following exception:
GET http://localhost:8085/Phoenix/resources/angular/app/ 404 (Not Found) in browser console. Please suggest anything to fix this issue.
Follow below steps to achieve our main goal, to run SPRINGMVC + Angular2 on a single server.
Create normal Dynamic web project.
Add all dependancy required for spring or user maven pom.xml
Open CMD, navigate to angular2 application. Hit command npm install and then ng build or use ng build --prod for production.This command will create a "dist" folder, copy all files including all folders.
Paste those files and folders into WebContent directory.
Last thing, you need to change basehref="./" in index.html. Now you are ready to run server or you can deploy war file and serve it with tomcat or other servers.
Checkout this thread, I have mentioned file structure and its working fine.
I know there are many drawbacks to use these way for running application on a single server, but if it must required you can follow this.
If you change anything at angular side, you need to copy paste dist folder all time and then you can deploy it!
I think you are missing the Ressourcehandler configuration and also the Controller on Java site - Here are some examples for using Spring MVC and Angular

Categories