Skip to content

Commit 23eb466

Browse files
author
Tomáš Kraus
authored
PostgreSQL driver support for JPA/Hibernate in native image (helidon-io#2596)
Signed-off-by: Tomas Kraus <Tomas.Kraus@oracle.com>
1 parent baf91a7 commit 23eb466

13 files changed

Lines changed: 540 additions & 4 deletions

File tree

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,4 @@ pipeline {
6767
}
6868
}
6969
}
70-
}
70+
}

dependencies/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
<version.lib.opentracing.grpc>0.2.1</version.lib.opentracing.grpc>
117117
<version.lib.opentracing.tracerresolver>0.1.8</version.lib.opentracing.tracerresolver>
118118
<version.lib.persistence-api>2.2.3</version.lib.persistence-api>
119-
<version.lib.postgresql>42.2.16</version.lib.postgresql>
119+
<version.lib.postgresql>42.2.18</version.lib.postgresql>
120120
<version.lib.prometheus>0.9.0</version.lib.prometheus>
121121
<version.lib.reactive-streams-tck>1.0.3</version.lib.reactive-streams-tck>
122122
<version.lib.reactivestreams>1.0.3</version.lib.reactivestreams>

etc/pods/pgsql.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#
2+
# Copyright (c) 2018, 2020 Oracle and/or its affiliates.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
17+
apiVersion: v1
18+
kind: Pod
19+
metadata:
20+
name: pgsql
21+
spec:
22+
containers:
23+
- name: pgsql
24+
image: postgres
25+
ports:
26+
- containerPort: 5432
27+
env:
28+
- name: POSTGRES_USER
29+
value: "user"
30+
- name: POSTGRES_PASSWORD
31+
value: "password"
32+
- name: POSTGRES_DB
33+
value: "pokemon"

etc/scripts/test-integ-mysql.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ mvn ${MAVEN_ARGS} -f ${WS_DIR}/pom.xml \
5252

5353
# Run tests in Java VM application
5454
(cd tests/integration/jpa && \
55-
mvn ${MAVEN_ARGS} clean verify -Dmysql)
55+
mvn ${MAVEN_ARGS} clean verify \
56+
-Dmaven.test.failure.ignore=true -Dmysql \
57+
-pl model,appl)
5658

5759
# Run tests in native image application
5860
(cd tests/integration/jpa && \
59-
mvn ${MAVEN_ARGS} clean verify -Dmysql -Pnative-image -Dnative-image)
61+
mvn ${MAVEN_ARGS} clean verify \
62+
-Dmaven.test.failure.ignore=true -Dmysql \
63+
-Pnative-image -Dnative-image -pl model,appl)

etc/scripts/test-integ-pgsql.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/bash -ex
2+
#
3+
# Copyright (c) 2018, 2020 Oracle and/or its affiliates.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
set -o pipefail || true # trace ERR through pipes
19+
set -o errtrace || true # trace ERR through commands and functions
20+
set -o errexit || true # exit the script if any statement returns a non-true return value
21+
22+
on_error(){
23+
CODE="${?}" && \
24+
set +x && \
25+
printf "[ERROR] Error(code=%s) occurred at %s:%s command: %s\n" \
26+
"${CODE}" "${BASH_SOURCE}" "${LINENO}" "${BASH_COMMAND}"
27+
}
28+
trap on_error ERR
29+
30+
# Path to this script
31+
if [ -h "${0}" ] ; then
32+
readonly SCRIPT_PATH="$(readlink "${0}")"
33+
else
34+
readonly SCRIPT_PATH="${0}"
35+
fi
36+
37+
# Path to the root of the workspace
38+
readonly WS_DIR=$(cd $(dirname -- "${SCRIPT_PATH}") ; cd ../.. ; pwd -P)
39+
40+
source ${WS_DIR}/etc/scripts/pipeline-env.sh
41+
42+
JAVA_HOME='/tools/graalvm-ce-java11-20.2.0'
43+
PATH="${PATH}:${JAVA_HOME}/bin"
44+
45+
mvn ${MAVEN_ARGS} --version
46+
47+
# Temporary workaround until job stages will share maven repository
48+
mvn ${MAVEN_ARGS} -f ${WS_DIR}/pom.xml \
49+
clean install -e \
50+
-DskipTests \
51+
-Ppipeline
52+
53+
# Run tests in Java VM application
54+
(cd tests/integration/jpa && \
55+
mvn ${MAVEN_ARGS} clean verify \
56+
-Dmaven.test.failure.ignore=true -Dpgsql \
57+
-pl model,appl)
58+
59+
# Run tests in native image application
60+
(cd tests/integration/jpa && \
61+
mvn ${MAVEN_ARGS} clean verify \
62+
-Dmaven.test.failure.ignore=true -Dpgsql \
63+
-Pnative-image -Dnative-image -pl model,appl)

integrations/db/pgsql/pom.xml

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Copyright (c) 2020 Oracle and/or its affiliates.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
18+
<project xmlns="http://maven.apache.org/POM/4.0.0"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
<modelVersion>4.0.0</modelVersion>
22+
<parent>
23+
<groupId>io.helidon.integrations.db</groupId>
24+
<artifactId>helidon-integrations-db-project</artifactId>
25+
<version>2.1.1-SNAPSHOT</version>
26+
</parent>
27+
28+
<artifactId>helidon-integrations-db-pgsql</artifactId>
29+
<name>Helidon Integrations DB PostgreSQL JDBC</name>
30+
<description>JDBC driver for PostgreSQL database with native-image support</description>
31+
32+
<properties>
33+
<spotbugs.skip>true</spotbugs.skip>
34+
<maven.javadoc.skip>true</maven.javadoc.skip>
35+
</properties>
36+
37+
<dependencies>
38+
<dependency>
39+
<groupId>org.postgresql</groupId>
40+
<artifactId>postgresql</artifactId>
41+
<scope>provided</scope>
42+
</dependency>
43+
<dependency>
44+
<groupId>org.graalvm.nativeimage</groupId>
45+
<artifactId>svm</artifactId>
46+
<scope>provided</scope>
47+
</dependency>
48+
<dependency>
49+
<groupId>org.junit.jupiter</groupId>
50+
<artifactId>junit-jupiter-api</artifactId>
51+
<scope>test</scope>
52+
</dependency>
53+
<dependency>
54+
<groupId>org.hamcrest</groupId>
55+
<artifactId>hamcrest-all</artifactId>
56+
<scope>test</scope>
57+
</dependency>
58+
</dependencies>
59+
60+
<profiles>
61+
<profile>
62+
<id>release</id>
63+
<build>
64+
<plugins>
65+
<plugin>
66+
<groupId>org.apache.maven.plugins</groupId>
67+
<artifactId>maven-jar-plugin</artifactId>
68+
<executions>
69+
<execution>
70+
<id>empty-javadoc-jar</id>
71+
<phase>package</phase>
72+
<goals>
73+
<goal>jar</goal>
74+
</goals>
75+
<configuration>
76+
<classifier>javadoc</classifier>
77+
<classesDirectory>${project.build.directory}/javadoc</classesDirectory>
78+
</configuration>
79+
</execution>
80+
</executions>
81+
</plugin>
82+
</plugins>
83+
</build>
84+
</profile>
85+
</profiles>
86+
</project>
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.integrations.db.pgsql;
17+
18+
import java.io.IOException;
19+
import java.io.ObjectInputStream;
20+
import java.io.ObjectOutputStream;
21+
import java.lang.reflect.Field;
22+
import java.util.Properties;
23+
24+
import com.oracle.svm.core.annotate.Alias;
25+
import com.oracle.svm.core.annotate.Delete;
26+
import com.oracle.svm.core.annotate.Substitute;
27+
import com.oracle.svm.core.annotate.TargetClass;
28+
import org.postgresql.ds.common.BaseDataSource;
29+
30+
/**
31+
* Replace serialization code.
32+
*/
33+
@TargetClass(className = "org.postgresql.ds.common.BaseDataSource")
34+
public final class BaseDataSourceSubstitution {
35+
36+
@Alias
37+
private String[] serverNames;
38+
@Alias
39+
private String databaseName;
40+
@Alias
41+
private String user;
42+
@Alias
43+
private String password;
44+
@Alias
45+
private int[] portNumbers;
46+
@Alias
47+
private Properties properties;
48+
49+
/*
50+
* Original PgSQL prototype uses Serialization to create deep clone of BaseDataSource
51+
* class. This replacement makes just shallow copy but it seems to be enough.
52+
* IOException is thrown to match prototype's failures.
53+
*/
54+
/**
55+
* Initialize PgSQL {@code BaseDataSource} from another instance.
56+
*
57+
* @param source source instance
58+
* @throws IOException when any issue with data copying occurs
59+
*/
60+
@Substitute
61+
public void initializeFrom(BaseDataSource source) throws IOException {
62+
final String[] serverNamesSrc = source.getServerNames();
63+
final int[] portNumbersSrc = source.getPortNumbers();
64+
if (serverNamesSrc != null) {
65+
serverNames = new String[serverNamesSrc.length];
66+
for (int i = 0; i < serverNamesSrc.length; i++) {
67+
serverNames[i] = serverNamesSrc[i] != null ? serverNamesSrc[i] : null;
68+
}
69+
} else {
70+
serverNames = null;
71+
}
72+
databaseName = source.getDatabaseName();
73+
user = source.getUser();
74+
password = source.getPassword();
75+
if (portNumbersSrc != null) {
76+
portNumbers = new int[portNumbersSrc.length];
77+
System.arraycopy(portNumbersSrc, 0, portNumbers, 0, portNumbersSrc.length);
78+
} else {
79+
portNumbers = null;
80+
}
81+
try {
82+
Field propertiesField = BaseDataSource.class.getDeclaredField("properties");
83+
boolean propertiesAcc = propertiesField.canAccess(source);
84+
propertiesField.setAccessible(true);
85+
final Properties propertiesSrc = (Properties) propertiesField.get(source);
86+
propertiesField.setAccessible(propertiesAcc);
87+
properties = new Properties();
88+
properties.putAll(propertiesSrc);
89+
} catch (IllegalAccessException | NoSuchFieldException | SecurityException e) {
90+
throw new IOException("Could not initialize Properties class", e);
91+
}
92+
}
93+
94+
/*
95+
* Removing writeBaseObject from original. It shall not be accessible now.
96+
*/
97+
@Delete
98+
protected void writeBaseObject(ObjectOutputStream out) throws IOException {
99+
}
100+
101+
/*
102+
* Removing readBaseObject from original. It shall not be accessible now.
103+
*/
104+
@Delete
105+
protected void readBaseObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
106+
}
107+
108+
/**
109+
* Creates an instance of PgSQL BaseDataSource substitution class.
110+
* For testing purposes only.
111+
*/
112+
BaseDataSourceSubstitution() {
113+
this.serverNames = null;
114+
this.databaseName = null;
115+
this.user = null;
116+
this.password = null;
117+
this.portNumbers = null;
118+
this.properties = null;
119+
}
120+
121+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Substitutions for GraalVM native image for PostgreSQL database driver.
19+
*/
20+
package io.helidon.integrations.db.pgsql;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"classes": [
3+
"org.postgresql.Driver",
4+
"org.postgresql.ds.common.BaseDataSource",
5+
"org.hibernate.dialect.PostgreSQL10Dialect",
6+
"org.hibernate.dialect.PostgreSQL81Dialect",
7+
"org.hibernate.dialect.PostgreSQL82Dialect",
8+
"org.hibernate.dialect.PostgreSQL91Dialect",
9+
"org.hibernate.dialect.PostgreSQL92Dialect",
10+
"org.hibernate.dialect.PostgreSQL93Dialect",
11+
"org.hibernate.dialect.PostgreSQL94Dialect",
12+
"org.hibernate.dialect.PostgreSQL95Dialect",
13+
"org.hibernate.dialect.PostgreSQL9Dialect",
14+
"org.hibernate.dialect.PostgreSQLDialect",
15+
"org.hibernate.dialect.PostgresPlusDialect"
16+
]
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#
2+
# Copyright (c) 2020 Oracle and/or its affiliates.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
17+
Args= --initialize-at-run-time=org.postgresql.sspi.SSPIClient

0 commit comments

Comments
 (0)