Why not to use / as a context path in maven tomcat? - maven

I'm using maven tomcat plugin to deploy an app. It does deploy in root context if I set path to <path>/<path> but I want to know if it causes any problems because the docs explicitly says "Do not use /".
Related question: How to set context path to root(“/”) in Tomcat 7.0 when using Maven
Why not to use / as path in maven tomcat?

The JavaDoc pointing out to "Do not use /" was introduced in this commit:
(MTOMCAT-102) Add a mojo to build a standalone jar to run a web application: use path field to store webapp to have a more nice name than projet.build.finalName
When scrolling down the commit you see that the path property value is used to create a JarArchiveEntry:
os.putArchiveEntry( new JarArchiveEntry( path + ".war" ) );
which for configured <path>/<path> would translate to a file name of "/.war" looking kind of invalid. On the other this would possibly yield to ".war" file name when extracted.
Today for version 2.2 this piece of code looks like this changed for bug MTOMCAT-103:
os.putArchiveEntry(
new JarArchiveEntry(
StringUtils.removeStart( path, "/" ) + ".war"
)
);
which for configured <path>/<path> would translate to ".war" as file name looking way more legal but still not really desirable imho.
As the Tomcat 7 Documentation states the base file name for the empty context path
(aka "/") should be ROOT your best bet is to choose <path>ROOT<path> to achieve the desired result.
Edit:
For reproducing this, I checked out tomcat-maven-plugin.git and used their integration test. I had some truble to get a functional build at all, bit after removing some stuff from their server.xml and changing tomcat7-maven-plugin version to 2.1 it worked:
This is the diff applyied to their integration test app:
diff --git a/tomcat7-maven-plugin/src/it/simple-war-exec-project/pom.xml b/tomcat7-maven-plugin/src/it/simple-war-exec-project/pom.xml
index 8ce51b7..e00f0ea 100644
--- a/tomcat7-maven-plugin/src/it/simple-war-exec-project/pom.xml
+++ b/tomcat7-maven-plugin/src/it/simple-war-exec-project/pom.xml
## -42,7 +42,7 ##
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
- <version>#pom.version#</version>
+ <version>2.1</version>
</plugin>
</plugins>
</pluginManagement>
## -65,7 +65,7 ##
</goals>
<phase>package</phase>
<configuration>
- <path>foo</path>
+ <path>ROOT</path>
<serverXml>src/main/tomcatconf/server.xml</serverXml>
</configuration>
</execution>
diff --git a/tomcat7-maven-plugin/src/it/simple-war-exec-project/src/main/tomcatconf/server.xml b/tomcat7-maven-plugin/src/it/simple-war-exec-project/src/main/tomcatconf/server.xml
index 76ab562..de086fc 100644
--- a/tomcat7-maven-plugin/src/it/simple-war-exec-project/src/main/tomcatconf/server.xml
+++ b/tomcat7-maven-plugin/src/it/simple-war-exec-project/src/main/tomcatconf/server.xml
## -19,14 +19,7 ##
<Server port="8010" shutdown="SHUTDOWN">
- <GlobalNamingResources>
- <!-- Used by Manager webapp -->
- <Resource name="UserDatabase" auth="Container"
- type="org.apache.catalina.UserDatabase"
- description="User database that can be updated and saved"
- factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
- pathname="conf/tomcat-users.xml" />
- </GlobalNamingResources>
+
<Service name="Catalina">
<Connector port="8080" keepAliveTimeout="1800000" maxKeepAliveRequests="30000" maxThreads="300" />
## -34,8 +27,6 ##
<Engine name="Catalina" defaultHost="localhost">
<Valve className="org.apache.catalina.valves.AccessLogValve"
resolveHosts="false" pattern="%t-ip:%a-protocol:%H-localPort:%p-path:%U-time:%D ms"/>
- <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
- resourceName="UserDatabase" />
<Host name="localhost" appBase="webapps" />
</Engine>
Then from within the folder /tomcat-maven-plugin/tomcat7-maven-plugin/src/it/simple-war-exec-project I did:
$ mvn clean package
...
[INFO] BUILD SUCCESS
...
$ cd target/
$ java -jar simple-war-exec-project-1.0-SNAPSHOT-war-exec.jar
...
INFORMATION: Deploying web application archive C:\Temp\tomcat-maven-plugin\tomcat7-maven-plugin\src\it\simple-war-exec-project\target\.extract\webapps\ROOT.war
...
And the result:

Related

Websphere 9 maven remote deployment

My springboot application builds into a WAR file (using Jenkins). I want to automate the remote deployment to Websphere 9.
I have read around and it seems there is no maven plugin for deployment to websphere 9 but ant support is pretty good. So, I'm using maven ant plugin to help running those ant tasks. I started with attempt to list the applications installed, just to see if it works. However I'm running into an exception related to localization:
[ERROR] C:\DEV\ant-was-deploy.xml:81:
java.util.MissingResourceException: Can't find bundle for base name
com.ibm.ws.profile.resourcebundle.WSProfileResourceBundle, locale
en_US
My ant-was-deploy.xml is referenced from pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>id123</id>
<phase>clean</phase>
<configuration>
<locales>es</locales>
<target>
<ant antfile="${basedir}/ant-was-deploy.xml">
<target name="listApps"/>
</ant>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
ant-was-deploy.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project name="websphere" default="listApps" basedir="." >
<target name="listApps" >
<taskdef name="wsListApps" classname="com.ibm.websphere.ant.tasks.ListApplications" classpath="${wasHome.dir}/plugins/com.ibm.ws.runtime.jar" />
<wsListApps
profileName="AppServ01"
wasHome="C:\\opt\\IBM\\WebSphere\\AppServer"
/>
</target>
</project>
I think the error comes from com.ibm.ws.runtime.jar. Inside it has WSProfileResourceBundle.class and WSProfileResourceBundle_en.class but not WSProfileResourceBundle_en_US.class (name is just an assumption - I have copied the bundle with this name inside the jar but it didn't work).
I also tried to set the locale for the entire plugin but it seems that localization for this plugin is not implemented properly (no impact in my case - I set the locale to 'es' but still got the error for en_US).
I also tried to pass system parameters to maven command: mvn clean -Duser.language=fr -Duser.country=FR
It didn't work either.
So, my question is if there is a way to change the locale before the ant script? If I can set it to 'en' probably it will find the right resource bundle.
I'm fairly new to Websphere, if there is another solution to automate the remote deployment to websphere 9 I would be happy to hear it. I would rather not use scripts on target server or Jenkins plugin but if there is no other way ...
I just had the same issue. In my case, i was using an AppServer name (AppSrv1 instead of AppSrv01) that did not exist anymore, in my maven settings.xml.
The right server name solved the issue.

Liquibase loadData changeset ignores context

I have a jhipster project, with Java, Spring and Liquibase as always. I want to load mock users on "dev" mode only, but when deploying to Heroku using the "prod" profile, they are ALSO loaded. It's like the context is ignored completely by liquibase. What am I doing wrong here?
The application-prod.yml file has a liquibase context set to "prod"
spring:
liquibase:
contexts: prod
and the application-dev.yml is setting liquibase context to "dev":
spring:
liquibase:
contexts: dev
I have some mock user data that I want to load only on dev (when running on localhost), and the liquibase changeset looks like this:
<changeSet author="me" id="mock-data-1" context="dev" >
<loadData encoding="UTF-8"
file="config/liquibase/mock_users.csv"
separator=";"
tableName="jhi_user">
<column name="activated" type="boolean"/>
<column name="created_date" type="timestamp"/>
</loadData>
...
</changeSet>
All other changesets have no context applied.
(Probably not relevant but) my mock_users.csv looks like this:
id;login;password_hash;first_name;last_name;email;image_url;activated;lang_key;created_by;last_modified_by;created_date;team_id
5;user1;$2a$10$VEjxo0jq2YG9Rbk2HmX9S.k1uZBGYUHdUcid3g/vfiEl7lwWgOH/K;;;user1#localhost.com;;true;sv;system;system;2019-12-03T09:21:06Z;1
Here is my Procfile for Heroku deployment:
web: java $JAVA_OPTS -jar target/*.war --spring.profiles.active=prod,heroku --server.port=$PORT
release: cp -R src/main/resources/config config && ./mvnw liquibase:update -Pheroku
When deploying to Heroku however the logs say thay no context is set at all:
Liquibase settings:
...
2019-12-03T13:17:08.821255+00:00 app[release.7646]: [INFO] context(s): null
...
And the entire changeLog is executed, I can see that in the Heroku logs too.
How do I make sure the liquibase contexts from my application-prod.yml file are used correctly?
EDIT* I can make heroku run liquibase with prod context by editing the pom file, under the "heroku" profile, "liquibase maven plugin" setting the "contexts" tag:
<profile>
<id>heroku</id>
<build>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<configuration combine.self="override">
<changeLogFile>src/main/resources/config/liquibase/master.xml</changeLogFile>
<diffChangeLogFile>src/main/resources/config/liquibase/changelog/${maven.build.timestamp}_changelog.xml</diffChangeLogFile>
<driver></driver>
<url>${env.JDBC_DATABASE_URL}</url>
<defaultSchemaName></defaultSchemaName>
<username>${env.JDBC_DATABASE_USERNAME}</username>
<password>${env.JDBC_DATABASE_PASSWORD}</password>
<referenceUrl>hibernate:spring:se.axesslab.respekttrappan.domain?dialect=org.hibernate.dialect.PostgreSQL82Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy</referenceUrl>
<verbose>true</verbose>
<contexts>prod</contexts>
<logging>debug</logging>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
</configuration>
</plugin>
But should this really be required? Then what's the point of having the application-*.yml files hold different liquibase contexts?
The execution of Liquibase is triggered from within the Maven plugin, ./mvnw liquibase:update -Pheroku. The maven plugin doesn't know about the Liquibase context you set in Spring's property file.
Like you figured out yourself, you have to either set the context in the pom.xml or let Spring execute Liquibase.

SonarQube - Multimodule project based on filesystem hierarchy

Some cvsrepository named Foo has several modules, f.e. module1, module2, ...
A buildscript does cvs checkout, compile and building the module.jar for all modules.
After the build has finished the filesystem looks like that :
Foo/module1/src
/bin
/module2/src
/bin
...
Now i want to use the sonartask like that :
Define the global sonar properties like sonar.username ... sonar.projektName=Foo for MainProject and sonar.modules=module1.module2,... for the modules.
Afterwards looping over the module folders, setting module specific sonar properties,
like sonar.projectName (for modulename) sonar.sources, sonar.binaries etc.
Looping works fine, but it seems as sonar wants a single build.xml for every submodule.
So i need another possibility for grouping modules.
I only found a commercial plugin => Portfolio Management plugin but need another solution.
-- EDIT --
I already found and tried to use the examples from github and documentation, but it seems theyrequire one main build file and a build.xml in every module folder.
Whereas my situation is different. There's only one build.xml that contains a javac + jar target for every module of my project. When build is done, the resulting filesystem looks like mentioned above.
The build is part of the deployment workflow which is driven by a xmlproperty file, that contains the projectname and all modulenames of that deployment job among other things.
Now after the build is done, in the next antfile i want to loop over the modules in that xmlproperty file via xmltask, pointing the module specific properties to filesystem, f.e. sonar.sources=/Foo/module1/src sonar.binaries=/Foo/module1/bin and call <sonar:sonar/> . Overriding of module specific properties in the loop is done via Flaka <let>
After all it's just looping over an existing filesystem setting the sonar poperties and calling the sonar task with approiate properties.
-- EDIT after comment --
Tried it like that :
build.xml
<project name="sonar" xmlns:fl="antlib:it.haefelinger.flaka" xmlns:sonar="antlib:org.sonar.ant">
<fl:install-property-handler/>
<!-- Import Sonar -->
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml"/>
<!-- Import XMLTask -->
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
<xmltask source="C:/WKS/Eclipse/372/sonar/props.xml">
<copy path="//project/name/text()" property="projectname"/>
<copy path="//module/*/label/text()" property="projectlabel"/>
<copy path="//module/*/name/text()" property="modules" append="true" propertyseparator="," />
</xmltask>
<property name="sonar.projectKey" value="${projectname}"/>
<!-- Set modules IDs -->
<property name="sonar.modules" value="#{replace('${modules}', '', ' ')}"/>
<property name="sonar.language" value="java" />
<property name="sonar.sourceEncoding" value="UTF-8" />
<property name="sonar.host.url" value="http://somehost:9000" />
<property name="sonar.login" value="admin" />
<property name="sonar.password" value="admin" />
<xmltask source="C:/WKS/Eclipse/372/sonar/props.xml">
<call path="//module/*">
<param path="label/text()" name="modullabel"/>
<param path="name/text()" name="modulname"/>
<actions>
<fl:let>
sonar.projectName ::= replace('#{modulname}', '', ' ')
sonar.projectVersion ::= '#{modullabel}'
sonar.#{replace('#{modulname}', '', ' ')}.projectBaseDir ::= '${ant.working.dir}/build/projects/${projectname}/#{modulname}'
sonar.sources ::= '${ant.working.dir}/build/projects/${projectname}/#{modulname}/src'
sonar.binaries ::= '${ant.working.dir}/build/results/compile/${projectname}/#{modulname}'
</fl:let>
<!-- Execute Sonar -->
<sonar:sonar />
</actions>
</call>
</xmltask>
</project>
output :
Setting project property: modules -> Modul 1,Modul 2,Modul 3,Modul 4
Setting project property: sonar.projectKey -> Foobar
Setting project property: sonar.modules -> Modul1,Modul2,Modul3,Modul4
Setting project property: ant.working.dir -> c:\WKS\5513
Setting project property: sonar.language -> java
Setting project property: sonar.sourceEncoding -> UTF-8
Setting project property: sonar.host.url -> http://somehost:9000
Setting project property: sonar.login -> admin
Setting project property: sonar.password -> admin
Setting project property: sonar.projectName -> Modul1
Setting project property: sonar.projectVersion -> l_5_04_52_cd
Setting project property: sonar.Modul1.projectBaseDir -> c:\WKS\5513/build/projects/foobar/Modul 1
Setting project property: sonar.sources -> c:\WKS\5513/build/projects/foobar/Modul 1/src
Setting project property: sonar.binaries -> c:\WKS\5513/build/results/compile/foobar/Modul 1
parsing buildfile jar:file:/C:/WKS/Eclipse/372/DevJars/sonar/sonar-ant-task-2.1.jar!/org/sonar/ant/antlib.xml with URI = jar:file:/C:/WKS/Eclipse/372/DevJars/sonar/sonar-ant-task-2.1.jar!/org/sonar/ant/antlib.xml from a zip file
Class org.sonar.ant.SonarTask loaded from parent loader (parentFirst)
[sonar:sonar] Apache Ant(TM) version 1.9.1 compiled on May 15 2013
[sonar:sonar] Sonar Ant Task version: 2.1
[sonar:sonar] Loaded from: file:/C:/WKS/Eclipse/372/DevJars/sonar/sonar-ant-task-2.1.jar
[sonar:sonar] INFO: Default locale: "de_DE", source code encoding: "UTF-8"
[sonar:sonar] INFO: Work directory: C:\WKS\sonar
[sonar:sonar] INFO: Sonar Server 3.7.2
BUILD FAILED
C:\WKS\Eclipse\372\sonar\sonar.xml:41: The following error occurred while executing this line:
C:\WKS\Eclipse\372\sonar\sonar.xml:54: org.sonar.runner.impl.RunnerException: Unable to execute Sonar
...
Caused by: java.lang.IllegalStateException: The base directory of the module 'Modul1' does not exist: C:\WKS\Eclipse\372\sonar\Modul 1
I tried also to set the basedir attribute to the value of my ${ant.working.dir}, where all binariues and src folders reside, didn't work either.
See documentation : http://docs.codehaus.org/display/SONAR/Analyzing+with+SonarQube+Ant+Task#AnalyzingwithSonarQubeAntTask-Multi-moduleProject
And example : https://github.com/SonarSource/sonar-examples/tree/master/projects/multi-module/ant
I had a similar problem. When you run the ant task from eclipse, sonar errors are not showed. so, I figure out the problem when the ant ask was executed from command console.
I had two problems:
The sonar.host.url property is mandatory
The sonar.projectKey could not contain special characters, for instance space

jetty load multiple context

We have an maven+springMVC application that uses maven jetty plugin to start the app up when we do development. We use a jetty-env.xml file to set a context and JNDI config. The application will be part of a bigger portal.
We are using maven jetty plugin
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.2.0.v20101020</version>
with config
<webAppConfig>
<contextPath>/ASX/mainApp</contextPath>
<jettyEnvXml>src/main/resources/jetty-env.xml</jettyEnvXml>
</webAppConfig>
and use jetty-env.xml
<Configure id='jms-webapp-wac' class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/ASX/mainApp</Set>
...
...
</Configure>
Our dir structure is:
MainApp
/forms
page1.html
page2.html
etc...
/WEB-INF
web.xml
PortalApp
/BAL_S
/css
/images
/js
etc...
Now the PortalApp only has static files and is not really a web application i.e. it doesn't have web.xml
The application is dependent on javaScripts from the portal. The location of some of the javaScript are like:
<script src="/BAL_S/js/portal-jquery-lib.js"></script>
<script src="/BAL_S/js/libs/foundation.js"></script>
etc...
As you can see that the location starts with /BAL_S which we are finding tricky to get working as it's like referring to another webapp context. When we start the application with jetty we get javaScript errors because it cannot find /BAL_S
If we deploy our app in tomcat and configure it, as below, the application works fine without any javaScript errors.
<Context path="/" docBase="PortalApp"/>
So the question is how can I do the similar configuration in Jetty so when the application starts up it detects /BAL_S context?
I guess we need to have two contexts in Jetty. How do I configure that?
What is the webConfig for maven jetty plugin to refer to this config?
Hope someone can help. Example would be useful.
Thanks in advance.
GM
OK All I had to do was add to maven jetty plugin configuration, the following:
<contextHandlers>
<contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext">
<contextPath>/</contextPath>
<resourceBase>src/main/PortalApp/</resourceBase>
</contextHandler>
</contextHandlers>
So this configures context path '/' to 'src/main/PortalApp/' and now we are able to get to /BAL_S in the tag.

Jetty Maven Plugin is ignoring custom webdefault.xml

I'm trying to get around the common issue of Jetty locking static files on Windows with the technique of setting useFileMappedBuffer to false in webdefault.xml. Unfortunately, every time Jetty is not picking up my customized webdefault.xml.
I'm using Apache Maven 3.0.2. I've tried using the maven-jetty-plugin (v6.1.26) and jetty-maven-plugin (v8.0.0.M2) but with no difference. I've tried running clean and rebuilding as well before running Jetty.
I've verified each time that my webdefault.xml was taken from the same version as the plugin and has the correct settings, namely, only changing this setting from true to false:
...
<init-param>
<param-name>useFileMappedBuffer</param-name>
<param-value>false</param-value>
</init-param>
...
And here's what my pom.xml Jetty plugin section looks like:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<contextPath>/</contextPath>
<webDefaultXml>src/main/resources/webdefault.xml</webDefaultXml>
</configuration>
</plugin>
I've also tried altering the path to my file:
<webDefaultXml>${basedir}/src/main/resources/webdefault.xml</webDefaultXml>
Everywhere I've seen this exact solution and it sounds like it is working for others (although I found one instance where someone had my issue). The startup for jetty has this in the output:
> mvn jetty:run
...
[INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml
[INFO] Web overrides = none
...
This further makes me think it isn't being applied. All the other paths are correct in the output.
My most direct issue that I'm seeing while Jetty is running is that whenever I edit a static file (JavaScript, CSS, etc.) with IntelliJ IDEA 10, I get this error message:
Cannot save file:
D:\...\... (The requested operation cannot be performed on a file with a user-mapped section open)
After I stop Jetty then it saves just fine. This happens every time.
Any ideas what I could be doing wrong? Thanks in advance.
I found an entirely different doc for the newer Jetty plugin jetty-maven-plugin (v8.0.0.M2) and it looks like the configuration name has changed:
http://wiki.eclipse.org/Jetty/Reference/webdefault.xml#Using_the_Jetty_Maven_Plugin
<project>
...
<plugins>
<plugin>
...
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<webAppConfig>
...
<defaultsDescriptor>/my/path/to/webdefault.xml</defaultsDescriptor>
</webAppConfig>
</configuration>
</plugin>
...
</plugins>
...
</project>
This now seems to work for the newer plugin. I'm still unsure why the v6 plugin does not pick up the customized config.
The only solution I found that worked with maven-jetty-plugin 6.1.24 was this:
http://false.ekta.is/2010/12/jettyrun-maven-plugin-file-locking-on-windows-a-better-way/
The Jetty documentation outlines three ways to do it (as of Jetty 9):
https://www.eclipse.org/jetty/documentation/current/troubleshooting-locked-files-on-windows.html
I successfully used the init-param method in Maven:
<!-- Running an embedded server for testing/development -->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.9.v20180320</version>
<configuration>
<webApp>
<_initParams>
<org.eclipse.jetty.servlet.Default.useFileMappedBuffer>false</org.eclipse.jetty.servlet.Default.useFileMappedBuffer>
</_initParams>
</webApp>
</configuration>
</plugin>

Resources