diff --git a/agroal/deployment/pom.xml b/agroal/deployment/pom.xml
new file mode 100644
index 000000000..9e0b7235a
--- /dev/null
+++ b/agroal/deployment/pom.xml
@@ -0,0 +1,31 @@
+
+
+
+ shamrock-agroal
+ org.jboss.shamrock
+ 1.0.0.Alpha1-SNAPSHOT
+ ../
+
+ 4.0.0
+
+ shamrock-agroal-deployment
+
+
+
+ org.jboss.shamrock
+ shamrock-core-deployment
+
+
+ org.jboss.shamrock
+ shamrock-agroal-runtime
+
+
+ org.jboss.shamrock
+ shamrock-transactions-deployment
+
+
+
+
+
\ No newline at end of file
diff --git a/agroal/deployment/src/main/java/org/jboss/shamrock/agroal/AgroalProcessor.java b/agroal/deployment/src/main/java/org/jboss/shamrock/agroal/AgroalProcessor.java
new file mode 100644
index 000000000..5acb75939
--- /dev/null
+++ b/agroal/deployment/src/main/java/org/jboss/shamrock/agroal/AgroalProcessor.java
@@ -0,0 +1,55 @@
+package org.jboss.shamrock.agroal;
+
+import java.util.function.Function;
+
+import javax.inject.Inject;
+
+import org.jboss.shamrock.agroal.runtime.DataSourceProducer;
+import org.jboss.shamrock.agroal.runtime.DataSourceTemplate;
+import org.jboss.shamrock.deployment.ArchiveContext;
+import org.jboss.shamrock.deployment.BeanDeployment;
+import org.jboss.shamrock.deployment.ProcessorContext;
+import org.jboss.shamrock.deployment.ResourceProcessor;
+import org.jboss.shamrock.deployment.RuntimePriority;
+import org.jboss.shamrock.deployment.buildconfig.BuildConfig;
+import org.jboss.shamrock.deployment.codegen.BytecodeRecorder;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+class AgroalProcessor implements ResourceProcessor {
+
+ @Inject
+ private BeanDeployment beanDeployment;
+
+ @Override
+ public void process(ArchiveContext archiveContext, ProcessorContext processorContext) throws Exception {
+ BuildConfig config = archiveContext.getBuildConfig();
+ BuildConfig.ConfigNode ds = config.getApplicationConfig().get("datasource");
+ if (ds.isNull()) {
+ return;
+ }
+ String driver = ds.get("driver").asString();
+ String url = ds.get("url").asString();
+ if (driver == null) {
+ throw new RuntimeException("Driver is required");
+ }
+ if (url == null) {
+ throw new RuntimeException("Driver is required");
+ }
+ String userName = ds.get("username").asString();
+ String password = ds.get("password").asString();
+
+ processorContext.addReflectiveClass(false, false, driver);
+ beanDeployment.addAdditionalBean(DataSourceProducer.class);
+ try (BytecodeRecorder bc = processorContext.addDeploymentTask(RuntimePriority.DATASOURCE_DEPLOYMENT)) {
+ DataSourceTemplate template = bc.getRecordingProxy(DataSourceTemplate.class);
+ template.addDatasource(null, url, bc.classProxy(driver), userName, password);
+ }
+ }
+
+ @Override
+ public int getPriority() {
+ return 1;
+ }
+}
diff --git a/agroal/deployment/src/main/java/org/jboss/shamrock/agroal/AgroalSetup.java b/agroal/deployment/src/main/java/org/jboss/shamrock/agroal/AgroalSetup.java
new file mode 100644
index 000000000..a97f84a36
--- /dev/null
+++ b/agroal/deployment/src/main/java/org/jboss/shamrock/agroal/AgroalSetup.java
@@ -0,0 +1,11 @@
+package org.jboss.shamrock.agroal;
+
+import org.jboss.shamrock.deployment.SetupContext;
+import org.jboss.shamrock.deployment.ShamrockSetup;
+
+public class AgroalSetup implements ShamrockSetup {
+ @Override
+ public void setup(SetupContext context) {
+ context.addResourceProcessor(new AgroalProcessor());
+ }
+}
diff --git a/agroal/deployment/src/main/resources/META-INF/services/org.jboss.shamrock.deployment.ShamrockSetup b/agroal/deployment/src/main/resources/META-INF/services/org.jboss.shamrock.deployment.ShamrockSetup
new file mode 100644
index 000000000..4c97b5438
--- /dev/null
+++ b/agroal/deployment/src/main/resources/META-INF/services/org.jboss.shamrock.deployment.ShamrockSetup
@@ -0,0 +1 @@
+org.jboss.shamrock.agroal.AgroalSetup
diff --git a/agroal/pom.xml b/agroal/pom.xml
new file mode 100644
index 000000000..e20b48a75
--- /dev/null
+++ b/agroal/pom.xml
@@ -0,0 +1,18 @@
+
+
+
+ shamrock-parent
+ org.jboss.shamrock
+ 1.0.0.Alpha1-SNAPSHOT
+
+ 4.0.0
+
+ shamrock-agroal
+ pom
+
+ deployment
+ runtime
+
+
\ No newline at end of file
diff --git a/agroal/runtime/pom.xml b/agroal/runtime/pom.xml
new file mode 100644
index 000000000..c7a9f5646
--- /dev/null
+++ b/agroal/runtime/pom.xml
@@ -0,0 +1,61 @@
+
+
+
+ shamrock-agroal
+ org.jboss.shamrock
+ 1.0.0.Alpha1-SNAPSHOT
+ ../
+
+ 4.0.0
+
+ shamrock-agroal-runtime
+
+
+
+ org.jboss.shamrock
+ shamrock-core-runtime
+
+
+ org.jboss.graalvm
+ graal-annotations
+
+
+
+ org.jboss.narayana.jta
+ narayana-jta
+
+
+
+ org.jboss.narayana.jts
+ narayana-jts-integration
+
+
+
+ org.jboss.spec.javax.transaction
+ jboss-transaction-api_1.2_spec
+
+
+
+ io.agroal
+ agroal-api
+
+
+ io.agroal
+ agroal-narayana
+
+
+ io.agroal
+ agroal-pool
+
+
+
+
+
+
+ maven-dependency-plugin
+
+
+
+
\ No newline at end of file
diff --git a/agroal/runtime/src/main/java/org/jboss/shamrock/agroal/runtime/DataSourceProducer.java b/agroal/runtime/src/main/java/org/jboss/shamrock/agroal/runtime/DataSourceProducer.java
new file mode 100644
index 000000000..c934603da
--- /dev/null
+++ b/agroal/runtime/src/main/java/org/jboss/shamrock/agroal/runtime/DataSourceProducer.java
@@ -0,0 +1,184 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2017, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.shamrock.agroal.runtime;
+
+import java.sql.Driver;
+import java.sql.SQLException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+import javax.sql.DataSource;
+import javax.sql.XADataSource;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+
+import io.agroal.api.AgroalDataSource;
+import io.agroal.api.AgroalDataSourceListener;
+import io.agroal.api.configuration.supplier.AgroalDataSourceConfigurationSupplier;
+import io.agroal.api.security.NamePrincipal;
+import io.agroal.api.security.SimplePassword;
+import io.agroal.api.transaction.TransactionIntegration;
+import io.agroal.narayana.NarayanaTransactionIntegration;
+
+@ApplicationScoped
+public class DataSourceProducer {
+
+ private static final Logger log = Logger.getLogger(DataSourceProducer.class.getName());
+
+ private Class driver;
+ private String dataSourceName;
+ private String url;
+ private String userName;
+ private String password;
+ private boolean jta;
+ private boolean connectable;
+ private boolean xa;
+
+ private AgroalDataSource agroalDataSource;
+
+ @Inject
+ private TransactionManager transactionManager;
+
+ @Inject
+ private TransactionSynchronizationRegistry transactionSynchronizationRegistry;
+
+ private AgroalDataSource dataSource;
+
+ @Produces
+ @ApplicationScoped
+ public AgroalDataSource getDatasource() throws SQLException {
+ Class> providerClass = driver;
+ if (xa) {
+ if (!XADataSource.class.isAssignableFrom(providerClass)) {
+ throw new RuntimeException("Driver is not an XA datasource and xa has been configured");
+ }
+ } else {
+ if (providerClass != null && !DataSource.class.isAssignableFrom(providerClass) && !Driver.class.isAssignableFrom(providerClass)) {
+ throw new RuntimeException("Driver is an XA datasource and xa has been configured");
+ }
+ }
+ AgroalDataSourceConfigurationSupplier dataSourceConfiguration = new AgroalDataSourceConfigurationSupplier();
+ dataSourceConfiguration.connectionPoolConfiguration().connectionFactoryConfiguration().jdbcUrl(url);
+ dataSourceConfiguration.connectionPoolConfiguration().connectionFactoryConfiguration().connectionProviderClass(providerClass);
+
+ if (jta || xa) {
+ TransactionIntegration txIntegration = new NarayanaTransactionIntegration(transactionManager, transactionSynchronizationRegistry, null, connectable);
+ dataSourceConfiguration.connectionPoolConfiguration().transactionIntegration(txIntegration);
+ }
+ // use the name / password from the callbacks
+ if (userName != null) {
+ dataSourceConfiguration.connectionPoolConfiguration().connectionFactoryConfiguration().principal(new NamePrincipal(userName));
+ }
+ if (password != null) {
+ dataSourceConfiguration.connectionPoolConfiguration().connectionFactoryConfiguration().credential(new SimplePassword(password));
+ }
+
+ agroalDataSource = AgroalDataSource.from(dataSourceConfiguration);
+ log.log(Level.INFO, "Started data source " + url);
+ return agroalDataSource;
+ }
+
+ @PreDestroy
+ public void stop() {
+ agroalDataSource.close();
+ }
+
+ public static Logger getLog() {
+ return log;
+ }
+
+ public Class getDriver() {
+ return driver;
+ }
+
+ public void setDriver(Class driver) {
+ this.driver = driver;
+ }
+
+ public String getDataSourceName() {
+ return dataSourceName;
+ }
+
+ public void setDataSourceName(String dataSourceName) {
+ this.dataSourceName = dataSourceName;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public boolean isJta() {
+ return jta;
+ }
+
+ public void setJta(boolean jta) {
+ this.jta = jta;
+ }
+
+ public boolean isConnectable() {
+ return connectable;
+ }
+
+ public void setConnectable(boolean connectable) {
+ this.connectable = connectable;
+ }
+
+ public boolean isXa() {
+ return xa;
+ }
+
+ public void setXa(boolean xa) {
+ this.xa = xa;
+ }
+
+ public AgroalDataSource getAgroalDataSource() {
+ return agroalDataSource;
+ }
+
+ public void setAgroalDataSource(AgroalDataSource agroalDataSource) {
+ this.agroalDataSource = agroalDataSource;
+ }
+}
diff --git a/agroal/runtime/src/main/java/org/jboss/shamrock/agroal/runtime/DataSourceTemplate.java b/agroal/runtime/src/main/java/org/jboss/shamrock/agroal/runtime/DataSourceTemplate.java
new file mode 100644
index 000000000..7439bc5cd
--- /dev/null
+++ b/agroal/runtime/src/main/java/org/jboss/shamrock/agroal/runtime/DataSourceTemplate.java
@@ -0,0 +1,18 @@
+package org.jboss.shamrock.agroal.runtime;
+
+import org.jboss.shamrock.runtime.BeanContainer;
+import org.jboss.shamrock.runtime.ContextObject;
+
+public class DataSourceTemplate {
+
+ public void addDatasource(@ContextObject("bean.container") BeanContainer beanContainer,
+ String url, Class driver,
+ String userName, String password) {
+ DataSourceProducer producer = beanContainer.instance(DataSourceProducer.class);
+ producer.setDriver(driver);
+ producer.setUrl(url);
+ producer.setUserName(userName);
+ producer.setPassword(password);
+ }
+
+}
diff --git a/agroal/runtime/src/main/java/org/jboss/shamrock/agroal/runtime/graal/AgroalDataSourceReplacement.java b/agroal/runtime/src/main/java/org/jboss/shamrock/agroal/runtime/graal/AgroalDataSourceReplacement.java
new file mode 100644
index 000000000..98774a29a
--- /dev/null
+++ b/agroal/runtime/src/main/java/org/jboss/shamrock/agroal/runtime/graal/AgroalDataSourceReplacement.java
@@ -0,0 +1,24 @@
+package org.jboss.shamrock.agroal.runtime.graal;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+import io.agroal.api.AgroalDataSource;
+import io.agroal.api.AgroalDataSourceListener;
+import io.agroal.api.configuration.AgroalDataSourceConfiguration;
+import io.agroal.pool.DataSource;
+
+@TargetClass(AgroalDataSource.class)
+final class AgroalDataSourceReplacement {
+
+ @Substitute
+ static AgroalDataSource from(AgroalDataSourceConfiguration configuration, AgroalDataSourceListener... listeners) throws SQLException {
+ return new DataSource(configuration, listeners);
+
+ }
+
+}
diff --git a/core/deployment/src/main/java/org/jboss/shamrock/deployment/BuildTimeGenerator.java b/core/deployment/src/main/java/org/jboss/shamrock/deployment/BuildTimeGenerator.java
index baa1b9f55..1c93c9474 100644
--- a/core/deployment/src/main/java/org/jboss/shamrock/deployment/BuildTimeGenerator.java
+++ b/core/deployment/src/main/java/org/jboss/shamrock/deployment/BuildTimeGenerator.java
@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -164,6 +165,7 @@ public class BuildTimeGenerator {
private final Map reflectiveClasses = new LinkedHashMap<>();
private final Set resources = new HashSet<>();
private final Set resourceBundles = new HashSet<>();
+ private final List> beforeAnalysisCallback = new ArrayList<>();
@Override
public BytecodeRecorder addStaticInitTask(int priority) {
@@ -246,6 +248,11 @@ public class BuildTimeGenerator {
resourceBundles.add(bundle);
}
+ @Override
+ public void addBeforeAnalysis(Consumer callback) {
+ beforeAnalysisCallback.add(callback);
+ }
+
void writeMainClass() throws IOException {
Collections.sort(tasks);
@@ -298,11 +305,16 @@ public class BuildTimeGenerator {
ClassCreator file = new ClassCreator(ClassOutput.gizmoAdaptor(output, true), GRAAL_AUTOFEATURE, null, Object.class.getName(), "org/graalvm/nativeimage/Feature");
file.addAnnotation("com/oracle/svm/core/annotate/AutomaticFeature");
-
+ MethodCreator afterReg = file.getMethodCreator("afterRegistration", void.class, "org.graalvm.nativeimage.Feature$AfterRegistrationAccess");
MethodCreator beforeAn = file.getMethodCreator("beforeAnalysis", "V", "org/graalvm/nativeimage/Feature$BeforeAnalysisAccess");
//TODO: at some point we are going to need to break this up, as if it get too big it will hit the method size limit
+ for(Consumer i : beforeAnalysisCallback) {
+ i.accept(afterReg);
+ }
+ afterReg.returnValue(null);
+
for (String i : resources) {
beforeAn.invokeStaticMethod(ofMethod(ResourceHelper.class, "registerResources", void.class, String.class), beforeAn.load(i));
}
diff --git a/core/deployment/src/main/java/org/jboss/shamrock/deployment/ProcessorContext.java b/core/deployment/src/main/java/org/jboss/shamrock/deployment/ProcessorContext.java
index c48dfdc97..c028d001e 100644
--- a/core/deployment/src/main/java/org/jboss/shamrock/deployment/ProcessorContext.java
+++ b/core/deployment/src/main/java/org/jboss/shamrock/deployment/ProcessorContext.java
@@ -1,10 +1,12 @@
package org.jboss.shamrock.deployment;
import java.io.IOException;
+import java.util.function.Consumer;
import java.util.function.Function;
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.MethodInfo;
+import org.jboss.protean.gizmo.MethodCreator;
import org.jboss.shamrock.deployment.codegen.BytecodeRecorder;
import org.objectweb.asm.ClassVisitor;
@@ -87,4 +89,6 @@ public interface ProcessorContext {
void addResourceBundle(String bundle);
+
+ void addBeforeAnalysis(Consumer callback);
}
diff --git a/core/deployment/src/main/java/org/jboss/shamrock/deployment/RuntimePriority.java b/core/deployment/src/main/java/org/jboss/shamrock/deployment/RuntimePriority.java
index 356f59949..8b7775381 100644
--- a/core/deployment/src/main/java/org/jboss/shamrock/deployment/RuntimePriority.java
+++ b/core/deployment/src/main/java/org/jboss/shamrock/deployment/RuntimePriority.java
@@ -17,4 +17,5 @@ public class RuntimePriority {
public static final int UNDERTOW_START = 500;
public static final int BEAN_VALIDATION_DEPLOYMENT = 600;
public static final int TRANSACTIONS_DEPLOYMENT = 700;
+ public static final int DATASOURCE_DEPLOYMENT = 700;
}
diff --git a/core/deployment/src/main/java/org/jboss/shamrock/deployment/buildconfig/BuildConfig.java b/core/deployment/src/main/java/org/jboss/shamrock/deployment/buildconfig/BuildConfig.java
index b798a9567..395a4812f 100644
--- a/core/deployment/src/main/java/org/jboss/shamrock/deployment/buildconfig/BuildConfig.java
+++ b/core/deployment/src/main/java/org/jboss/shamrock/deployment/buildconfig/BuildConfig.java
@@ -154,5 +154,9 @@ public class BuildConfig {
public Object getUnderlying() {
return node;
}
+
+ public boolean isNull() {
+ return node == null;
+ }
}
}
diff --git a/core/runtime/src/main/java/org/jboss/shamrock/runtime/graal/MappedByteBufferReplacement.java b/core/runtime/src/main/java/org/jboss/shamrock/runtime/graal/MappedByteBufferReplacement.java
new file mode 100644
index 000000000..4cfff40ad
--- /dev/null
+++ b/core/runtime/src/main/java/org/jboss/shamrock/runtime/graal/MappedByteBufferReplacement.java
@@ -0,0 +1,16 @@
+package org.jboss.shamrock.runtime.graal;
+
+import java.io.FileDescriptor;
+import java.nio.MappedByteBuffer;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+
+@TargetClass(MappedByteBuffer.class)
+final class MappedByteBufferReplacement {
+
+ @Substitute
+ private void force0(FileDescriptor fd, long address, long length) {
+
+ }
+}
diff --git a/examples/strict/pom.xml b/examples/strict/pom.xml
index a35b16536..22ac5cb4a 100644
--- a/examples/strict/pom.xml
+++ b/examples/strict/pom.xml
@@ -69,6 +69,17 @@
shamrock-transactions-deployment
provided
+
+
+ org.jboss.graalvm
+ graal-annotations
+
@@ -82,6 +93,11 @@
shamrock-graal
test
+
+ org.hsqldb
+ hsqldb
+ 2.4.0
+
diff --git a/examples/strict/src/main/java/org/jboss/shamrock/example/datasource/DatasourceResource.java b/examples/strict/src/main/java/org/jboss/shamrock/example/datasource/DatasourceResource.java
new file mode 100644
index 000000000..d4de0fceb
--- /dev/null
+++ b/examples/strict/src/main/java/org/jboss/shamrock/example/datasource/DatasourceResource.java
@@ -0,0 +1,38 @@
+package org.jboss.shamrock.example.datasource;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import javax.inject.Inject;
+import javax.sql.DataSource;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("/datasource")
+public class DatasourceResource {
+//
+// @Inject
+// private DataSource dataSource;
+//
+// @GET
+// public String simpleTest() throws Exception {
+// try (Connection con = dataSource.getConnection()) {
+// try (Statement statement = con.createStatement()) {
+// statement.execute("create table a (b int)");
+// }
+// try (Statement statement = con.createStatement()) {
+// statement.execute("insert into a values (10)");
+// }
+// try (Statement statement = con.createStatement()) {
+// try (ResultSet rs = statement.executeQuery("select b from a")) {
+// if(rs.next()) {
+// return rs.getString(1);
+// }
+// return "FAILED";
+// }
+// }
+// }
+// }
+
+}
diff --git a/examples/strict/src/main/java/org/jboss/shamrock/example/datasource/HSQLDriverReplacement.java b/examples/strict/src/main/java/org/jboss/shamrock/example/datasource/HSQLDriverReplacement.java
new file mode 100644
index 000000000..e0b67e366
--- /dev/null
+++ b/examples/strict/src/main/java/org/jboss/shamrock/example/datasource/HSQLDriverReplacement.java
@@ -0,0 +1,115 @@
+package org.jboss.shamrock.example.datasource;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.hsqldb.DatabaseURL;
+import org.hsqldb.error.ErrorCode;
+import org.hsqldb.jdbc.JDBCConnection;
+import org.hsqldb.jdbc.JDBCDriver;
+import org.hsqldb.jdbc.JDBCUtil;
+import org.hsqldb.persist.HsqlProperties;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+
+@TargetClass(JDBCDriver.class)
+final class HSQLDriverReplacement {
+
+
+ @Substitute
+ public static Connection getConnection(String url,
+ Properties info) throws SQLException {
+
+ final HsqlProperties props = DatabaseURL.parseURL(url, true, false);
+
+ if (props == null) {
+
+ // supposed to be an HSQLDB driver url but has errors
+ throw JDBCUtil.invalidArgument();
+ } else if (props.isEmpty()) {
+
+ // is not an HSQLDB driver url
+ return null;
+ }
+
+ long timeout = 0;
+
+ if (info != null) {
+ timeout = HsqlProperties.getIntegerProperty(info, "loginTimeout", 0);
+ }
+
+ props.addProperties(info);
+
+ if (timeout == 0) {
+ timeout = DriverManager.getLoginTimeout();
+ }
+
+ // @todo: maybe impose some sort of sane restriction
+ // on network connections regardless of user
+ // specification?
+ if (timeout == 0) {
+
+ // no timeout restriction
+ return new JDBCConnection(props);
+ }
+
+ String connType = props.getProperty("connection_type");
+
+ if (DatabaseURL.isInProcessDatabaseType(connType)) {
+ return new JDBCConnection(props);
+ }
+
+ // @todo: Better: ThreadPool? HsqlTimer with callback?
+ final JDBCConnection[] conn = new JDBCConnection[1];
+ final SQLException[] ex = new SQLException[1];
+ Thread t = new Thread() {
+
+ public void run() {
+
+ try {
+ conn[0] = new JDBCConnection(props);
+ } catch (SQLException se) {
+ ex[0] = se;
+ }
+ }
+ };
+
+ t.start();
+
+ try {
+ t.join(1000 * timeout);
+ } catch (InterruptedException ie) {
+ }
+
+ try {
+
+ // PRE:
+ // deprecated, but should be ok, since neither
+ // the HSQLClientConnection or the HTTPClientConnection
+ // constructor will ever hold monitors on objects in
+ // an inconsistent state, such that damaged objects
+ // become visible to other threads with the
+ // potential of arbitrary behavior.
+ //t.stop();
+ } catch (Exception e) {
+ } finally {
+ try {
+ t.setContextClassLoader(null);
+ } catch (Throwable th) {
+ }
+ }
+
+ if (ex[0] != null) {
+ throw ex[0];
+ }
+
+ if (conn[0] != null) {
+ return conn[0];
+ }
+
+ throw JDBCUtil.sqlException(ErrorCode.X_08501);
+ }
+}
diff --git a/examples/strict/src/main/resources/META-INF/shamrock-build.yaml b/examples/strict/src/main/resources/META-INF/shamrock-build.yaml
new file mode 100644
index 000000000..f7d7fc758
--- /dev/null
+++ b/examples/strict/src/main/resources/META-INF/shamrock-build.yaml
@@ -0,0 +1,3 @@
+datasource:
+ url: "jdbc:hsqldb:http://localhost:7676/test"
+ driver: "org.hsqldb.jdbc.JDBCDriver"
\ No newline at end of file
diff --git a/examples/strict/src/test/java/org/jboss/shamrock/example/test/DatasourceITCase.java b/examples/strict/src/test/java/org/jboss/shamrock/example/test/DatasourceITCase.java
new file mode 100644
index 000000000..43392c70b
--- /dev/null
+++ b/examples/strict/src/test/java/org/jboss/shamrock/example/test/DatasourceITCase.java
@@ -0,0 +1,10 @@
+package org.jboss.shamrock.example.test;
+
+import org.jboss.shamrock.junit.GraalTest;
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+
+@RunWith(GraalTest.class)
+@Ignore
+public class DatasourceITCase extends DatasourceTestCase {
+}
\ No newline at end of file
diff --git a/examples/strict/src/test/java/org/jboss/shamrock/example/test/DatasourceTestCase.java b/examples/strict/src/test/java/org/jboss/shamrock/example/test/DatasourceTestCase.java
new file mode 100644
index 000000000..897d5708b
--- /dev/null
+++ b/examples/strict/src/test/java/org/jboss/shamrock/example/test/DatasourceTestCase.java
@@ -0,0 +1,56 @@
+package org.jboss.shamrock.example.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.hsqldb.server.WebServer;
+import org.jboss.shamrock.junit.ShamrockTest;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(ShamrockTest.class)
+@Ignore
+public class DatasourceTestCase {
+
+ static WebServer ws;
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ Path dir = Files.createTempDirectory("shamrock-test");
+ ws = new WebServer();
+ ws.setPort(7676);
+ ws.setAddress("localhost");
+ ws.setDatabaseName(0, "test");
+ ws.setDatabasePath(0, dir.toAbsolutePath().toString() + File.separator + "tempdb");
+ ws.start();
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ ws.stop();
+ }
+
+ @Test
+ public void testDataSource() throws Exception {
+ URL uri = new URL("http://localhost:8080/rest/datasource");
+ URLConnection connection = uri.openConnection();
+ InputStream in = connection.getInputStream();
+ byte[] buf = new byte[100];
+ int r;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ while ((r = in.read(buf)) > 0) {
+ out.write(buf, 0, r);
+ }
+ Assert.assertEquals("10", new String(out.toByteArray()));
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index e701779b0..5b487744f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,6 +52,8 @@
6.0.7.Final
5.8.0.Final
1.1.1.Final
+ 1.1
+ 7.6.0.Final
@@ -71,6 +73,7 @@
ext/arc
bean-validation
transactions
+ agroal
@@ -121,6 +124,16 @@
+
+ org.jboss.shamrock
+ shamrock-agroal-deployment
+ ${project.version}
+
+
+ org.jboss.shamrock
+ shamrock-agroal-runtime
+ ${project.version}
+
org.jboss.shamrock
shamrock-bean-validation-deployment
@@ -297,6 +310,23 @@
jackson-databind
${jackson.version}
+
+ io.agroal
+ agroal-api
+ ${agroal.version}
+
+
+
+ io.agroal
+ agroal-narayana
+ ${agroal.version}
+
+
+
+ io.agroal
+ agroal-pool
+ ${agroal.version}
+
io.undertow
undertow-servlet
@@ -494,6 +524,11 @@
jboss-jaxrs-api_2.1_spec
${jboss-jaxrs-api_2.1_spec.version}
+
+ org.jboss
+ jboss-transaction-spi
+ ${jboss-transaction-spi.version}
+
org.jboss.weld.se
weld-se-core
diff --git a/transactions/deployment/src/main/java/org/jboss/shamrock/transactions/TransactionsProcessor.java b/transactions/deployment/src/main/java/org/jboss/shamrock/transactions/TransactionsProcessor.java
index 7fcf776bf..a9a60aada 100644
--- a/transactions/deployment/src/main/java/org/jboss/shamrock/transactions/TransactionsProcessor.java
+++ b/transactions/deployment/src/main/java/org/jboss/shamrock/transactions/TransactionsProcessor.java
@@ -1,7 +1,14 @@
package org.jboss.shamrock.transactions;
+import static org.jboss.protean.gizmo.MethodDescriptor.ofMethod;
+
+import java.util.Properties;
+import java.util.function.Consumer;
+
import javax.inject.Inject;
+import org.jboss.protean.gizmo.MethodCreator;
+import org.jboss.protean.gizmo.ResultHandle;
import org.jboss.shamrock.deployment.ArchiveContext;
import org.jboss.shamrock.deployment.BeanDeployment;
import org.jboss.shamrock.deployment.ProcessorContext;
@@ -11,7 +18,9 @@ import org.jboss.shamrock.deployment.codegen.BytecodeRecorder;
import org.jboss.shamrock.transactions.runtime.TransactionProducers;
import org.jboss.shamrock.transactions.runtime.TransactionTemplate;
-import com.arjuna.ats.arjuna.coordinator.CheckedActionFactory;
+import com.arjuna.ats.arjuna.common.RecoveryEnvironmentBean;
+import com.arjuna.ats.arjuna.common.recoveryPropertyManager;
+import com.arjuna.ats.arjuna.recovery.RecoveryManager;
import com.arjuna.ats.internal.arjuna.coordinator.CheckedActionFactoryImple;
import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionSynchronizationRegistryImple;
@@ -34,12 +43,22 @@ class TransactionsProcessor implements ResourceProcessor {
TransactionSynchronizationRegistryImple.class.getName());
//we want to force Arjuna to init at static init time
- try (BytecodeRecorder bc = processorContext.addDeploymentTask(RuntimePriority.TRANSACTIONS_DEPLOYMENT)) {
+ try (BytecodeRecorder bc = processorContext.addStaticInitTask(RuntimePriority.TRANSACTIONS_DEPLOYMENT)) {
TransactionTemplate tt = bc.getRecordingProxy(TransactionTemplate.class);
- tt.setDefaultProperties(PropertiesFactory.getDefaultProperties());
- tt.forceInit();
+ Properties defaultProperties = PropertiesFactory.getDefaultProperties();
+ tt.setDefaultProperties(defaultProperties);
}
+ processorContext.addBeforeAnalysis(new Consumer() {
+ @Override
+ public void accept(MethodCreator methodCreator) {
+ methodCreator.invokeStaticMethod(ofMethod(RecoveryManager.class, "delayRecoveryManagerThread", void.class));
+ ResultHandle result = methodCreator.invokeStaticMethod(ofMethod(recoveryPropertyManager.class, "getRecoveryEnvironmentBean", RecoveryEnvironmentBean.class));
+ methodCreator.invokeVirtualMethod(ofMethod(RecoveryEnvironmentBean.class, "setExpiryScanInterval", void.class, int.class), result, methodCreator.load(0));
+
+ }
+ });
+
}
@Override