Deploying war file together with resources - java

I have war file which I have deployed but after deploying the resources and links are not working.
<build>
<finalName>KFA</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Tests.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
When I build the application I get kfa.war which i deploy to tomcat
but unfortunately I can't access any page, I get http status 404 -
/kfa/trainee. sample controller
#Controller
#RequestMapping("/kfa/trainee")
public class TraineeController {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
TraineeService traineeService;
RegService regService;
#Autowired
public void setTraineeService(TraineeService traineeService) {
this.traineeService = traineeService;
}
#Autowired
public void setRegService(RegService regService) {
this.regService = regService;
}
#RequestMapping(method = RequestMethod.GET)
public ModelAndView addMember(ModelMap model){
model.addAttribute("module", "kfa/trainee");
model.addAttribute("submodule", "add_trainee");
model.addAttribute("title", "Trainee");
model.addAttribute("subtitle", "Add");
model.addAttribute("trainee", new Trainee());
return new ModelAndView("/kfa/index", model);
}
}
When I ran and deploy within intellij idea I get everything working fine. My question is how should i configure the build pasted above to allow me ran the war file on tomcat in another machine.
If not understood you can ask for more information. I will be glad for your help.

If you deploy a war file called kfa.war in a tomcat container, tomcat assumes the context path /kfa if you don't give any other information while deploying.
Try to access /kfa/kfa/trainee.
But looking at the log files of your tomcat should help! You can install tomcat's manager war (https://tomcat.apache.org/tomcat-7.0-doc/manager-howto.html) to get information about the installed WARs in your container going to /manager/html.

Verify if your war has all the content that it is supposed to have by unzipping it.
If it does not have the required content make sure your project is using the right maven directory structure as mentioned here https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html.
If not you might have to restructure your project accordingly and everything should work as expected

Related

Is there a way to Debug why my executable JAR of a JavaFX-Project runs on my Computer but not on others ? (Using jdk 1.8._051)

I exportet a Jar of a JavaFX2 Project. It works fine, but when I run it on another machine there will be a
classDefNotFoundExeption: javafx.application.Application
Any hints how to tackle this Problem ?
This is my Manifest:
Class-Path: .
Main-Class: proj.view.Launcher
I also programmed Launcher that starts a Swing GUI in case JavaFX is not found.
Here is my Launcher Class
public class Launcher {
public static void main(String[] args) {
try {
Class c = javafx.application.Application.class;
proj.main.App.main(args);
}catch (NoClassDefFoundError e) {
String[] t = {"Swing Backup","Application start Error"};
MainFrame.remote(t);
}
}
}
The other computers are running on a Java installation that doesn't include JavaFX. It works on your machine because you do have JavaFX installed.
To test if javafx.application.Application is available, you need to use reflection, i.e.
boolean hasJavaFX;
try {
Class.forName("javafx.application.Application");
hasJavaFX = true;
} catch (ClassNotFoundException e) {
hasJavaFX = false;
}
if (hasJavaFX) {
MainFrame.remote(new String[] {"Swing Backup","Application start Error"});
} else {
proj.main.App.main(args);
}
You might get classDefNotFoundExeption: javafx.application.Application when you are running on machine having jdk above 11.
oracle has removed javaFX form JDK 11, hence need to provide dependency on javafx-controls module.
`<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>12-ea+9</version>
</dependency>`
add this to your dependency.
https://openjfx.io/
To me it looks like runnable jar issue if then same code is working through IDE's on those machines. You can try maven assembly plugin to pack your jar.
The Apache Maven Assembly Plugin allows users to aggregate the project output along with its dependencies, modules, site documentation, and other files into a single, runnable package.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>
package.your_main_class
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
I figured it out:
It was the User Path variable that pointed to a JDK10 bin.
We changed the Path. Now it works with "java -jar programm.jar"
but not with "java programm.jar"
but not with a Regular click on the file. But we wrote a batchFile that Starts the Application with "java -jar" and it works fine.
Has anyone a explanation for that behavior ?

Maven Filtering parameters in file

I have been looking over the maven war plugin and how to configure it. Here is my situation. I have a web application that is distributed to several production facilities. There are two files, in this web app, that are customized for each facility. These are /js/config.js and /META-INF/context.xml.
I have my project in a typical maven structure:
/src
|--/main
|--webapp
|--/js
|--config.js
|--properties
|--plant.properties
|--/META-INF
|--context.xml
I've left out non-essential directories for brevity.
The config.js has been altered to contain "parameter" I want substituted:
var Config {
...
system_title: '${plant_name} - Audit System',
...
}
The relevant portion of my pom is:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<filters>
src/main/webapp/js/properties/fayetteville.properties
</filters>
<failOnMissingWebXml>false</failOnMissingWebXml>
<webResources>
<resource>
<directory>src/main/webapp/js</directory>
<filtering>true</filtering>
<exclude>**/properties</exclude>
</resource>
</webResources>
</configuration>
</plugin>
When I run "mvn clean package", I would expect to see ${plant_name} replaced with what is in my properties file. In this case, my properties file contains a single key-value pair:
plant_name=Austin
But I am not seeing the substitution. The resulting config.js in the target folder still contains ${plant_name} as does the config.js in the resulting war file.
I really don't want to use profiles if possible. Eventually, I want the build process to use a list of properties files to do this for all plants.
From my research, including a number of SO questions and answers, I feel I have things configured correctly.
What might I be doing wrong?

jersey with jackson works when I run with netbeans but now when execute the jar file [duplicate]

I am using the Java Jersey framework(with Maven), and use IntelliJ as my IDE. I have encountered this runtime exception that ONLY happens when I try to run the code from the command line (using maven to compile and then java -jar ) but NOT when running within IntelliJ, which is strange.
I have some Java code that will try to make an HTTP GET on some remote URL and try to read the returned JSON into some Lombok POJO :
String targetUrl = "some valid URL";
WebTarget webTarget = client.target(targetUrl);
Response response = webTarget.request(MediaType.APPLICATION_JSON_TYPE).get();
ParseResponse parseResponse = response.readEntity(ParseResponse.class);
I am not sure why, but when it hits that last line that does the "readEntity()" method, I will get the error below:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/json; charset=utf-8
This is strange, because I definitely have the jersey-media-json-jackson dependency specified in my pom.xml :
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.23</version>
</dependency>
and this is my POJO class that I was trying to readEntity() into :
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class ParseResponse {
#JsonProperty("id")
private Integer id;
...Other params...
}
And like I mentioned before, it is strange that this only happens when I try to run on the command line like this but there is no error when running in IntelliJ:
mvn clean package
java -jar target/NameOfJar.jar
Did I miss something obvious here? I have looked at other people with similar issues like this online but haven't found a solution.
Thanks
IS
If you look inside the jersey-media-json-jackson jar you should see a file
META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
The contents of this file should be a single fully qualified name of a class that implements the name of the file, namely
org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable
This file is used by Jersey auto-discoverable mechanism to automatically register features without us having to explicitly register them. Briefly, how it works, is that all Jersey modules/jars that have components that should be automatically registered, should have the above named file located in the jar, with the contents being the name(s) of the auto-discoverable component. Jersey will then use the Service Loader pattern to load the classes named in the file, and register them.
The problem this causes when creating uber jars is that you can only have one copy of a file, you can't have duplicates. So what if we have multiple jars with the above file? Well only one of those files will be included in the uber jar. Which one? Who knows, but there is only one lucky winner. So for the rest of the jars, their auto-discover mechanism never kicks in. This is the case with your Jackson feature, where the auto-discoverable registers the JacksonFeature. You can try to explicitly register with your application, and you should see that it now works.
But what about other jars/modules that may have this file? It's for this reason that when creating uber jars, you should use the maven-shade-plugin. What this plugin allows you to do, is combine the contents of the files so that all the discoverables get included into that one single file. Below is an example usage
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.YourApp</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
This example was actually taken from Dropwizard's Getting Started. You can check it out for further explanation. The main part of concern the ServicesResorceTransformer, which is what concatenates the services files.

Getting maven project version and artifact ID from pom while running in Eclipse

I was looking up how to get the application name(artifact id) and version from maven pom or manifest when I came across this question Get Maven artifact version at runtime.
The above works for me when I package the project but I can't seem to get anything to work when I try to run the program using eclipse. I tried using the .properties method when building since I assumed that is not package dependent but I am still not getting a result. If anyone has an idea or solution to this problem it would be greatly appreciated.
My last attempt is below. This uses the manifest when packaged(which works) and trying to get the .properties file when running in eclipse.
String appVersion = getClass().getPackage().getImplementationVersion();
if(appVersion == null || "".equals(appVersion)) {
appVersion = Glob.getString(appVersion);
if(appVersion == null || "".equals(appVersion)) {
System.exit(0);
}
}
Create a property file
src/main/resources/project.properties
with the below content
version=${project.version}
artifactId=${project.artifactId}
Now turn on maven resource filtering
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
so that this file is processed into
target/classes/project.properties
with some content similar to this
version=1.5
artifactId=my-artifact
Now you can read this property file to get what you want and this should work every time.
final Properties properties = new Properties();
properties.load(this.getClassLoader().getResourceAsStream("project.properties"));
System.out.println(properties.getProperty("version"));
System.out.println(properties.getProperty("artifactId"));
An easy solution with maven 4 is now to add a VersionUtil static method in your package:
package my.domain.package;
public class VersionUtil {
public static String getApplicationVersion(){
String version = VersionUtil.class.getPackage().getImplementationVersion();
return (version == null)? "unable to reach": version;
}
}
The thing is you need this ´mave-war-plugin´ in the project's pom, saying you want to add addDefaultImplementationEntries:
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
...
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
...
Then call the VersionUtil.getApplicationVersion() from some place in your code.

FileNotFoundException for bean definition file happens only online, not on localhost

When I published a war file for an application that works locally with Eclipse WTP, I had a FileNotFoundException for the bean.xml file with my beans definitions.
SEVERE: Exception sending context initialized event to listener instance of
class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanDefinitionStoreException:
IOException parsing XML document from class path resource
[META-INF/spring/beans.xml]; nested exception is java.
io.FileNotFoundException: class path resource [META-INF/spring/beans.xml]
cannot be opened because it does not exist
at Caused by: java.io.FileNotFoundException: class path resource
[META-INF/spring/beans.xml] cannot be opened because it does not exist
...
I created the war file with mvn war:war and copied in the webapps folder of Tomcat 7.
beans.xml is located in src/main/resources/META-INF/spring/beans.xml and I've the following in my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webResources>
<resource>
<directory>src/main/resources</directory>
</resource>
</webResources>
</configuration>
</plugin>
In the war file beans.xml gets packaged in META-INF/spring/beans.xml
In my web.xml I've:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/spring/beans.xml</param-value>
</context-param>
However the file is not found. How to solve the problem?
UPDATE: as Matthew Farwell suggested, is bean.xml is not packaged in the right location, so it's not in the class path, I think it's specified with maven-war-plugin parameters, now I try to look at its documentation. If someone knows it would be helpful.
UPDATE 2: As explained in maven-war-plugin documentation, there is an optional parameter called targetPath. I tried and after changing maven-war-plugin configuration adding targetPath it gets packaged correctly.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webResources>
<resource>
<directory>src/main/resources</directory>
<targetPath>WEB-INF/classes</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
UPDATE 3: About Ryan Stewart's suggestion, I started my initial pom setup using roo, but after that I've done many changes and I'm not using roo any more. The directory src/main/resources is not mentioned in any other places in pom.xml (I've used grep), however the only setting that looks suspicious to me is:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration><encoding>UTF-8</encoding></configuration>
</plugin>
I've commented out that plugin, but nothing changed, then I commented out the configuration part of maven-war-plugin, but src/main/resources was not added to the war anymore, so for now I've added it back and I'm uploading it to test it online (it's still a staging server actually, not the final one anyway).
UPDATE 4 Ryan Stewart suggested that the problem was that I was running "mvn war:war" instead of "mvn package", and that was indeed the problem. With my targetPath, the resources appeared in WEB-INF/classes, but there weren't any classes there.
I was fighting an uphill battle, while instead the simpler solution was to remove the configuration part as in update 3, and use "mvn package" to build the war file. Thank you to both of you Ryan and Matthew, not only I solved my problem, but I've also learnt something more about Maven.
I have to assume you have another part of the POM that's excluding the file in question from being processed as a classpath resource, else it should be working. Either
Stop doing that, and it'll work fine--the content of src/main/resources becomes classpath resources by default--or
remove the classpath: from your path. Without that prefix, the path given in contextConfigLocation will be resolved against the root of the WAR file, and it will correctly find your file in META-INF/spring.
If you take path 1, then you should remove the webResources section, or you'll end up with the file in two places--not problematic, but potentially confusing.
In a war, / is not part of the classpath for a webapp. The classpath includes /WEB-INF/classes and all of the jars in /lib. See Apache Tomcat 6.0 - Class Loader HOW-TO
WebappX — A class loader is created for each web application that is
deployed in a single Tomcat instance. All unpacked classes and
resources in the /WEB-INF/classes directory of your web application,
plus classes and resources in JAR files under the /WEB-INF/lib
directory of your web application, are made visible to this web
application, but not to other ones.
The other web servers will have similar rules. If you wish to reference something as part of the classpath, put it in WEB-INF/classes.

Categories