I am very new to web world and so I was trying to create a simple
JSP-Servlet based webpage but wanted to build the same on maven. I
google almost everything but eclipse is throwing exception while
trying to create eclipse maven project , while trying to create
dynamic project from Eclipse , it worked but couldn;t find an easy way
to integrate Servlet along with JSP page, Finally I found a way , I
created a dynamic web project in eclipe, then created required java
directory in the project and compiled with maven included the servlet
dependency. Is it a proper way to do it , or is there some extremely
easy way to create dynamic web project in maven which includes JSP ,
Servlet both.
Now once I am done with my approach may be broken approach , just after clicking on the first page button , getting
SEVERE: Allocate exception for servlet Controllertest
java.lang.ClassNotFoundException: com.abc.test.Controller
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)
at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:529)
at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:511)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:139)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1148)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:864)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:134)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
So here is my structure of the code-
my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>de.vogella.wtp.jsp</display-name>
<welcome-file-list>
<welcome-file>ShowAll.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description>Controllertest</description>
<display-name>Controllertest</display-name>
<servlet-name>Controllertest</servlet-name>
<servlet-class>com.abc.test.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Controllertest</servlet-name>
<url-pattern>/Controllertest</url-pattern>
</servlet-mapping>
</web-app>
and my servlet-
import java.io.IOException;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Controllertest
*/
public class Controllertest extends HttpServlet {
private static final long serialVersionUID = 1L;
private static String DELETE_JSP = "/Delete.jsp";
private static String EDIT_JSP = "/Edit.jsp";
private static String SHOWALL_JSP = "/ShowAll.jsp";
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String forward="";
// Get a map of the request parameters
#SuppressWarnings("unchecked")
Map parameters = request.getParameterMap();
if (parameters.containsKey("delete")){
forward = DELETE_JSP;
} else if (parameters.containsKey("edit")){
forward = EDIT_JSP;
} else {
forward = SHOWALL_JSP;
}
RequestDispatcher view = request.getRequestDispatcher(forward);
view.forward(request, response);
}
}
I don;t think any more tweaks I did .
for better clarification here is my eclipse Deployment Assembly
my 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>com.mkyong</groupId>
<artifactId>CounterWebApp3</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>CounterWebApp3 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<build>
<finalName>CounterWebApp3</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${basedir}/src/main/java</directory>
<targetPath>WEB-INF/classes</targetPath>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.css</include>
<include>**/*.html</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Actually the problem is the output classes are getting generated
inside target/classes.Once I copied the classes from target to web-inf
, it worked.
Now I need to know the reason and then need to figure that out in my set-up.
Please try to create your servlet class by right click on project –> New –> Class, not with the right click on project –> New –> Servlet option in Eclipse.
I have tried it and it is working fine
Related
I have created a maven project with basic archetype. created a web.xml under /webapp/WEB-INF .
web.xml is given as follows
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<welcome-file-list>
<welcome-file>home.html</welcome-file>
</welcome-file-list>
</web-app>
pom.xml is as shown below.
<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.tvashtra</groupId>
<artifactId>HelloWorld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
home.html is present in webapp folder but outside WEB-INF directory.
along with this created a servlet by extending HttpServlet class like below.
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("/Login")
public class ServletOne extends HttpServlet
{
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException
{
try {
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Mukesh Khanna</title>");
out.println("</head>");
out.println("<body>");
out.println("<h2>My name is Ashish Parab</h2>");
out.println("</body>");
out.println("</html>");
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
I ensure that jboss http port is working on 9080 port
now after doing all this, i deployed the war however nothing seems to work.
*
http://localhost:9080/HelloWorld
*
*
http://localhost:9080/HelloWorld/Login
*
both above links displaying message as "the site can't be reached"
context root is HelloWorld
upon googling/youtubing, i have come across many examples where they are using Tomcat server as plugin but i don't want that.
Thanks in advance
as suggested in below comment, i created jboss-web.xml and kept under WEB-INF
i am using JBOSS 7 EAP and below is the content of jboss-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.jboss.com/xml/ns/javaee
http://www.jboss.org/j2ee/schema/jboss-web_5_1.xsd">
<context-root>/HelloWorld</context-root>
</jboss-web>
however still not able to hit the target http://localhost:9080/HelloWorld
there seems to be problem of multiple jboss instances running on a same machine.
followed the exact same procedure without jboss-web.xml
also removed servlet dependency from pom and added below one
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
it worked like a charm!
I am trying to use the JCA and CICSECI functionality to connect to IBM Mainframe via the CICS Transaction Gateway.
My Servlet code is:
package com.ebs.jca.web;
import java.io.IOException;
import javax.annotation.Resource;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.Interaction;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ebs.cics.copybook.T060.T060REQUEST;
import com.ebs.cics.copybook.T060.T060RESPONSE;
import com.ibm.connector2.cics.ECIInteractionSpec;
/**
* Servlet implementation class CICSServlet1
*/
#WebServlet("/CICSServlet1")
public class CICSServlet1 extends HttpServlet {
private static final long serialVersionUID = 1L;
#Resource(lookup="eis/cicsECI_CF")
private ConnectionFactory cf = null;
/**
* #see HttpServlet#HttpServlet()
*/
public CICSServlet1() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
T060REQUEST t060Req = new T060REQUEST();
t060Req.setAccountNumber("10917683");
t060Req.setApplication("ST");
t060Req.setTransactionId("T060");
T060RESPONSE t060Resp = new T060RESPONSE();
try {
Connection eciConn = cf.getConnection();
Interaction eciInt = eciConn.createInteraction();
// Setup the interactionSpec.
ECIInteractionSpec eSpec = new ECIInteractionSpec();
eSpec.setCommareaLength(8000);
//eSpec.setReplyLength(20);
eSpec.setFunctionName("EBOT060");
eSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);
eciInt.execute(eSpec, t060Req, t060Resp);
//eciInt.execute(eSpec, t060Req, t060Resp);
/*System.out.println("return code is:");
System.out.println(t060Resp.getReturnCode());
icbResp.setResp__code(Short.toString(t060Resp.getReturnCode()));
icbResp.setResp__text(t060Resp.getReturnText());*/
} catch (ResourceException e) {
e.printStackTrace();
//throw e;
} catch (Exception e) {
e.printStackTrace();
throw e;
}
response.getWriter().append("Resp: ").append(Short.toString(t060Resp.getReturnCode())).append(", text: ").append(t060Resp.getReturnText());
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
The exeption that I am getting is:
[err] com.ibm.connector2.cics.CICSUserInputException: CTG9628E InteractionSpec passed to execute() not of type ECIInteractionSpec
[err] at com.ibm.connector2.cics.ECIInteraction.execute(Unknown Source)
[err] at com.ebs.jca.web.CICSServlet1.doGet(CICSServlet1.java:62)
[err] at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
[err] at [internal classes]
[err] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[err] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[err] at java.lang.Thread.run(Thread.java:748)
My server.xml is as follows:
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>localConnector-1.0</feature>
<feature>javaee-7.0</feature>
<feature>jca-1.7</feature>
</featureManager>
<keyStore id="defaultKeyStore" password="{xor}NDomDCswLToPKDs="/>
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<library id="ebsPropertiesFiles">
<folder dir="C:\ICBFiles\Properties\EBS\"/>
</library>
<!--The location of the cicseci.rar needs to be updated to the full path-->
<resourceAdapter autoStart="true" id="eciResourceAdapter" location="C:\ICBFiles\SharedLibs\cicseci9002.rar"/>
<connectionFactory id="cicsECI_CF" jndiName="eis/cicsECI_CF">
<!--The properties need to be updated to the location of the CICS Transaction Gateway-->
<properties.eciResourceAdapter ServerName="CICSQ2V5" connectionUrl="tcp://EBS-WSDEV2-2012.ad.xxx.pri" portNumber="2006"/>
</connectionFactory>
<applicationMonitor updateTrigger="mbean"/>
<webApplication id="jca-web" location="jca-web.war" name="jca-web"/>
</server>
And my POM is:
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>https://raw.github.com/WASdev/ci.maven.tools/master/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
<modelVersion>4.0.0</modelVersion>
<groupId>com.ebs.jca</groupId>
<artifactId>jca-web</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>jca-web</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>net.wasdev.maven.tools.targets</groupId>
<artifactId>liberty-target</artifactId>
<version>RELEASE</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.ibm.websphere.ws</groupId>
<artifactId>wsadie.marshall</artifactId>
<version>1.0.0</version>
<type>jar</type>
<!-- <scope>provided</scope> -->
</dependency>
<dependency>
<groupId>com.ebs.cics.copybooks</groupId>
<artifactId>T060</artifactId>
<version>1.2.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>javax.resource</groupId>
<artifactId>javax.resource-api</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.ibm.cicseci</groupId>
<artifactId>cicseci</artifactId>
<version>9.0.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.ibm.cicseci</groupId>
<artifactId>cicsframe</artifactId>
<version>9.0.0</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<finalName>${project.name}</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
When I google the error code. The IBM docs state:
https://www.ibm.com/support/knowledgecenter/en/SSZHFX_9.2.0/CTG9628E.html
"Review your Java client application. Refer to the product documentation for further details."
I have reviewed the following tutorials but they do not show a complete build environment.
https://developer.ibm.com/cics/2014/05/06/using-jca-with-the-cics-tg-in-websphere-liberty-profile/
https://github.com/cicsdev/cicstg-jca-liberty-sample
And I get the same error when using the sample code.
I have also tried to setting up a connectionFactory as described in this link:
https://www.ibm.com/support/knowledgecenter/SSGMCP_5.3.0/com.ibm.cics.ts.java.doc/topics/dfhpj2_jca_remote_eci_devconfig.html
When I set up a connectionFactory as shown:
<connectionFactory id="com.ibm.cics.wlp.jca.local.eci" jndiName="eis/ECI">
<properties.com.ibm.cics.wlp.jca.remote.eci serverName="CICSQ2V5" connectionUrl="tcp://EBS-WSDEV2-2012.ad.xxxx.pri" portNumber="2006"/>
</connectionFactory>
the dependency injection breaks.
CWNEN0030E: The server was unable to obtain an object instance for the java:comp/env/com.ibm.ctg.samples.liberty.JCAServlet/cf reference. The exception message was: CWNEN1003E: The server was unable to find the eis/ECI binding with the javax.resource.cci.ConnectionFactory type for the java:comp/env/com.ibm.ctg.samples.liberty.JCAServlet/cf reference.
Many Thanks
Looking at your server.xml configuration, the web application doesn't have the classloader definition required to load the InteractionSpec class from the resource adapters.
So it should be specified as
<webApplication id="jca-web" location="jca-web.war" name="jca-web">
<classloader classProviderRef="eciResourceAdapter" />
</webApplication>
Posting the process that I have followed to solve the issue.
There was obviously a class version conflict as stated by Trilarion and crshnburn.
Thanks for the help.
1 Install new Liberty profile.
2 Extract the cics.jar from the RAR archive for compile purposes.
3 Do not include the jcaRemoteEci-1.0 feature in the server.xml.
4 Use the following server.xml:
<?xml version="1.0" encoding="UTF-8"?>
<server description="ejb server">
<!-- Enable features -->
<featureManager>
<feature>javaee-7.0</feature>
<feature>localConnector-1.0</feature>
</featureManager>
<!-- Encoded password can be generated using bin/securityUtility -->
<keyStore password="change1me"/>
<basicRegistry id="basic" realm="BasicRealm">
<user name="user1" password="change1me"/>
</basicRegistry>
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<library id="ebsPropertiesFiles">
<folder dir="C:\\ICBFiles\\Properties\\EBS" />
</library>
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint id="defaultHttpEndpoint"
httpPort="9080"
httpsPort="9443" />
<!--The location of the cicseci.rar needs to be updated to the full path-->
<resourceAdapter autoStart="true" id="eciResourceAdapter" location="C:\ICBFiles\SharedLibs\cicseci9200.rar"/>
<connectionFactory id="cicsECI_CF" jndiName="eis/cicsECI_CF">
<!--The properties need to be updated to the location of the CICS Transaction Gateway-->
<properties.eciResourceAdapter connectionUrl="tcp://EBS-WSDEV2-2012.ad.aib.pri" portNumber="2006" ServerName="CICSUWV5"/>
</connectionFactory>
<enterpriseApplication id="icb-liberty-ear" location="icb-liberty-ear.ear" name="icb-liberty-ear">
<classloader commonLibraryRef="ebsPropertiesFiles" classProviderRef="eciResourceAdapter"/>
</enterpriseApplication>
</server>
4 Use the following pom.xml. Note that cicseci is defined with the 'provided' scope allow compiler dependency but to avoid packaging into the war archive.
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.icb</groupId>
<artifactId>icb-liberty</artifactId>
<version>1.0</version>
</parent>
<artifactId>icb-liberty-war</artifactId>
<packaging>war</packaging>
<name>ICB WAR Module</name>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<log4j.version>2.8.2</log4j.version>
<apache.commons.version>3.5</apache.commons.version>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ibm.cicseci</groupId>
<artifactId>cicseci</artifactId>
<version>9.0.0</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.ibm.websphere.ws</groupId>
<artifactId>wsadie.marshall</artifactId>
<version>1.0.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.ebs.cics.copybooks</groupId>
<artifactId>LAICBRES</artifactId>
<version>1.0.0</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<finalName>icb-liberty-war</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
<packagingExcludes>pom.xml</packagingExcludes>
<warName>icb-liberty-war</warName>
<fileNameMapping>no-version</fileNameMapping>
</configuration>
</plugin>
</plugins>
</build>
</project>
Is there any Spring support for wedhdfs? I didnt find any useful link on google.
I want to connect to hadoop with normal authentication and kerberos authentication via webhdfs. Is this supported in spring?
Any useful links will be helpful.
Thanks
Yes, Spring Data supports this. According to this documentation, it's possible to configure any supported Hadoop file system:
http://docs.spring.io/spring-hadoop/docs/current/reference/html/fs.html
SHDP does not enforce any specific protocol to be used - in fact, as
described in this section any FileSystem implementation can be used,
allowing even other implementations than HDFS to be used.
See below for a code sample that demonstrates auto-wiring a WebHDFS FileSystem instance into a command-line application. To run this, pass file paths as command line arguments, and it will list every file present at that path by calling FileSystem.listStatus.
The code sample is configured to connect to an unsecured WebHDFS instance with "simple" authentication. To connect to a WebHDFS instance secured with Kerberos, you'd set up the relevant configuration properties in the <hdp:configuration id="hadoopConfiguration" /> bean. Hadoop security configuration is a very large topic. Rather than repeat the information, I'll just point to the documentation in Apache:
http://hadoop.apache.org/docs/r2.4.1/hadoop-project-dist/hadoop-common/SecureMode.html
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test-spring-hadoop</groupId>
<artifactId>test-webhdfs</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Test Spring Hadoop with WebHDFS</name>
<description>Test Spring Hadoop with WebHDFS</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.0.RELEASE</version>
</parent>
<repositories>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/libs-release</url>
</repository>
</repositories>
<properties>
<start-class>testwebhdfs.Main</start-class>
<java.version>1.6</java.version>
<hadoop.version>2.4.1</hadoop.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-hadoop</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>${hadoop.version}</version>
</dependency>
</dependencies>
</project>
src/main/resources/hadoop-context.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:hdp="http://www.springframework.org/schema/hadoop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/hadoop http://www.springframework.org/schema/hadoop/spring-hadoop.xsd">
<hdp:configuration id="hadoopConfiguration" />
<hdp:file-system uri="webhdfs://localhost:50070" />
</beans>
src/main/java/testwebhdfs/Main.java
package testwebhdfs;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
#Configuration
#ImportResource("hadoop-context.xml")
public class Main implements CommandLineRunner {
#Autowired
private FileSystem fs;
#Override
public void run(String... strings) throws Exception {
Path[] paths = new Path[strings.length];
for (int i = 0; i < strings.length; ++i) {
paths[i] = new Path(strings[i]);
}
for (FileStatus stat: fs.listStatus(paths)) {
System.out.println(stat.getPath());
}
}
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
I added an aspect to a working Spring+Wicket application to log thrown exceptions, and now I get the following error whenever I load the Report page:
ERROR | 2013-12-09 08:42:06,149 | qtp1559334851-16 | DefaultExceptionMapper:123 - Unexpected error occurred
org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor 'public org.jonblack.ReportPage() throws java.lang.Exception'. An exception has been thrown during construction!
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:194)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:67)
...
Caused by: java.lang.IllegalStateException: bean of type [org.jonblack.ReportController] not found
at org.apache.wicket.spring.injection.annot.AnnotProxyFieldValueFactory.getBeanNameOfClass(AnnotProxyFieldValueFactory.java:236)
at org.apache.wicket.spring.injection.annot.AnnotProxyFieldValueFactory.getBeanName(AnnotProxyFieldValueFactory.java:179)
...
I'm using java configuration for the project, so there is no applicationContext.xml. All configuration is done via annotations, the bulk of which are in AppConfig.java.
All the code for my application is shown below. I've left out the HTML templates and HomePage as they aren't integral to the problem.
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>org.jonblack</groupId>
<artifactId>sw-p2</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<!-- TODO project name -->
<name>sw-p2</name>
<description></description>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<properties>
<aspectj.version>1.7.4</aspectj.version>
<spring.version>3.2.4.RELEASE</spring.version>
<wicket.version>6.11.0</wicket.version>
<jetty.version>7.6.3.v20120416</jetty.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- WICKET DEPENDENCIES -->
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-core</artifactId>
<version>${wicket.version}</version>
</dependency>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-extensions</artifactId>
<version>${wicket.version}</version>
</dependency>
<dependency>
<groupId>org.wicketstuff</groupId>
<artifactId>wicketstuff-annotation</artifactId>
<version>${wicket.version}</version>
</dependency>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-spring</artifactId>
<version>${wicket.version}</version>
</dependency>
<!-- Spring dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</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-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- aspectj -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- LOGGING DEPENDENCIES - LOG4J -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<!-- JUNIT DEPENDENCY FOR TESTING -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!-- JETTY DEPENDENCIES FOR TESTING -->
<dependency>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-all-server</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<filtering>false</filtering>
<directory>src/main/resources</directory>
</resource>
<resource>
<filtering>false</filtering>
<directory>src/main/java</directory>
<includes>
<include>**</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<testResources>
<testResource>
<filtering>false</filtering>
<directory>src/test/resources</directory>
</testResource>
<testResource>
<filtering>false</filtering>
<directory>src/test/java</directory>
<includes>
<include>**</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
<plugins>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty.version}</version>
<configuration>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8080</port>
<maxIdleTime>3600000</maxIdleTime>
</connector>
<connector implementation="org.eclipse.jetty.server.ssl.SslSocketConnector">
<port>8443</port>
<maxIdleTime>3600000</maxIdleTime>
<keystore>${project.build.directory}/test-classes/keystore</keystore>
<password>wicket</password>
<keyPassword>wicket</keyPassword>
</connector>
</connectors>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
</configuration>
</plugin>
</plugins>
</build>
</project>
AppConfig.java
package org.jonblack;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.Executor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ComponentScan;
//import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
#Configuration
#ComponentScan("org.jonblack")
#EnableAsync
#EnableAspectJAutoProxy()
public class AppConfig {
private static final Logger log = LoggerFactory.getLogger(AppConfig.class);
#Bean
public ReportController reportController() {
log.info("Getting ReportController");
return new ReportController();
}
#Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setCorePoolSize(5);
pool.setMaxPoolSize(10);
pool.setWaitForTasksToCompleteOnShutdown(true);
return pool;
}
#Bean
public ExceptionLoggingAspect exceptionLoggingAspect() {
return new ExceptionLoggingAspect();
}
#Bean
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
AnnotationAwareAspectJAutoProxyCreator aop = new AnnotationAwareAspectJAutoProxyCreator();
return aop;
}
}
ExceptionLoggingAspect.java
package org.jonblack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class ExceptionLoggingAspect {
private static final Logger LOG = LoggerFactory.getLogger(ExceptionLoggingAspect.class);
#AfterThrowing(pointcut="execution(* org.jonblack.ReportController.getReportData(..))", throwing="ex")
public void afterThrowing(Throwable ex) {
LOG.error(ex.getMessage());
}
}
ReportController.java
package org.jonblack;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Controller;
#Controller
public class ReportController {
private static final Logger log = LoggerFactory.getLogger(ReportController.class);
#Autowired
private ThreadPoolTaskExecutor taskExecutor;
#Async
public Future<String> getReportData() throws Exception {
log.info("Entered into getReportData()");
try {
log.info("Throwing an exception");
throw new Exception("Something went wrong");
} catch(Exception ex) {
log.error("In catch block: {}", ex.getMessage());
}
final Future<String> result = taskExecutor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
return "not a fancy result";
}
});
log.info("Returning from getReportData()");
return result;
}
}
ReportPage.java
package org.jonblack;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.wicketstuff.annotation.mount.MountPath;
#MountPath("report")
public class ReportPage extends WebPage {
private static final Logger log = LoggerFactory.getLogger(ReportPage.class);
#SpringBean
ReportController reportController;
public ReportPage() throws Exception {
log.info("Starting ReportPage");
reportController.getReportData();
}
}
WicketApplication.java
package org.jonblack;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
import org.wicketstuff.annotation.scan.AnnotatedMountScanner;
public class WicketApplication extends WebApplication
{
#Override
public Class<? extends WebPage> getHomePage()
{
return HomePage.class;
}
#Override
public void init()
{
super.init();
// Spring
getComponentInstantiationListeners().add(
new SpringComponentInjector(this));
// Annotation-driven page mounting
new AnnotatedMountScanner().scanPackage("org.jonblack").mount(this);
}
}
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>sw-p2</display-name>
<!-- Configuration loading -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.jonblack.AppConfig</param-value>
</context-param>
<!-- Spring -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- Wicket -->
<filter>
<filter-name>wicket.sw-p2</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>org.jonblack.WicketApplication</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>wicket.sw-p2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
I've followed the Spring reference for Aspects but it's very thin on the ground when it comes to java configurations (and I do find the reference to be quite hard to follow).
I've also done the obligatory DuckDuckGo search and found only references to XML configurations.
On stackoverflow itself I have found this post which explains the same problem, but the cause in that instance was an incorrect annotation and incorrectly named applicationContext.xml file: neither of these helped resolve my situation. I tried using #Autowired instead of #SpringBean, and got the same NullPointerException. Given that the linked post resolved it without this change, I assume this isn't the right path to take.
The problem lies in your configuration.
#Bean
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
AnnotationAwareAspectJAutoProxyCreator aop = new AnnotationAwareAspectJAutoProxyCreator();
return aop;
}
This bean leads to creation of a proxy of a proxy. The #EnableAspectJAutoProxy annotation already registers an AutoProxyCreator and due to the existence of multiple, different instances, this will lead to proxy duplication.
Next to that the additional declaration of your aspect might lead to 2 aspects being instantiated.
#Bean
public ExceptionLoggingAspect exceptionLoggingAspect() {
return new ExceptionLoggingAspect();
}
Your #Aspect is also an #Component and as such will be detected by the #ComponentScan functionality.
Basically removing both beans should fix your problem.
public Future<String> getReportData() throws Exception {
log.info("Entered into getReportData()");
try {
log.info("Throwing an exception");
throw new Exception("Something went wrong");
} catch(Exception ex) { // This catch blocks swallows the exception
log.error("In catch block: {}", ex.getMessage());
}
}
Next to your configuration problems, you also have a problem with your code. Basically your aspect is useless. You have a try/catch block in your code which swallows the Exception. This swallowing leads to a situation where your aspect never sees the exception and will never trigger. From your aspects point of view the exception never happened.
Either don't catch and simply let the Exception bubble up the stack or rethrow the Exception.
I'm relatively new to maven and have been struggling with attached tests, I've found a few articles here that have got me part of the way there but can't quite get that last little bit. Here is what I'm trying to do. I have 2 modules one that defines a set of interfaces and rudimentary test of those interfaces. The second module provides an implementation of the interface and I'd like to run the predefined test on it. I boiled it down to a simple example, here are the two projects:
interface
+ pom.xml
+ src
+ main
+ java
+ demo
+ Messenger.java
+ test
+ java
+ demo
+ MessengerTest.java
impl
+ pom.xml
+ src
+ main
+ java
+ demo
+ impl
+ MessengerImpl.java
+ test
+ resources
+ context.xml
The interface 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">
<groupId>demo</groupId>
<artifactId>interface</artifactId>
<version>1.0</version>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
The Messenger.java source:
package demo;
public interface Messenger {
String getMessage();
}
The MessengerTest.java source:
package demo;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import demo.Messenger;
public class MessengerTest {
private BeanFactory beanfactory;
#Before
public void setUp() throws Exception {
beanfactory = new ClassPathXmlApplicationContext("context.xml");
}
#Test
public final void testGetMessage() throws Exception {
final Messenger msngr = beanfactory.getBean(Messenger.class);
String msg = msngr.getMessage();
assertNotNull(msg);
assertTrue(msg.length() > 0);
}
}
Executing 'mvn install' appears to do the right thing creating interface-1.0.jar and interface-1.0-tests.jar in my local repository.
The implementation code is simple, the 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">
<groupId>demo</groupId>
<artifactId>impl</artifactId>
<version>1.0</version>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>demo</groupId>
<artifactId>interface</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>demo</groupId>
<artifactId>interface</artifactId>
<version>1.0</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
</project>
The MessageImpl.java source:
package demo.impl;
import demo.Messenger;
public class MessengerImpl implements Messenger {
#Override
public String getMessage() {
return "Hello World";
}
}
And finally, the spring context file:
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="MyMessenger" class="demo.impl.MessengerImpl"/>
</beans>
With all of this in place I execute 'mvn -Dtest=demo.MessengerTest test', and unfortunately it fails with "... No tests were executed!". So there is the problem.
Sorry, for being so long winded but I wanted to be fairly complete, any guidance would be greatly appreciated.
Surefire doesn't scan through the classpath when deciding what classes to run, so only tests defined in the same module are normally considered. It checks in target/classes in the impl project, doesn't see any tests, and ignores MessengerTest. You could define a test suite in the impl project that references the tests to run, or unzip the dependency into target/classes.