Running a Spring MVC Webapp on Tomcat9 - spring

I'm trying to run a Spring MVC webapp on Tomcat9. I'm able to deploy it using Maven to Tomcat. I'm also able to access the index.jsp from FireFox. However, my index.jsp does a simple re-direct to /customer/list and that results in a 404 Not Found error. I've done RequestMapping on the controller class (for /customer) and GetMapping on a method in that class (for /list). The same code works when I run it as a dynamic web project in Eclipse with embedded Tomcat. But, when I re-wrote it as a Maven project, I'm only able to reach index.jsp, but the re-direct in index.jsp fails. Code below ...
index.jsp
<% response.sendRedirect("/customer/list"); %>
spring.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Add support for component scanning -->
<context:component-scan base-package="com.luv2code.crm" />
<!-- Add support for conversion, formatting and validation support -->
<mvc:annotation-driven/>
<!-- Define Spring MVC view resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- Step 1: Define Database DataSource / connection pool -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="org.postgresql.Driver" />
<property name="jdbcUrl" value="jdbc:postgresql://localhost/hibernate?currentSchema=web_crm" />
<property name="user" value="hbstudent" />
<property name="password" value="hbstudent" />
<!-- these are connection pool properties for C3P0 -->
<property name="initialPoolSize" value="5"/>
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxIdleTime" value="30000" />
</bean>
<!-- Step 2: Setup Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="com.luv2code.crm.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Step 3: Setup Hibernate transaction manager -->
<bean id="myTransactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Step 4: Enable configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="myTransactionManager" />
<!-- Add support for reading web resources: css, images, js, etc ... -->
<mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>
</beans>
CustomerController.java
package com.luv2code.crm.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.luv2code.crm.entity.Customer;
import com.luv2code.crm.service.CustomerService;
#Controller
#RequestMapping("/customer")
public class CustomerController {
#Autowired
private CustomerService customerService;
#GetMapping("/list")
public String listCustomers(Model m) {
m.addAttribute("customerList", customerService.getCustomers());
return "list-customers";
}
#GetMapping("/showFormForAdd")
public String showFormForAdd(Model m) {
m.addAttribute("customer", new Customer());
return "customer-form";
}
#PostMapping("/saveCustomer")
public String saveCustomer(#ModelAttribute("customer") Customer c) {
customerService.saveCustomer(c);
return "redirect:/customer/list";
}
#GetMapping("/showFormForUpdate")
public String showFormForUpdate(#RequestParam("customerId") int i, Model m) {
m.addAttribute("customer", customerService.getCustomer(i));
return "customer-form";
}
#GetMapping("/delete")
public String deleteCustomer(#RequestParam("customerId") int i) {
customerService.deleteCustomer(i);
return "redirect:/customer/list";
}
#GetMapping("/search")
public String searchCustomers(#RequestParam("theSearchName") String s, Model m) {
m.addAttribute("customerList", customerService.searchCustomers(s));
return "list-customers";
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.luv2code</groupId>
<artifactId>web_crm</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>web_crm Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring.version>5.3.5</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.19</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.30.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>web_crm</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<url>http://localhost:8080/manager/text</url>
<server>TomcatServer</server>
<path>/web_crm</path>
<username>admin</username>
<password>password</password>
<update>true</update>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<distributionManagement>
<repository>
<id>internal.repo</id>
<name>Internal repo</name>
<!-- <url>file:///home/tushar/Software/apache-tomcat-9.0.43/webapps</url> -->
<url>http://localhost:8080/manager</url>
</repository>
</distributionManagement>
</project>
Directory structure
$ tree
.
├── pom.xml
└── src
├── main
│   ├── java
│   │   ├── com
│   │   │   └── luv2code
│   │   │   └── crm
│   │   │   ├── controller
│   │   │   │   └── CustomerController.java
│   │   │   ├── dao
│   │   │   │   ├── CustomerDAOImpl.java
│   │   │   │   └── CustomerDAO.java
│   │   │   ├── entity
│   │   │   │   └── Customer.java
│   │   │   ├── service
│   │   │   │   ├── CustomerServiceImpl.java
│   │   │   │   └── CustomerService.java
│   │   │   └── test
│   │   │   └── TestDBServlet.java
│   │   └── hibernate.cfg.xml
│   ├── resources
│   └── webapp
│   ├── index.jsp
│   ├── resources
│   │   └── css
│   │   ├── add-customer-style.css
│   │   └── style.css
│   └── WEB-INF
│   ├── classes
│   │   └── hibernate.cfg.xml
│   ├── spring.cfg.xml
│   ├── view
│   │   ├── customer-form.jsp
│   │   └── list-customers.jsp
│   └── web.xml
└── test
19 directories, 17 files

I was finally able to resolve this.
In pom.xml, you can specify a deployment path. By default, it is the same as your artifactId. Then, when you specify the url mapping in web.xml, it should be relative to the deployment path. In my web.xml, I was including the deployment path component as well in the url mapping. Hence, it was not working.
I changed the url mapping to / and it works fine.

Related

static files in springboot project deployed to an external Tomcat with WAR

I'm new to Spring and Springboot, I'm just trying an easy thing I can't sort out:
As per the title, I want to put in a project some static files, then package the project with maven as war and deploy it to an existing Tomcat.
I'm using Springboot 2.7.8, Java 17 and Tomcat 8.5.47
This is my pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.8</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo-01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>demo-01</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
and this is my application class:
package com.example.demo01;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class Demo01Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Demo01Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Demo01Application.class, args);
}
}
then I've put an "Hello World" index.html under src/main/resources/static
and finally I've run
mvn clean package
and I've got a war file like this:
├───META-INF
└───WEB-INF
├───classes
│ │ application.properties
│ │
│ ├───com
│ │ └───example
│ │ └───demo01
│ │ Demo01Application.class
│ │
│ └───static
│ index.html
│
└───lib
jackson-annotations-2.13.4.jar
jackson-core-2.13.4.jar
jackson-databind-2.13.4.2.jar
jackson-datatype-jdk8-2.13.4.jar
jackson-datatype-jsr310-2.13.4.jar
jackson-module-parameter-names-2.13.4.jar
jakarta.annotation-api-1.3.5.jar
jul-to-slf4j-1.7.36.jar
log4j-api-2.17.2.jar
log4j-to-slf4j-2.17.2.jar
logback-classic-1.2.11.jar
logback-core-1.2.11.jar
slf4j-api-1.7.36.jar
snakeyaml-1.30.jar
spring-aop-5.3.25.jar
spring-beans-5.3.25.jar
spring-boot-2.7.8.jar
spring-boot-autoconfigure-2.7.8.jar
spring-boot-starter-2.7.8.jar
spring-boot-starter-json-2.7.8.jar
spring-boot-starter-logging-2.7.8.jar
spring-boot-starter-web-2.7.8.jar
spring-context-5.3.25.jar
spring-core-5.3.25.jar
spring-expression-5.3.25.jar
spring-jcl-5.3.25.jar
spring-web-5.3.25.jar
spring-webmvc-5.3.25.jar
As you can see, th index.html is under WEB-INF\classes\static
Is it supposed to be served by tomcat from that location?!
Anyway: I've deployed the war file to Tomcat, and when I point my browser to http://localhost/demo-01-0.0.1-SNAPSHOT I get a sad 404
What an I missing ?
EDIT:
I've found the cause of my problem (thanks to #khmarbaise who pointed me in the right direction): since the external Tomcat instance (8.5.47) is using Java 8, having instructed Spring Boot to make the package compliant with Java 17, with these directive in my pom.xml:
<properties>
<java.version>17</java.version>
</properties>
created the problem.
It was sufficient to remove these three lines, and now everything works fine.

Merge parent and child pom during assembly

I have a multi-module maven project. I want to assembly each of the child so when they are uncompressed and executed with maven to not depend on the parent pom.
Is there a way with assembly plugin to kind of "merge" the parent pom and the child pom?
Original project:
├── pom.xml
├── README.md
├── module1
│   ├── assembly.xml
│   ├── pom.xml
│   ├── README.md
│   └── src
└── module2
├── assembly.xml
├── pom.xml
├── README.md
└── src
Assembly package (zip):
moduleX
├── pom.xml <-- merged pom
├── README.md
└── src
The packaged assembly will be used by an external client outside from our organization, so he doesn't have access to our repositories.
Update:
As JF Meier suggested, using flatten-maven-plugin solves my issue.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>flatten</id>
<phase>prepare-package</phase>
<goals>
<goal>flatten</goal>
</goals>
<configuration>
<flattenMode>bom</flattenMode>
<pomElements>
<build>keep</build>
</pomElements>
</configuration>
</execution>
</executions>
</plugin>
And then on my assembly.xml I just add the generated .flattened-pom.xml and rename it to pom.xml:
<files>
<file>
<source>.flattened-pom.xml</source>
<destName>pom.xml</destName>
</file>
</files>
I guess you want something like the
https://www.mojohaus.org/flatten-maven-plugin/
It allows you to "merge" the parent POM into your POM.

Apache Karaf WAR file deploy not working. 404-Not found on webbrowser

I am creating SpringMVC application with maven in IntelliJ. I referred this link for creating SpringMVC maven application. here, is a code of
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>temp-maven</groupId>
<artifactId>spring-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<spring.version>5.1.0.RELEASE</spring.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
</dependencies>
</project>
web.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--<web-app xmlns=”http://java.sun.com/xml/ns/j2ee"-->
<!--xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance"-->
<!--xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"-->
<!--version=”2.4″>-->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>HelloWorld Application</display-name>
<description>
This is a simple web application for karaf deployment test.
</description>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
I want to deploy WAR of this application on Karaf container. To generate .war file, I am executing below command inside project directory.
mvn compile
mvn package
This generates .war in /target directory.
After that I am copying generated .war file to /deploy directory of karaf. This automatically deploys my bundle in Karaf. On execution of below commands, it shows .war bundle as deployed.
karaf#root()> web:list
ID │ State │ Web-State │ Level │ Web-ContextPath │ Name
────┼─────────────┼─────────────┼───────┼─────────────────┼──────────────────────────────
151 │ Active │ Deployed │ 80 │ /spring-maven │ spring-maven (1.0.0.SNAPSHOT)
karaf#root()> http:list
ID │ Servlet │ Servlet-Name │ State │ Alias │ Url
────┼───────────────────────┼──────────────────────────┼─────────────┼─────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
59 │ TomcatResourceServlet │ /system/console/res:/res │ Deployed │ /system/console/res │ [/system/console/res/*]
59 │ KarafOsgiManager │ ServletModel-6 │ Deployed │ /system/console │ [/system/console/*]
151 │ TomcatResourceServlet │ default │ Deployed │ /spring-maven/ │ [/spring-maven/]
151 │ DispatcherServlet │ dispatcher │ Deployed │ │ [/spring-maven/]
151 │ JspServletWrapper │ jsp │ Deployed │ │ [/spring-maven/*.jsp, /spring-maven/*.jspx, /spring-maven/*.jspf, /spring-maven/*.xsp, /spring-maven/*.JSP, /spring-maven/*.JSPX, /spring-maven/*.JSPF, /spring-maven/*.XSP]
But when I open http://localhost:8181/spring-maven/, it shows HTTP Status 404 – Not Found. Apache Tomcat/8.5.32. I don't have tomcat on my machine. I am not getting where I am going wrong. Please guide me on this issue.
Thank you.
However, Karaf not perform component-scan like Tomcat. Remove these 2 lines
<context:component-scan base-package="YourPackageName" /> <mvc:annotation-driven />
and adding
<context:annotation-config /> in HelloWeb-servlet.xml worked for me.

Where to put persistence.xml in gwt maven MultiModule project?

I have project with one parent maven module and three submodules:
server
shared
web
Here is main project (aka parent) pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pl.derp</groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>server</module>
<module>shared</module>
<module>web</module>
</modules>
<properties>
<gwtVersion>2.7.0</gwtVersion>
<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<tomcat.webport>8082</tomcat.webport>
<tomcat.ajpport>8182</tomcat.ajpport>
<tomcat.context>/parent</tomcat.context>
</properties>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
<version>${gwtVersion}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
<classifier>sources</classifier>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean install tomcat7:run-war-only</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>${gwtVersion}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
</plugin>
<!-- IDE -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.7</version> <!-- Note 2.8 does not work with AspectJ aspect path -->
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<wtpversion>2.0</wtpversion>
<additionalBuildcommands>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
</additionalBuildcommands>
<additionalProjectnatures>
<projectnature>com.google.gwt.eclipse.core.gwtNature</projectnature>
</additionalProjectnatures>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<path>${tomcat.context}</path>
<port>${tomcat.webport}</port>
<ajpPort>${tomcat.ajpport}</ajpPort>
<systemProperties>
<JAVA_OPTS>-XX:MaxPermSize=256m</JAVA_OPTS>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
</project>
Here is my whole project structure:
daniel#DK1L:~/git/GWT2.7MavenEclipse/GWT2.7MavenEclipse$ tree
.
├── pom.xml
├── server
│   ├── pom.xml
│   └── src
│      └── main
│      ├── java
│      │   └── pl
│      │   └── derp
│      │   └── server
│      │   └── GreetingServiceImpl.java
│      └── resources
│      ├── META-INF
│      │   └── persistence.xml
│      └── pl
│      └── derp
│      └── server.gwt.xml
├── shared
│   ├── pom.xml
│   └── src
│      └── main
│      ├── java
│      │   └── pl
│      │   └── derp
│      │   ├── shared
│      │   │   └── FieldVerifier.java
│      │   └── web
│      │   ├── GreetingServiceAsync.java
│      │   └── GreetingService.java
│      └── resources
│      └── pl
│      └── derp
│      └── shared.gwt.xml
├── war
│   └── WEB-INF
│   └── web.xml
├── web
│   ├── pom.xml
│   └── src
│      ├── main
│      │   ├── java
│      │   │   └── pl
│      │   │   └── derp
│      │   │   └── web
│      │   │   ├── Messages.java
│      │   │   └── parent.java
│      │   ├── resources
│      │   │   └── pl
│      │   │   └── derp
│      │   │   ├── parent.gwt.xml
│      │   │   └── web
│      │   │   ├── Messages_fr.properties
│      │   │   └── Messages.properties
│      │   └── webapp
│      │   ├── META-INF
│      │   │   └── context.xml
│      │   ├── parent.css
│      │   ├── parent.html
│      │   └── WEB-INF
│      │   └── web.xml
│      └── test
│      ├── java
│      │   └── pl
│      │   └── derp
│      │   └── web
│      │   └── GwtTestparent.java
│      └── resources
│      └── pl
│      └── derp
│      └── parentJUnit.gwt.xml
└── WebContent
└── META-INF
I wonder Where I should put persistence.xml? In what package name, dir and project should I put it?
I use gwt 2.7
If you use a maven structure project, you should put the persistence.xml file into the following directory:
src/main
/java
/com.my.package
/client
/shared
/server
/resources
/META-INF/persistence.xml
According to that documentation
the right place for the persistence.xml would be:
WEB-INF/classes/META-INF.

Nar dependency in multi-module maven project

I set up a multi module maven project, which is comprised of a module destined to build nar jni library, and a jar packaged module that is dependent on that library.
I am able to install the nar library to my local maven repository, but I fail to use it in dependent module.
For instance, I run mvn nar:nar-unpack and I get:
[INFO] ------------------------------------------------------------------------
[INFO] Building nar-dependent 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- nar-maven-plugin:3.2.0:nar-unpack (default-cli) # nar-dependent ---
[INFO] Unpacking 0 dependencies to /home/przemek/Documents/stimulant/nar-dependent/target/nar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
It seems that there are no nar dependencies, which is obviously not true.
Moreover, trying to execute the main method of the class that makes use of the jni library fails:
mvn exec:java -Dexec.mainClass=App
[INFO] --- exec-maven-plugin:1.4.0:java (default-cli) # nar-dependent ---
[WARNING]
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:293)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.UnsatisfiedLinkError: no nar-library-1.0-SNAPSHOT in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1865)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at jnibook.NarSystem.loadLibrary(NarSystem.java:23)
at jnibook.HelloWorld.<clinit>(HelloWorld.java:10)
at App.main(App.java:9)
... 6 more
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
The structure of the project looks like this:
.
├── nar-dependent
│   ├── pom.xml
│   └── src
│   └── main
│   └── java
│   └── App.java
├── nar-library
│   ├── pom.xml
│   └── src
│   ├── main
│   │   ├── c
│   │   │   └── HelloWorld.c
│   │   ├── include
│   │   ├── java
│   │   │   └── jnibook
│   │   │   └── HelloWorld.java
│   │   └── resources
│   └── test
│   └── java
├── parent
│   └── pom.xml
Here is the parent pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sidec</groupId>
<artifactId>stimulant</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>../nar-library</module>
<module>../nar-dependent</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
The nar-library module pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>sidec</groupId>
<artifactId>stimulant</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>nar-library</artifactId>
<packaging>nar</packaging>
<name>nar-library</name>
<properties>
<skipTests>true</skipTests>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.2.0</version>
<extensions>true</extensions>
<configuration>
<cpp>
<exceptions>false</exceptions>
</cpp>
<libraries>
<library>
<type>jni</type>
<linkCPP>false</linkCPP>
<narSystemPackage>jnibook</narSystemPackage>
</library>
</libraries>
<javah>
<includes>
<include></include>
</includes>
</javah>
</configuration>
</plugin>
</plugins>
</build>
</project>
The nar-dependent pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>sidec</groupId>
<artifactId>stimulant</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>nar-dependent</artifactId>
<packaging>jar</packaging>
<name>nar-dependent</name>
<build>
<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.2.0</version>
<extensions>true</extensions>
<!--<executions>-->
<!--<execution>-->
<!--<id>nar-download</id>-->
<!--<goals>-->
<!--<goal>nar-download</goal>-->
<!--</goals>-->
<!--</execution>-->
<!--</executions>-->
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>sidec</groupId>
<artifactId>nar-library</artifactId>
<version>1.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
</dependencies>
</project>
Finally, as a proof that it is really the HelloWorld project, a library class:
package jnibook;
public class HelloWorld {
public native void print();
static {
NarSystem.loadLibrary();
}
}
and a client app:
import jnibook.HelloWorld;
public class App {
public static void main(String ... args){
(new HelloWorld()).print();
}
}
I referenced https://maven-nar.github.io/examples.html with no success.
I have no idea what is going wrong.
Any ideas? Here is zip with project.
This might be an outdated question, but I'll answer all the same :
When running the java JNI app, it must be told where to find the .so library holding the relevant native C code used by JNI.
For example, if you closed your app in the executable jar app.jar :
java -Djava.library.path=[path to the .so native C library] -jar app.jar
PS - you can see that the JVM can't find the native C library thanks to the exception : java.lang.UnsatisfiedLinkError: no nar-library-1.0-SNAPSHOT in java.library.path
I have tried my own variant of your example with version 3.6.0 of the plugin. With that version, I at least get
Unpacking 1 dependencies to /home/karsten/svn/hellotest/target/nar
and the .so gets unpacked when I run mvn nar:nar-unpack in the dependent module.
But the only way I have found to make mvn nar:nar-integration-test work in the dependent module, is by writing
LD_LIBRARY_PATH=target/nar/hellojni-0.0-amd64-Linux-gpp-jni/lib/amd64-Linux-gpp/jni mvn nar:nar-integration-test
I tried several ways of specifying java.library.path, but with no success.

Resources