Skip to content

Commit

Permalink
Revisit apache#4048 to Springless JPA extension
Browse files Browse the repository at this point in the history
  • Loading branch information
zhfeng committed Aug 7, 2023
1 parent 03458a5 commit fa7cf2f
Show file tree
Hide file tree
Showing 17 changed files with 296 additions and 58 deletions.
28 changes: 26 additions & 2 deletions docs/modules/ROOT/pages/reference/extensions/jpa.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,32 @@ endif::[]

The extension leverages https://quarkus.io/guides/hibernate-orm[Quarkus Hibernate ORM] to provide the JPA implementation via Hibernate.

Refer to the https://quarkus.io/guides/hibernate-orm[Quarkus Hibernate ORM] documentation to see how to configure Hibernate and your datasource,
Refer to the https://quarkus.io/guides/hibernate-orm[Quarkus Hibernate ORM] documentation to see how to configure Hibernate and your datasource.

Also, it leverages https://quarkus.io/guides/transaction#programmatic-approach[Quarkus TX API] to provide `TransactionStrategy` implementation.

When a single persistence unit is used, the Camel Quarkus JPA extension will automatically configure the JPA component with a
`EntityManagerFactory` and `TransactionManager`.
`EntityManagerFactory` and `TransactionStrategy`.

[id="extensions-jpa-configuration-configuring-jpamessageidrepository"]
=== Configuring JpaMessageIdRepository
It needs to use `EntityManagerFactory` and `TransactionStrategy` from the CDI container to configure the `JpaMessageIdRepository`:
[source, java]
----
@Inject
EntityManagerFactory entityManagerFactory;
@Inject
TransactionStrategy transactionStrategy;
from("direct:idempotent")
.idempotentConsumer(
header("messageId"),
new JpaMessageIdRepository(entityManagerFactory, transactionStrategy, "idempotentProcessor"));
----

[NOTE]
====
Since it excludes the `spring-orm` dependency, some options such as `sharedEntityManager`, `transactionManager` are not supported.
====

4 changes: 0 additions & 4 deletions extensions/jpa/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-support-spring-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-jpa</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
*/
package org.apache.camel.quarkus.component.jpa.deployment;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import org.apache.camel.component.jpa.JpaComponent;
import org.apache.camel.quarkus.component.jpa.CamelJpaProducer;
import org.apache.camel.quarkus.component.jpa.CamelJpaRecorder;
import org.apache.camel.quarkus.core.deployment.spi.CamelRuntimeBeanBuildItem;

Expand All @@ -37,8 +39,10 @@ FeatureBuildItem feature() {
@Record(ExecutionTime.RUNTIME_INIT)
@BuildStep
void configureJpaComponentBean(
BuildProducer<AdditionalBeanBuildItem> additionalBeans,
BuildProducer<CamelRuntimeBeanBuildItem> camelRuntimeBean,
CamelJpaRecorder recorder) {
additionalBeans.produce(new AdditionalBeanBuildItem(CamelJpaProducer.class));

camelRuntimeBean.produce(
new CamelRuntimeBeanBuildItem(
Expand Down
14 changes: 5 additions & 9 deletions extensions/jpa/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
</properties>

<dependencies>
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm</artifactId>
Expand All @@ -44,19 +49,10 @@
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-support-spring</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jpa</artifactId>
</dependency>

<dependency><!-- https://github.com/apache/camel-quarkus/issues/4084 -->
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
27 changes: 25 additions & 2 deletions extensions/jpa/runtime/src/main/doc/configuration.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
The extension leverages https://quarkus.io/guides/hibernate-orm[Quarkus Hibernate ORM] to provide the JPA implementation via Hibernate.

Refer to the https://quarkus.io/guides/hibernate-orm[Quarkus Hibernate ORM] documentation to see how to configure Hibernate and your datasource,
Refer to the https://quarkus.io/guides/hibernate-orm[Quarkus Hibernate ORM] documentation to see how to configure Hibernate and your datasource.

Also, it leverages https://quarkus.io/guides/transaction#programmatic-approach[Quarkus TX API] to provide `TransactionStrategy` implementation.

When a single persistence unit is used, the Camel Quarkus JPA extension will automatically configure the JPA component with a
`EntityManagerFactory` and `TransactionManager`.
`EntityManagerFactory` and `TransactionStrategy`.

=== Configuring JpaMessageIdRepository
It needs to use `EntityManagerFactory` and `TransactionStrategy` from the CDI container to configure the `JpaMessageIdRepository`:
[source, java]
----
@Inject
EntityManagerFactory entityManagerFactory;
@Inject
TransactionStrategy transactionStrategy;
from("direct:idempotent")
.idempotentConsumer(
header("messageId"),
new JpaMessageIdRepository(entityManagerFactory, transactionStrategy, "idempotentProcessor"));
----

[NOTE]
====
Since it excludes the `spring-orm` dependency, some options such as `sharedEntityManager`, `transactionManager` are not supported.
====
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.quarkus.component.jpa;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Produces;
import org.apache.camel.component.jpa.TransactionStrategy;

@Dependent
public class CamelJpaProducer {
@Produces
@ApplicationScoped
public TransactionStrategy quarkusTransactionStrategy() {
return new QuarkusTransactionStrategy();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,16 @@
*/
package org.apache.camel.quarkus.component.jpa;

import io.quarkus.arc.Arc;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.annotations.Recorder;
import jakarta.transaction.TransactionManager;
import jakarta.transaction.UserTransaction;
import org.apache.camel.component.jpa.JpaComponent;
import org.springframework.transaction.jta.JtaTransactionManager;

@Recorder
public class CamelJpaRecorder {

public RuntimeValue<JpaComponent> createJpaComponent() {
TransactionManager transactionManager = Arc.container().instance(TransactionManager.class).get();
UserTransaction userTransaction = Arc.container().instance(UserTransaction.class).get();

JpaComponent component = new JpaComponent();
component.setTransactionManager(new JtaTransactionManager(userTransaction, transactionManager));
component.setTransactionStrategy(new QuarkusTransactionStrategy());
return new RuntimeValue<>(component);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.camel.quarkus.component.jpa;

import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.narayana.jta.RunOptions;
import org.apache.camel.component.jpa.TransactionStrategy;

import static io.quarkus.narayana.jta.QuarkusTransaction.runOptions;

public class QuarkusTransactionStrategy implements TransactionStrategy {
@Override
public void executeInTransaction(Runnable runnable) {
QuarkusTransaction.run(runOptions().semantic(RunOptions.Semantic.JOIN_EXISTING), runnable);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.camel.quarkus.component.jpa.graal;

import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.core.annotate.TargetClass;
import org.apache.camel.component.jpa.DefaultTransactionStrategy;

@TargetClass(DefaultTransactionStrategy.class)
@Delete
final public class DefaultTransactionStrategySubstitution {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.camel.quarkus.component.jpa.graal;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import jakarta.persistence.EntityManagerFactory;
import org.apache.camel.component.jpa.JpaComponent;
import org.apache.camel.component.jpa.TransactionStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@TargetClass(JpaComponent.class)
final public class JpaComponentSubstitution {
@Alias
private TransactionStrategy transactionStrategy;

@Alias
private EntityManagerFactory entityManagerFactory;

@Alias
private void initEntityManagerFactory() {
}

@Substitute
protected void doInit() throws Exception {
initEntityManagerFactory();

Logger LOG = LoggerFactory.getLogger(JpaComponent.class);
if (entityManagerFactory == null) {
LOG.warn(
"No EntityManagerFactory has been configured on this JpaComponent. Each JpaEndpoint will auto create their own EntityManagerFactory.");
}

if (transactionStrategy != null) {
LOG.info("Using TransactionStrategy configured: {}", transactionStrategy);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.camel.quarkus.component.jpa.graal;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import jakarta.persistence.EntityManagerFactory;
import org.apache.camel.component.jpa.JpaEndpoint;
import org.apache.camel.component.jpa.TransactionStrategy;

@TargetClass(JpaEndpoint.class)
final public class JpaEndpointSubstitution {
@Alias
private TransactionStrategy transactionStrategy;

@Substitute
protected EntityManagerFactory createEntityManagerFactory() {
throw new UnsupportedOperationException("createEntityManagerFactory is not supported");
}

@Substitute
public TransactionStrategy getTransactionStrategy() {
return transactionStrategy;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.orm.jpa;

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;

public abstract class SharedEntityManagerCreator {
public static EntityManager createSharedEntityManager(EntityManagerFactory emf) {
throw new UnsupportedOperationException("createSharedEntityManager is not supported");
}
}
Loading

0 comments on commit fa7cf2f

Please sign in to comment.