How to pass parameters to guicified TestNG test from Surefire Maven plugin? - maven-2

I'm using Maven + Surefire + TestNG + Guice (latest stable ones)
I have "large" test that requires Guice to run.
Basically I'm doing it this way:
#Test(groups = "large")
#Guice(modules = FooLargeTest.Module.class)
public class FooLargeTest {
public static class Module extends AbstractModule {
public void configure() {
bindConstant().annotatedWith(FooPort.class).to(5000);
// ... some other test bindings
}
}
#Inject Provider<Foo> fooProvider;
#Test
public void testFoo() {
Foo foo = fooProvider.get() // here injection of port is done
// it could not be passed to constructor
// ... actual test of foo
}
}
The problem is that FooPort is hardcoded to 5000. It is a Maven property, so the first try was to use next Surefire configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
<systemPropertyVariables>
<fooPort>${foo.port}</fooPort>
</systemPropertyVariables>
</configuration>
</plugin>
And after that request it like System.getProperty("fooPort"). Unfortunately, documentation says, that this is only for JUnit test. At least I could not see this system variable during debugging of a test. I tried forkMode both default one and never, it does not change anything. For TestNG tests it's recommended to make it this way:
<properties>
<property>
<name>fooPort</name>
<value>${foo.port}</value>
</property>
</properties>
But now I should use this property from Guice, so it should be given somehow to GuiceModule, I've tried it next way:
#Test(groups = "large")
#Guice(moduleFactory = FooLargeTest.ModuleFactory.class)
public class FooLargeTest {
public static class ModuleFactory extends AbstractModule {
private final String fooPort = fooPort;
#Parameters("fooPort")
public ModuleFactory(String fooPort) {
this.fooPort = fooPort;
}
public Module createModule(final ITestContext context, Class<?> testClass) {
return new AbstractModule {
public void configure() {
bindConstant().annotatedWith(FooPort.class).to(fooPort);
// ... some other test bindings
}
}
}
}
#Inject Provider<Foo> fooProvider;
#Test
public void testFoo() {
Foo foo = fooProvider.get() // here injection of port is done
// actual test of foo
}
}
But this way was also a failure as creator for modulefactories does not take #Parameters into account and thus could not create instance of a factory.
Looks like I should try to get some data from ITestContext context, but I do not know how and if the data is there or if there is some simpler way to do what I want.
Thanks for a response.

I just ran a quick test and properties seem to be passed correctly to TestNG:
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng-single.yaml</suiteXmlFile>
</suiteXmlFiles>
<systemPropertyVariables>
<foo>bar</foo>
</systemPropertyVariables>
My suite file calls the test class B, which contains:
#Test
public void f() {
System.out.println(" property:" + System.getProperty("foo"));
}
and running it with Maven shows:
property:bar
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.358 sec
I'm not using Guice in this simple example but that's the only difference between your code and mine.
Feel free to create a small Maven project reproducing your problem, make sure that I can compile it and then email it to me.

I tried below test and works fine
My Pom file
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<!--<groups>Regression</groups> -->
<systemPropertyVariables>
<environment>UAT</environment>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
My TestNG test
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class TestAuthentication {
#Test (groups = { "Sniff", "Regression" })
public void validAuthenticationTest(){
System.out.println(" property:" + System.getProperty("environment"));
}
#Test (groups = { "Regression" },parameters = {"environment"})
public void failedAuthenticationTest(String environment){
System.out.println("Regression-"+environment);
}
#Parameters("environment")
#Test (groups = { "Sniff"})
public void newUserAuthenticationTest(String environment){
System.out.println("Sniff-"+environment);
}
}

Related

AspectJ is not working on beans without interface and defined in the configuration class

I created a demo application to reproduce it:
DemoService
open class DemoService {
fun test() {
println("test function is executed.")
}
}
DemoAspect
#Aspect
class DemoAspect {
#Around("execution(* com.example.demo.service.DemoService.test(..))")
fun testAspect(joinPoint: ProceedingJoinPoint) {
println("before test function.")
joinPoint.proceed()
println("after test function.")
}
}
AppConfig
#Configuration
#EnableAspectJAutoProxy
class AppConfig {
#Bean
fun demoService() = DemoService()
#Bean
fun demoAspect() = DemoAspect()
}
SpringDemoApplication
#SpringBootApplication
#Import(AppConfig::class)
class SpringDemoApplication
fun main(args: Array<String>) {
val context = runApplication<SpringDemoApplication>(*args)
val demoService = context.beanFactory.getBean(DemoService::class.java)
demoService.test()
}
Execution result:
test function is executed.
The aspect is not working which is not expected.
I tried following variations and they worked correctly:
Remove the beans in configuration services and register beans by annotations
DemoService
#Service
open class DemoService {
...
}
AppConfig
#Configuration
#EnableAspectJAutoProxy
class AppConfig {
#Bean
fun demoAspect() = DemoAspect()
}
Let DemoService implements an interface
DemoService
interface DemoService {
fun test()
}
open class DemoServiceImpl: DemoService {
override fun test() {
println("test function is executed.")
}
}
AppConfig
#Configuration
#EnableAspectJAutoProxy
class AppConfig {
#Bean
fun demoService() = DemoServiceImpl()
#Bean
fun demoAspect() = DemoAspect()
}
I want to understand why the AspectJ is not working on this combination:
The target bean is not implementing any interface.
The bean is registered in Configuration class.
Spring AOP, in contrast to native AspectJ, is based on dynamic proxies. In order to proxy a class, it must not be final. In Kotlin terms, it must be open. Moreover, in order to proxy a method, it must not be final either, i.e. you also need to open the method. See also this Baeldung tutorial.
So, please use open fun test(), then it works as expected.
Update for follow-up question:
why it works if I use #Service even though the function is final?
Because probably in your build you use the Kotlin all-open compiler plugin with Spring support enabled. If I were you, I would not use #Bean factory methods anyway, but simply #Component, #Service or similar Spring annotations directly on the implementation classes.
Of course, you could also use the generic all-open plugin in addition to the Spring version and then do this:
annotation class OpenMe()
#OpenMe
class DemoService {
fun test() {
println("test function is executed.")
}
}
Then, in Maven you would do something like:
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>all-open</plugin>
<plugin>spring</plugin>
</compilerPlugins>
<pluginOptions>
<option>all-open:annotation=org.acme.OpenMe</option>
</pluginOptions>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
Then you would not need any open keywords on the service class or method anymore and could continue to use your #Bean factory method. But I think this is more complicated than using Spring annotations - convention over configuration.

Kotlin get declared member property value

What is the equivalent code of Class#getDeclaredField in Kotlin? I'm looking for a pure Kotlin implementation... a reflection perhaps?
class Test {
public static final String TEST = "Hello";
public static void main(String[] args) {
System.out.println(
Test.class.getDeclaredField("TEST").get(Test.class));
}
}
first, add this dependency to avoid runtime error
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>1.3.50</version>
</dependency>
then:
val member = Test::class.members.find { it.name=="TEST" }
println(member)
println(member.call(Test())
output:
val generic.Test.TEST: kotlin.String
Hello
member type is Kcallable<*>?
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-callable/index.html

Spring Cloud Contract EXPLICIT and WEBTESTCLIENT testMode

I want to use Spring Cloud Contract to produce my contracts and verify them. I want to use Spring WebFlux and Junit5. This is my Controller:
#RestController
#Slf4j
public class HelloWorldPortRESTAdapter implements HelloWorldPort {
#GetMapping(value = "/hello-world", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
#Override
public Mono<String> helloWorld() {
return Mono.just("Hello World!");
}
}
This is cloud contract maven plugin configuration:
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<basePackageForTests>com.example.feedproviderapi.contract</basePackageForTests>
<testFramework>JUNIT5</testFramework>
<testMode>EXPLICIT</testMode>
</configuration>
</plugin>
But i don't know how base test class should look like. I tried this:
#ExtendWith(SpringExtension.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BaseTestClass {
#LocalServerPort
private int port;
#BeforeEach
void setup(){
RestAssured.baseURI = "http://localhost:" + this.port;
}
}
When I run mvn clean install, it returns java.net.ConnectException: Connection refused (Connection refused)
Then I changed testMode property in maven plugin to WEBTESTCLIENT and updated BaseTestClass like this:
#ExtendWith(SpringExtension.class)
#SpringBootTest
public class BaseTestClass {
#Autowired
WebApplicationContext context;
#BeforeEach
void setup(){
RestAssuredWebTestClient.standaloneSetup(context);
}
}
And again when I run mvn clean install now it returns:
You haven't configured a WebTestClient instance. You can do this statically
RestAssuredWebTestClient.mockMvc(..)
RestAssuredWebTestClient.standaloneSetup(..);
RestAssuredWebTestClient.webAppContextSetup(..);
or using the DSL:
given().
mockMvc(..). ..
Btw I tried RestAssuredWebTestClient.standaloneSetup(new HelloWorldPortRESTAdapter()); as well in my BaseTestClass but the result is same.
So how should I implement BaseTestClass regarding EXPLICIT and WEBTESTCLIENT testModes?
I have struggled for 3 days, to makes RestAssuredWebTestClient works.
Thanks a llooottt for : https://www.baeldung.com/spring-5-webclient
That's how i could do that:
#WebFluxTest
public class AnimeControllerIntegrTest{
WebTestClient testClient;
#Test
public void get_RA() {
testClient = WebTestClient.bindToServer().baseUrl("http://localhost:8080/animes").build();
RestAssuredWebTestClient
.given()
.webTestClient(testClient)
.when()
.get()
.then()
.statusCode(OK.value())
.body("name" ,hasItem("paulo"))
;
}
}
Please check the spring cloud contract samples https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/producer_webflux_webtestclient
And junit5
https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer_with_junit5
The
plugin
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<packageWithBaseClasses>com.example</packageWithBaseClasses>
<testMode>WEBTESTCLIENT</testMode>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<failIfNoTests>true</failIfNoTests>
</configuration>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${junit-platform-surefire-provider.version}</version>
</dependency>
</dependencies>
</plugin>
And The base class for junit5
public abstract class BeerRestBase {
#BeforeEach
public void setup() {
// remove::start[]
RestAssuredWebTestClient.standaloneSetup(new ProducerController(personToCheck -> personToCheck.age >= 20));
// remove::end[]
}
}
Try passing an ApplicationContext instance instead of WebApplicationContext.

force glassfish 4 to use jackson 2.3

I wrote an maven application which should run on Glassfish 4.
The Standard ApplicationConfig looks like this:
#javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
// following code can be used to customize Jersey 2.0 JSON provider:
try {
Class jsonProvider = Class.forName("org.glassfish.jersey.jackson.JacksonFeature");
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(getClass().getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
addRestResourceClasses(resources);
return resources;
}
The problem now is, that my resources which generate Json should use jackson 2.3 annotations.
But my glassfish uses some codehaus. ... packages to provide json. codehaus is the old version of jackson. I want to use the new one from fasterxml which provides the #JsonIdentityInfo annotation.
I thought that i could solve my problem by writing:
#javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(JacksonFeatures.class); //from the com.fasterxml.jackson.jaxrs.annotation Package
resources.add(JacksonJaxbJsonProvider.class);
resources.add(JacksonJsonProvider.class);
addRestResourceClasses(resources);
return resources;
}
But no effect. Now Glassfish uses the standard JsonProvider Moxy... which i dont want to use. Do you have any tips how i can force glassfish to use my library instead of the buildin-libraries? Or can i change the buildin library to the newer one?
And if you know how to solve this. could you please provide a little code-snippet?
EDIT 1:
After trying the first approach to solve it:
new ApplicationConfig:
#javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
//register( new GZipEncoder() );
register( JacksonFeature.class );
}
private void addMyResources() {
//a lot of resources.
}
}
JacksonFeature:
public class JacksonFeature implements Feature {
public boolean configure( final FeatureContext context ) {
String postfix = '.' + context.getConfiguration().getRuntimeType().name().toLowerCase();
context.property( CommonProperties.MOXY_JSON_FEATURE_DISABLE + postfix, true );
context.register( JsonParseExceptionMapper.class );
context.register( JsonMappingExceptionMapper.class );
context.register( JacksonJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class );
return true;
}
}
pom:
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.4</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.4</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>
Dependencies:
http://i.stack.imgur.com/uA4V2.png
Error:
SEVERE: Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:403)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:325)
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:177)
...
or
SEVERE: Exception while loading the app
SEVERE: Undeployment failed for context /blueserver
INFO: file:/C:/bluetrail/blueserver/target/blueserver-0.0.0.1/WEB-INF/classes/_de.bluetrail_blueserver_war_0.0.0.1PU logout successful
SEVERE: Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [IterableProvider<InjectionResolver<Object>>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 2 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.internal.inject.JerseyClassAnalyzer(#Named ClassAnalyzer, IterableProvider<InjectionResolver<Object>>)]
EDIT 2:
i will now post some classes of my project. In that classes i included all Annotations that i use.
i have like 16 entities like that:
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
#Entity
#JsonIdentityInfo(generator = ObjectIdGenerators.None.class, property = "id", scope=Address.class)
//the JsonIdentityInfo is the reason i need Jackson 2
public class Address implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String postalCode;
private String city;
private String country;
private String street;
private String houseNumber;
#Embedded
private Coordinate coordinate;
//getters, setters , etc.
}
then i have a lot of DAO's like that:
import de.ibs.trail.entity.Address;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
#Stateless
public class AddressDao extends GenericDao {
public Address getAddress(long id){
return em.find(Address.class, id);
}
public List<Address> getAddresses(){
List<Address> address = em.createQuery("SELECT a FROM Address a", Address.class).getResultList();
return address;
}
}
and finally i have a lot of REssources like that:
import de.bluetrail.blueserver.dao.AddressDao;
import de.ibs.trail.entity.Address;
import java.util.List;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
#Path("dummy")
#Stateless
public class DummyResource {
#Context
private UriInfo context;
#Inject userAuth user;
#Inject addressDao AddressDao;
public DummyResource() {
}
#GET
#Produces("application/json")
public List<Address> getAddress() {
return AddressDao.getAddresses();
}
}
Thats the first part. As a second part i have a class for some Google Services. Because i want to try to use some Google GeoLocation and Routing. I put the Google-Code into a pasteBin file, because its so huge:
http://pastebin.com/u3e0dms6
there i use libraries like:
import com.fasterxml.jackson.databind.ObjectMapper;
import de.ibs.trail.entity.Address;
//some other entities
//...
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Set;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
I hope that helps. All the other classes use the same annotations.
First make sure you have the following in your pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson.version}</version>
</dependency>
Then make sure you DO NOT have this in any pom.xml:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.5</version>
</dependency>
Then you need to disable moxy. The easiest way to do this is to ditch your Application class and replace is with a ResourceConfig class. First lets create YOUR JacksonFeature class:
public class JacksonFeature implements Feature {
public boolean configure( final FeatureContext context ) {
String postfix = '.' + context.getConfiguration().getRuntimeType().name().toLowerCase();
context.property( CommonProperties.MOXY_JSON_FEATURE_DISABLE + postfix, true );
context.register( JsonParseExceptionMapper.class );
context.register( JsonMappingExceptionMapper.class );
context.register( JacksonJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class );
return true;
}
}
Two interesting things here, first I disabled moxy and second I made sure to add the JacksonException mappers. This way you will get better errors than internal server error if there is a parsing or generation exception. Okay, last step it so rewrite your Application as a ResourceConfig class:
#javax.ws.rs.ApplicationPath("resources")
public class RestApplication extends ResourceConfig {
public RestApplication() {
register( new GZipEncoder() );
register( JacksonFeature.class );
}
private void addMyResources() {
register( MyResource1.class );
register( MyResource2.class );
}
}
That should do it. Also, instead of registering the resources one by one like this, if you know their path you can just remove all that code and add this to the constructor of RestApplication:
package( "com.me.myrestresourcespackage" );
Hope this helps.

How to make m2eclipse (Maven) point to the "persistence.xml" path?

I working with Eclipse Helios, m2eclipse Maven plugin and Glassfish plugin.
I edited the "pom.xml" file so that I can get the DerbyClient and the JPA Persistence classes.
<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.apress.javaee6</groupId>
<artifactId>chapter02</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>chapter02</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>10.6.1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<type>maven-plugin</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>EclipseLink Repo</id>
<url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo</url>
</repository>
</repositories>
</project>
Then, I created the "src/main/resrouce" directory and put a "persistence.xml" file that contains:
<xml version="1.0" encoding="UTF-8">
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="chapter02PU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.apress.javaee6.chapter02.Book</class>
<properties>
<property name="eclipselink.target-datababase" value="DERBY"/>
<property name="eclipselink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="eclipselink.jdbc.url" value="jdbc:derby://localhost:1527/chapter02DB;create=true"/>
<property name="eclipselink.jdbc.user" value="APP"/>
<property name="eclipselink.jdbc.password" value="APP"/>
<property name="eclipselink.jdbc.ddl-generation" value="create-tables"/>
<property name="eclipselink.jdbc.logging-level" value="INFO"/>
</properties>
</persistence-unit>
</persistence>
</xml>
Of course, the derby server runs perfectly.
And I have create the following Book Class:
package com.apress.javaee6.chapter02;
import javax.persistence.*;
#Entity
#NamedQuery(name="findAllBooks", query="SELECT b from Book b")
public class Book {
#Id #GeneratedValue
private Long id;
#Column(nullable = false)
private String title;
private float price;
#Column(length = 1000)
private String description;
private String isbn;
private Integer nbOfPage;
private Boolean illustrations;
public Book() {
super();
}
public Book(Long id, String title, float price, String description,
String isbn, Integer nbOfPage, Boolean illustrations) {
super();
this.id = id;
this.title = title;
this.price = price;
this.description = description;
this.isbn = isbn;
this.nbOfPage = nbOfPage;
this.illustrations = illustrations;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public Integer getNbOfPage() {
return nbOfPage;
}
public void setNbOfPage(Integer nbOfPage) {
this.nbOfPage = nbOfPage;
}
public Boolean getIllustrations() {
return illustrations;
}
public void setIllustrations(Boolean illustrations) {
this.illustrations = illustrations;
}
}
The main function is here:
package com.apress.javaee6.chapter02;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
// Create an instance of book
Book book = new Book();
book.setTitle("The Hitchhiker's guide to the Galaxy");
book.setPrice(12.5F);
book.setDescription("Science fiction comedy book");
book.setIsbn("1-84023-742-2");
book.setIllustrations(false);
// Gets an entity manager and a transaction
EntityManagerFactory emf = Persistence.createEntityManagerFactory("chapter02PU");
EntityManager em = emf.createEntityManager();
// Persists the book to the database
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
em.persist(book);
tx.commit();
em.close();
emf.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The problem is that the "persistence.xml" is not recognized.
How can I make Maven point to the "persistence.xml" file?
When I active the Maven console and "Update Dependencies", I got the following (bad) info:
28/06/10 15:20:36 CEST: [INFO] Using 'UTF-8' encoding to copy filtered resources.
28/06/10 15:20:36 CEST: [INFO] skip non existing resourceDirectory /home/zakaria/workspace/chapter02/src/main/resources
28/06/10 15:20:36 CEST: [INFO] Using 'UTF-8' encoding to copy filtered resources.
28/06/10 15:20:36 CEST: [INFO] skip non existing resourceDirectory /home/zakaria/workspace/chapter02/src/test/resources
So i think he tried somewhere to create the "resources" directories and cannot get them after the build.
Thank you so much ;)
Regards
You don't tell maven to "point" on a file, you put files in a directory that end up on the class path. For resources, you're supposed to use src/main/resources.
In other words, just put the persistence.xml in src/main/resources/META-INF.
I'm using m2eclipse 0.10.0 and I don't use any special workaround, it just works for at least 3 projects in my workspace of type jar, ejb and war.
If you're using m2eclipse 0.10.0, not having the resources recognized is a known problem (see m2eclipse user list). There is a workaround described here:
https://docs.sonatype.org/pages/viewpage.action?pageId=2949459
Using maven-resources-plugin version 2.4.2 or 2.4.3 may also work better than 2.4.
According to JPA standard persistence.xml should reside in the root of META-INF folder. So putting in into src/main/resources/META-INF should work