Search code examples
postgresqlopen-libertyjava-ee-8microprofile

How to add Postgres Driver to Open Liberty?


I am implementing a basic REST API with Micorprofile 3.2 and deploying it with Open Liberty.

The server.xml,

<?xml version="1.0" encoding="UTF-8"?>
<server description="${project.name}">

    <featureManager>
        <feature>microProfile-3.2</feature>
        <feature>jpa-2.2</feature>
        <feature>jdbc-4.2</feature>
        <feature>jndi-1.0</feature>
    </featureManager>

    <httpEndpoint id="defaultHttpEndpoint"
                  host="*"
                  httpPort="8080"
                  httpsPort="9443"/>

    <webApplication location="${project.name}.war" contextRoot="/"/>
    <mpMetrics authentication="false"/>

    <dataSource id="DefaultDataSource"
                jndiName="jdbc/postgresql">
        <jdbcDriver jdbcDriverRef="postgresql-driver" libraryRef="postgresql-library"/>
        <properties.postgres serverName="localhost"
                             portNumber="5432"
                             databaseName="postgres"
                             user="postgres"
                             password="postgres"/>
    </dataSource>

    <jdbcDriver id="postgresql-driver"
                javax.sql.XADataSource="org.postgresql.xa.PGXADataSource"
                javax.sql.ConnectionPoolDataSource="org.postgresql.ds.PGConnectionPoolDataSource"
                libraryRef="postgresql-library"/>

    <library id="postgresql-library">
        <fileset id="PostgreSQLFileset" dir="${shared.resource.dir}/jdbc"
                 includes="postgresql-42.2.9.jar"/>
    </library>
</server>

my persistence.xml,

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence">

    <persistence-unit name="jpa-unit" transaction-type="JTA">
        <jta-data-source>jdbc/postgresql</jta-data-source>
    </persistence-unit>
</persistence>

The problem is everytime i try to use a EntityManager i get the following error:

[INFO] [ERROR   ] CWWJP0015E: An error occurred in the org.eclipse.persistence.jpa.PersistenceProvider persistence provider when it attempted to create the container entity manager factory for the jpa-unit persistence unit. The following error occurred: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.7.5.v20191016-ea124dd158): org.eclipse.persistence.exceptions.EntityManagerSetupException
[INFO] Exception Description: Predeployment of PersistenceUnit [jpa-unit] failed.
[INFO] Internal Exception: javax.persistence.PersistenceException: CWWJP0013E: The server cannot locate the java:comp/DefaultDataSource data source for the jpa-unit persistence unit because it has encountered the following exception: javax.naming.NamingException [Root exception is java.sql.SQLNonTransientException: DSRA4000E: No implementations of [javax.sql.XADataSource, javax.sql.ConnectionPoolDataSource, javax.sql.DataSource, java.sql.Driver] are found for dataSource[DefaultDataSource] with library postgresql-library. The name or location of JDBC driver JAR files might be incorrect or inaccessible. Searched in: []. Searched under packages: [].].
[INFO] [ERROR   ] CWOWB1000E: A CDI error has occurred: CWNEN0030E: The server was unable to obtain an object instance for the java:comp/env/xx.xx.demo.micro.pq.infrastructure.infrastructure.EntityManagerProducer/entityManagerFactory reference.  The exception message was: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.7.5.v20191016-ea124dd158): org.eclipse.persistence.exceptions.EntityManagerSetupException
[INFO] Exception Description: Predeployment of PersistenceUnit [jpa-unit] failed.
[INFO] Internal Exception: javax.persistence.PersistenceException: CWWJP0013E: The server cannot locate the java:comp/DefaultDataSource data source for the jpa-unit persistence unit because it has encountered the following exception: javax.naming.NamingException [Root exception is java.sql.SQLNonTransientException: DSRA4000E: No implementations of [javax.sql.XADataSource, javax.sql.ConnectionPoolDataSource, javax.sql.DataSource, java.sql.Driver] are found for dataSource[DefaultDataSource] with library postgresql-library. The name or location of JDBC driver JAR files might be incorrect or inaccessible. Searched in: []. Searched under packages: [].].
[INFO] [ERROR   ] CWOWB1000E: A CDI error has occurred: CWNEN0030E: The server was unable to obtain an object instance for the java:comp/env/xx.xx.demo.micro.pq.infrastructure.infrastructure.EntityManagerProducer/entityManagerFactory reference.  The exception message was: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.7.5.v20191016-ea124dd158): org.eclipse.persistence.exceptions.EntityManagerSetupException
[INFO] Exception Description: Predeployment of PersistenceUnit [jpa-unit] failed.
[INFO] Internal Exception: javax.persistence.PersistenceException: CWWJP0013E: The server cannot locate the java:comp/DefaultDataSource data source for the jpa-unit persistence unit because it has encountered the following exception: javax.naming.NamingException [Root exception is java.sql.SQLNonTransientException: DSRA4000E: No implementations of [javax.sql.XADataSource, javax.sql.ConnectionPoolDataSource, javax.sql.DataSource, java.sql.Driver] are found for dataSource[DefaultDataSource] with library postgresql-library. The name or location of JDBC driver JAR files might be incorrect or inaccessible. Searched in: []. Searched under packages: [].].
[INFO] [WARNING ] CWMOT0009W: The OpenTracing exception mapper detected and is handling an unhandled exception from the JAX-RS application. 
[INFO]                                                                                                                java.lang.NullPointerException
[INFO]  at xx.xx.demo.micro.pq.infrastructure.infrastructure.EntityManagerProducer.createEntityManager(EntityManagerProducer.java:21)
[INFO]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[INFO]  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[INFO]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[INFO]  at java.lang.reflect.Method.invoke(Method.java:498)
[INFO]  at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:95)
[INFO]  at [internal classes]
[INFO]  at org.jboss.weldx.persistence.EntityManager$1152902288$Proxy$_$$_WeldClientProxy.getCriteriaBuilder(Unknown Source)
[INFO]  at xx.xx.demo.micro.pq.domain.ProductRepository.findAll(ProductRepository.java:42)
[INFO]  at xx.xx.demo.micro.pq.domain.ProductRepository$Proxy$_$$_WeldClientProxy.findAll(Unknown Source)
[INFO]  at xx.xx.demo.micro.pq.application.ProductResource.getAllProduct(ProductResource.java:54)
[INFO]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[INFO]  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[INFO]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[INFO]  at java.lang.reflect.Method.invoke(Method.java:498)
[INFO]  at com.ibm.ws.jaxrs20.cdi.component.JaxRsFactoryImplicitBeanCDICustomizer.serviceInvoke(JaxRsFactoryImplicitBeanCDICustomizer.java:304)
[INFO]  at [internal classes]

I create the EntityManager the following way:

  @(unitName = "jpa-unit")
  private EntityManagerFactory entityManagerFactory;

  @Produces
  @RequestScoped
  public EntityManager createEntityManager() {
    return entityManagerFactory.createEntityManager();
  }

I dont really understand why open liberty looks in here: Searched in: []. Searched under packages: [].].

EDIT: add pom.xml

<?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">
    <modelVersion>4.0.0</modelVersion>
    <groupId>xx.xxx</groupId>
    <artifactId>demo-micro-pq</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <openliberty.maven.version>3.1</openliberty.maven.version>
        <final.name>demo-micro-pq</final.name>
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <openliberty.version>[19.0.0.9,)</openliberty.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <version.javaee>8.0.1</version.javaee>
        <version.slf4j>1.7.28</version.slf4j>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.eclipse.microprofile</groupId>
            <artifactId>microprofile</artifactId>
            <version>3.2</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>${version.javaee}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.4.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.4.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${version.slf4j}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${version.slf4j}</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>demo-micro-pq</finalName>
    </build>
    <profiles>
        <profile>
            <id>liberty</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>io.openliberty.tools</groupId>
                        <artifactId>liberty-maven-plugin</artifactId>
                        <version>${openliberty.maven.version}</version>
                        <executions>
                            <execution>
                                <id>package-server</id>
                                <phase>package</phase>
                                <goals>
                                    <goal>create</goal>
                                    <goal>install-feature</goal>
                                    <goal>deploy</goal>
                                    <goal>package</goal>
                                </goals>
                                <configuration>
                                    <outputDirectory>target/wlp-package</outputDirectory>
                                </configuration>
                            </execution>
                        </executions>
                        <configuration>
                            <include>runnable</include>
                            <serverName>${final.name}</serverName>
                            <bootstrapProperties>
                                <project.name>${final.name}</project.name>
                                <jwt.issuer>https://server.example.com</jwt.issuer>
                            </bootstrapProperties>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-dependency-plugin</artifactId>
                        <version>3.1.1</version>
                        <executions>
                            <execution>
                                <id>copy</id>
                                <phase>package</phase>
                                <goals>
                                    <goal>copy</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>org.postgresql</groupId>
                                    <artifactId>postgresql</artifactId>
                                    <version>42.2.9</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                            <outputDirectory>liberty/wlp/usr/shared/resources</outputDirectory>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

Solution

  • Dependency plugin 'outputDirectory' must match server.xml directory

    You need to align your server config with the location you copy the dependency to in your Maven build.

    (Your problem seems to be you have an extra 'jdbc' subdir in your server config, compared to the location you're copying into from your Maven build).

    E.g.

    server.xml

    <server>
        <library id="postgresql-library">
            <fileset id="PostgreSQLFileset" dir="${shared.resource.dir}/jdbc"
                     includes="postgresql-42.2.9.jar"/>
        </library>
    </server>
    

    should point to the same directory as:

    pom.xml

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.1</version>
                    <configuration>
                       <outputDirectory>${project.build.directory}/liberty/wlp/usr/shared/resources/jdbc</outputDirectory>
    

    Follow-up note

    Note there is an open issue now where we're discussing different ideas to add support into the liberty-maven-plugin itself for copying dependencies into place.