mirror of
https://github.com/jlengrand/quarkus.git
synced 2026-03-10 08:41:22 +00:00
Initial attempt at agroal integration
This works in JVM mode, but fails due to an NPE in analysis on substrate
This commit is contained in:
31
agroal/deployment/pom.xml
Normal file
31
agroal/deployment/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<parent>
|
||||
<artifactId>shamrock-agroal</artifactId>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<version>1.0.0.Alpha1-SNAPSHOT</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>shamrock-agroal-deployment</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<artifactId>shamrock-core-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<artifactId>shamrock-agroal-runtime</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<artifactId>shamrock-transactions-deployment</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.jboss.shamrock.agroal.AgroalSetup
|
||||
18
agroal/pom.xml
Normal file
18
agroal/pom.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<parent>
|
||||
<artifactId>shamrock-parent</artifactId>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<version>1.0.0.Alpha1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>shamrock-agroal</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>deployment</module>
|
||||
<module>runtime</module>
|
||||
</modules>
|
||||
</project>
|
||||
61
agroal/runtime/pom.xml
Normal file
61
agroal/runtime/pom.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<parent>
|
||||
<artifactId>shamrock-agroal</artifactId>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<version>1.0.0.Alpha1-SNAPSHOT</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>shamrock-agroal-runtime</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<artifactId>shamrock-core-runtime</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.graalvm</groupId>
|
||||
<artifactId>graal-annotations</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.narayana.jta</groupId>
|
||||
<artifactId>narayana-jta</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.narayana.jts</groupId>
|
||||
<artifactId>narayana-jts-integration</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.transaction</groupId>
|
||||
<artifactId>jboss-transaction-api_1.2_spec</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.agroal</groupId>
|
||||
<artifactId>agroal-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.agroal</groupId>
|
||||
<artifactId>agroal-narayana</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.agroal</groupId>
|
||||
<artifactId>agroal-pool</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<String, ReflectionInfo> reflectiveClasses = new LinkedHashMap<>();
|
||||
private final Set<String> resources = new HashSet<>();
|
||||
private final Set<String> resourceBundles = new HashSet<>();
|
||||
private final List<Consumer<MethodCreator>> beforeAnalysisCallback = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public BytecodeRecorder addStaticInitTask(int priority) {
|
||||
@@ -246,6 +248,11 @@ public class BuildTimeGenerator {
|
||||
resourceBundles.add(bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBeforeAnalysis(Consumer<MethodCreator> 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<MethodCreator> 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));
|
||||
}
|
||||
|
||||
@@ -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<MethodCreator> callback);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -154,5 +154,9 @@ public class BuildConfig {
|
||||
public Object getUnderlying() {
|
||||
return node;
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return node == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,17 @@
|
||||
<artifactId>shamrock-transactions-deployment</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<artifactId>shamrock-agroal-deployment</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.jboss.graalvm</groupId>
|
||||
<artifactId>graal-annotations</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- test dependencies -->
|
||||
@@ -82,6 +93,11 @@
|
||||
<artifactId>shamrock-graal</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.4.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -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";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
datasource:
|
||||
url: "jdbc:hsqldb:http://localhost:7676/test"
|
||||
driver: "org.hsqldb.jdbc.JDBCDriver"
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
}
|
||||
35
pom.xml
35
pom.xml
@@ -52,6 +52,8 @@
|
||||
<hibernate-validator.version>6.0.7.Final</hibernate-validator.version>
|
||||
<narayana.version>5.8.0.Final</narayana.version>
|
||||
<jboss-transaction-api_1.2_spec.version>1.1.1.Final</jboss-transaction-api_1.2_spec.version>
|
||||
<agroal.version>1.1</agroal.version>
|
||||
<jboss-transaction-spi.version>7.6.0.Final</jboss-transaction-spi.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
@@ -71,6 +73,7 @@
|
||||
<module>ext/arc</module>
|
||||
<module>bean-validation</module>
|
||||
<module>transactions</module>
|
||||
<module>agroal</module>
|
||||
</modules>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
@@ -121,6 +124,16 @@
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<artifactId>shamrock-agroal-deployment</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<artifactId>shamrock-agroal-runtime</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.shamrock</groupId>
|
||||
<artifactId>shamrock-bean-validation-deployment</artifactId>
|
||||
@@ -297,6 +310,23 @@
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.agroal</groupId>
|
||||
<artifactId>agroal-api</artifactId>
|
||||
<version>${agroal.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.agroal</groupId>
|
||||
<artifactId>agroal-narayana</artifactId>
|
||||
<version>${agroal.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.agroal</groupId>
|
||||
<artifactId>agroal-pool</artifactId>
|
||||
<version>${agroal.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
@@ -494,6 +524,11 @@
|
||||
<artifactId>jboss-jaxrs-api_2.1_spec</artifactId>
|
||||
<version>${jboss-jaxrs-api_2.1_spec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss</groupId>
|
||||
<artifactId>jboss-transaction-spi</artifactId>
|
||||
<version>${jboss-transaction-spi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.weld.se</groupId>
|
||||
<artifactId>weld-se-core</artifactId>
|
||||
|
||||
@@ -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<MethodCreator>() {
|
||||
@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
|
||||
|
||||
Reference in New Issue
Block a user