JUnit Testing EJB layer with embedded glassfish and Maven - java

I have an existing JEE Maven and Eclipse project:
mainProject.ear
+--project1.war
+--project2.war
+--ejb-proj.jar
I would like to have a test profile for unit testing the EJB project, including read/write database with JPA.
I have added a dependency in my pom.xml like this:
<!-- Embedded glassfish -->
<plugin>
<groupId>org.glassfish</groupId>
<artifactId>maven-embedded-glassfish-plugin</artifactId>
<version>3.0-74b</version>
<configuration>
<goalPrefix>embedded-glassfish</goalPrefix>
<port>8080</port>
<autoDelete>true</autoDelete>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
</dependencies>
Then I have created a test class:
#Before
public void setup() {
// instantiate container and context
ejbContainer = EJBContainer.createEJBContainer();
logger.info("Opening the container");
ctx = ejbContainer.getContext();
}
These are the Maven goals, in Eclipse "skip test" is unflagged:
clean compile package
Glassfish is correctly started but I get an error about missing jdbc driver.
Class name is wrong or classpath is not set for : com.mysql.jdbc.jdbc2.optional.MysqlDataSource
So, these are the questions:
Why is the mysql dependency in embedded glassfish ignored ?
Is it correct to start the embedded container from the test class ? Maybe it would be better to have it started during the test phases.
In the end I want the container to be initialized only for the ejb test, so I suppose I have to deploy the ejb jar only. How can I do that ?
For completeness, the same maven goals with skip test = true just work. And the .ear deployed in a running container works too.

Related

Neo4j-harness throws java noclassdeffound exception for Scala.Serializable

When attempting to test a neo4j server using neo4j-harness, I get a noclassdeffound exception when building the embedded Neo4j server
private final Neo4j embeddedNeo4jServer = Neo4jBuilders.newInProcessBuilder()
.withDisabledServer()
.withFixture("")
.build(); // exception here
My pom.xml looks like this:
<dependencies>
<!-- Core Dependencies -->
<dependency><groupId>org.neo4j.driver</groupId><artifactId>neo4j-java-driver</artifactId><version>4.4.5</version></dependency>
<dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-streams</artifactId><version>3.0.0</version></dependency>
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-x-discovery</artifactId><version>4.2.0</version></dependency>
<dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>20211205</version></dependency>
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.30</version></dependency>
<!-- Test Dependencies -->
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.8.2</version><scope>test</scope></dependency>
<dependency><groupId>org.skyscreamer</groupId><artifactId>jsonassert</artifactId><version>1.5.0</version><scope>test</scope></dependency>
<dependency><groupId>org.neo4j.test</groupId><artifactId>neo4j-harness</artifactId><version>4.4.5</version><scope>test</scope></dependency>
<!-- Spring dependencies for an embedded Kafka instance -->
<dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId><version>2.8.3</version><scope>test</scope></dependency>
<dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka-test</artifactId><scope>test</scope><version>2.8.3</version></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><version>2.6.4</version>
<exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency>
<!-- Mockito dependencies - NOTE: the inline dependency replaces the core one, but might be removed in future versions-->
<!--<dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>4.4.0</version><scope>test</scope></dependency>-->
<dependency><groupId>org.mockito</groupId><artifactId>mockito-junit-jupiter</artifactId><version>4.4.0</version><scope>test</scope></dependency>
<dependency><groupId>org.mockito</groupId><artifactId>mockito-inline</artifactId><version>4.4.0</version><scope>test</scope></dependency>
</dependencies>
There is a clash in the version of scala-library used in spring-kafka-test and neo4j-harness.
To resolve this, you can exclude the scala dependency from spring-kafka-test, meaning the neo4j-harness version will be used for both.
To do this, add an exclusion in the pom.xml:
<dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka-test</artifactId><scope>test</scope><version>2.8.3</version>
<exclusions><exclusion><groupId>org.scala-lang</groupId><artifactId>scala-library</artifactId></exclusion></exclusions></dependency>

zookeeper jar in $HOME/.ivy2/jars for java application

My application is failing because of the following issue :
Source '/.../.ivy2/jars/org.apache.zookeeper_zookeeper-3.4.6.jar' does not exist
But I see, there exists a jar in that folder with "tests" suffix - org.apache.zookeeper_zookeeper-3.4.6-tests.jar
If I remove -tests from the name manually, the application runs fine.
I need to understand how can I place the jar my application is expecting in .ivy folder through my program/dependency.
Also, when are the all jars loaded in .ivy/jars folder, is it during the build?
I am using java with maven.
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
<type>pom</type>
</dependency>
add this to your maven dependencies also the org.apache.zookeeper_zookeeper-3.4.6-tests.jar is for the test environment.

How to deploy a module in an Alfresco deployed in Tomcat

I have successfully deployed alfresco community 4.2.f in a Tomcat 7.0.59 with a database MySQL5.6 and jdk1.8.0_141
No problems thus far, now, I got a module developed by our company which I need to be deployed in alfresco. This module invokes a WS which will send a PDF to some place.
I got this module in a jar compiled with jdk1.8.0_141
I tried to put it inside the alfresco.war before deployment in Tomcat in WEB-INF/lib but when I do that and deploy with startup.bat from Tomcat it pops in the console
instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/codehaus/xfire/XFireRuntimeException
I understand this exception is caused by putting the jar inside the war.
I was told that the jar was compiled also in jdk8.
Also, tell you that if instead of this jar I put inside the alfresco.war in WEB-INF/classes a properties file to get our database in deployment it works fine.
The problem is when I try to deploy the module.
I saw there are quite tutorials pointing to do something like:
java -jar bin/alfresco-mmt.jar
I can't do that because this is done installing alfresco with its wizard I assume. I did it deploying alfresco in a fresh tomcat installation.
Does anyone know how to deploy our module with the way we deployed alfresco? Thank you.
You have two ways to install your amp :
The first traditional one :
This is the one installed with the apply amp procédure (alfresco-mmt).
To me, this is not true that it is not compatible with your installation. You can easily find the bin folder (containing the alfresco-mmt.jar file) here in the alfresco packaging : https://download.alfresco.com/release/community/4.2.f-build-00012/alfresco-community-4.2.f.zip
When you have it, you can follow the documentation : http://docs.alfresco.com/4.2/tasks/amp-install.html
And apply your amp for example following this way :
java -jar alfresco-mmt.jar install <AMPFileLocation> <WARFileLocation>
The second one :
You can recreate the war with the alfresco sdk and include in the build the module you created.
If you follow this documentation : http://docs.alfresco.com/4.2/tasks/dev-extensions-maven-sdk-tutorials-all-in-one-archetype.html
the war produced in the target folder of the repo part will contain your module, since the pom of this module will contains a dependency to the amp module :
...
<dependencies>
<dependency>
<groupId>${alfresco.groupId}</groupId>
<artifactId>alfresco</artifactId>
<type>war</type>
</dependency>
<!-- Demonstrating the dependency on the repo AMP developed in the 'amp'
module -->
<dependency>
<groupId>x.y.z</groupId>
<artifactId>my-amp</artifactId>
<version>${my-amp.version}</version>
<type>amp</type>
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<!-- Here is can control the order of overlay of your (WAR, AMP, etc.)
dependencies | NOTE: At least one WAR dependency must be uncompressed first
| NOTE: In order to have a dependency effectively added to the WAR you need
to | explicitly mention it in the overlay section. | NOTE: First-win resource
strategy is used by the WAR plugin -->
<overlays>
<!-- Current project customizations -->
<overlay />
<!-- The Alfresco WAR -->
<overlay>
<groupId>${alfresco.groupId}</groupId>
<artifactId>alfresco</artifactId>
<type>war</type>
<!-- To allow inclusion of META-INF -->
<excludes />
</overlay>
<!-- Add / order your AMPs here -
<overlay>
<groupId>x.y.z</groupId>
<artifactId>my-amp</artifactId>
<type>amp</type>
</overlay>
</overlays>
</configuration>
</plugin>
</plugins>
</build>

JAX-RS does not work with Spring Boot 1.4.1

I am trying to develop a simple JAX-RS based web service using Spring Boot version 1.4.1.RELEASE. However getting this exception -
java.lang.IllegalStateException: No generator was provided and there is no default generator registered
at org.glassfish.hk2.internal.ServiceLocatorFactoryImpl.internalCreate(ServiceLocatorFactoryImpl.java:308) ~[hk2-api-2.5.0-b05.jar:na]
at org.glassfish.hk2.internal.ServiceLocatorFactoryImpl.create(ServiceLocatorFactoryImpl.java:268) ~[hk2-api-2.5.0-b05.jar:na]
at org.glassfish.jersey.internal.inject.Injections._createLocator(Injections.java:138) ~[jersey-common-2.23.2.jar:na]
at org.glassfish.jersey.internal.inject.Injections.createLocator(Injections.java:123) ~[jersey-common-2.23.2.jar:na]
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:330) ~[jersey-server-2.23.2.jar:na]
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:392) ~[jersey-container-servlet-core-2.23.2.jar:na]
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:177) ~[jersey-container-servlet-core-2.23.2.jar:na]
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:369) ~[jersey-container-servlet-core-2.23.2.jar:na]
Here are my program details -
Dependencies included in POM.xml -
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
And here is JerseyConfig file -
package com.test.main;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;
import com.test.resources.TutorialResource;
#Component
public class JerseyConfig extends ResourceConfig{
public JerseyConfig() {
register(TutorialResource.class);
packages("com.test.resources");
}
}
Important: Looks like this issue is not present in most recent versions of Spring Boot. However the content of this answer can still be used as a guide when you want to create an application with Spring Boot and Jersey.
The layout of the JAR has changed in Spring Boot 1.4.1
The layout of executable jars has changed in Spring Boot 1.4.1: application’s dependencies are now packaged in BOOT-INF/lib rather than lib, and application’s own classes are now packaged in BOOT-INF/classes rather than the root of the jar. And it affects Jersey:
Jersey classpath scanning limitations
The change to the layout of executable jars means that a limitation in Jersey’s classpath scanning now affects executable jar files as well as executable war files. To work around the problem, classes that you wish to be scanned by Jersey should be packaged in a jar and included as a dependency in BOOT-INF/lib. The Spring Boot launcher should then be configured to unpack those jars on start up so that Jersey can scan their contents.
I've found that registering classes instead of packages works. See below the steps to create an application with Spring Boot and Jersey.
Creating a web application with Spring Boot and Jersey
Ensure your pom.xml file declares spring-boot-starter-parent as the parent project:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
You also need the following dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
And the Spring Boot Maven plugin:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
For example purposes, create a Jersey resource class annotated with #Path and define a resource method to handle GET requests, producing text/plain:
#Path("/greetings")
public class GreetingResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
public Response getGreeting() {
return Response.ok("Hello, World!").build();
}
}
Then create a class that extends ResourceConfig or Application to register the Jersey resources and annotated it with #ApplicationPath. Registering classes instead of registering packages works with Spring Boot 1.4.1:
#Component
#ApplicationPath("api")
public class JerseyConfig extends ResourceConfig {
#PostConstruct
private void init() {
registerClasses(GreetingResource.class);
}
}
And finally create a Spring Boot class to execute the application:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
If you want to test this web service, you can use the JAX-RS Client API:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GreetingResourceTest {
#LocalServerPort
private int port;
private URI uri;
#Before
public void setUp() throws Exception {
this.uri = new URI("http://localhost:" + port);
}
#Test
public void testGreeting() {
Client client = ClientBuilder.newClient();
Response response = client.target(uri).path("api").path("greetings")
.request(MediaType.TEXT_PLAIN).get();
String entity = response.readEntity(String.class);
assertEquals("Hello, World!", entity);
}
}
To compile and run the application, follow these steps:
Open a command line window or terminal.
Navigate to the root directory of the project, where the pom.xml resides.
Compile the project: mvn clean compile.
Package the application: mvn package.
Look in the target directory. You should see a file with the following or a similar name: spring-jersey-1.0-SNAPSHOT.jar.
Change into the target directory.
Execute the JAR: java -jar spring-jersey-1.0-SNAPSHOT.jar.
The application should be available at http://localhost:8080/api/greetings.
Note 1: Have a look at the Spring Boot documentation. There's a section dedicated to Jersey.
Note 2: When producing JSON, ensure you have a JSON provider registered. ResourceConfig should take care of that though (just ensure that the dependencies are on the classpath).
Although Jersey cannot scan your classes inside the new version of the fat boot jar, you can achieve the same effect using Spring classpath scanning facilities. This way you can scan a package similarly to ResourceConfig.packages():
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(Provider.class));
scanner.addIncludeFilter(new AnnotationTypeFilter(Path.class));
config.registerClasses(scanner.findCandidateComponents("your.package.to.scan").stream()
.map(beanDefinition -> ClassUtils.resolveClassName(beanDefinition.getBeanClassName(), config.getClassLoader()))
.collect(Collectors.toSet()));
Note: please have a look at the source of org.glassfish.jersey.server.internal.scanning.AnnotationAcceptingListener. This is the stock solution and you can see that it does the same: it scans for classes annotated with #Path or #Provider (but doesn't manage to find anything because of the broken scanning mechanism).
Update:
I had a custom config which didn't extend ResourceConfig but returned an instance of it as a bean.
If you look at the official Spring example, you can insert the code above into the JerseyConfig() constructor (instead of the two register(...) calls). The only difference is that instead of calling config.registerClasses(...) you simply call registerClasses(...) in the constructor.
I think you should annotate your JerseyConfig with #Configuration and not #Component.

Attempting to setup/use mysql datasource with glassfish (using Cargo and Maven). How to deploy mysql connector?

Good evening!
Using Cargo via Maven, I've configured my pom.xml to create an instance of glassfish and then deploy my project to it, before running integration tests. I'm most of the way there, in that I've got my code deployed, I've setup a datasource and a JNDI resource for it, but when I attempt to actually use the resource, I get the following exception:
Wrong class name or classpath for Datasource Object
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
On a regular installation of glassfish, I can easily install the connector, but the installation of glassfish in this case is automated and a new instance is created each time I run the tests.
Is there any way that I can provide the mysql connector, either on a classpath that glassfish can read, or by installing it in the new instance of glassfish that's created each build?
Thanks!
Scouring the docs a little more, I found out that I can do this by providing maven dependencies in the container configuration, like so:
<configuration>
<container>
<containerId>glassfish3x</containerId>
<artifactInstaller>
<groupId>org.glassfish.main.distributions</groupId>
<artifactId>glassfish</artifactId>
<version>${glassfish.version}</version>
</artifactInstaller>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</container>
<configuration>
<properties>
<cargo.datasource.datasource.mysql>
cargo.datasource.jndi=jdbc/MysqlPool|
cargo.datasource.driver=com.mysql.jdbc.Driver|
cargo.datasource.url=jdbc:mysql://localhost/databasename|
cargo.datasource.transactionsupport=LOCAL_TRANSACTION|
cargo.datasource.username=username|
cargo.datasource.password=password
</cargo.datasource.datasource.mysql>
</properties>
</configuration>
</configuration>
Take note of the mysql dependency. It needs to reference a dependency already defined in my project (which, for my project has a scope of "provided"). This works as expected. :)

Categories

Resources