diff --git a/dependencies/pom.xml b/dependencies/pom.xml index a2dd8b2ec58..eb6e3848837 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -69,8 +69,8 @@ 2.2.220 1.3 4.4.0 - 6.3 - ${version.lib.hibernate.family}.1.Final + 6.6 + ${version.lib.hibernate.family}.29.Final 8.0.2.Final 5.0.1 1.5.18 diff --git a/integrations/cdi/hibernate-cdi/pom.xml b/integrations/cdi/hibernate-cdi/pom.xml index a9b8ba8213b..376d634c1e0 100644 --- a/integrations/cdi/hibernate-cdi/pom.xml +++ b/integrations/cdi/hibernate-cdi/pom.xml @@ -79,6 +79,11 @@ svm provided + + net.bytebuddy + byte-buddy + provided + diff --git a/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/ByteBuddyEnhancementContext.java b/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/ByteBuddyEnhancementContext.java new file mode 100644 index 00000000000..ab665ab1f1c --- /dev/null +++ b/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/ByteBuddyEnhancementContext.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Oracle and/or its affiliates. + * + * Licensed 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 io.helidon.integrations.cdi.hibernate; + +import java.util.Optional; + +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.RecomputeFieldValue; +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import net.bytebuddy.description.field.FieldDescription; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +@TargetClass(className = "org.hibernate.bytecode.enhance.internal.bytebuddy.ByteBuddyEnhancementContext") +@SuppressWarnings("checkstyle:StaticVariableName") +final class ByteBuddyEnhancementContext { + + @Alias + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias) + private static ElementMatcher.Junction IS_GETTER; + + @Substitute + Optional resolveGetter(FieldDescription fieldDescription) { + return Optional.empty(); + } +} diff --git a/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/ByteBuddyProxyHelper.java b/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/ByteBuddyProxyHelper.java new file mode 100644 index 00000000000..9f0822e3da8 --- /dev/null +++ b/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/ByteBuddyProxyHelper.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Oracle and/or its affiliates. + * + * Licensed 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 io.helidon.integrations.cdi.hibernate; + +import java.util.Collection; +import java.util.function.BiFunction; + +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.RecomputeFieldValue; +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.NamingStrategy; +import net.bytebuddy.description.type.TypeDefinition; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.dynamic.DynamicType; + + +@TargetClass(className = "org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyHelper") +@SuppressWarnings("checkstyle:StaticVariableName") +final class ByteBuddyProxyHelper { + + @Alias + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias) + private static TypeDescription OBJECT; + + @Substitute + private BiFunction> proxyBuilder(TypeDefinition persistentClass, + Collection interfaces) { + return null; + } +} diff --git a/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/BytecodeProviderInitiator.java b/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/BytecodeProviderInitiator.java index 5284cf1a2f2..736ceaaef22 100644 --- a/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/BytecodeProviderInitiator.java +++ b/integrations/cdi/hibernate-cdi/src/main/java/io/helidon/integrations/cdi/hibernate/BytecodeProviderInitiator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Oracle and/or its affiliates. + * Copyright (c) 2024, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,13 @@ package io.helidon.integrations.cdi.hibernate; +import java.util.Map; import java.util.function.Predicate; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; import org.hibernate.bytecode.spi.BytecodeProvider; +import org.hibernate.service.spi.ServiceRegistryImplementor; /** * In native image, we force the usage of the no-op bytecode provider so no bytecode @@ -34,17 +36,23 @@ private BytecodeProviderInitiator() { } @Substitute - public static BytecodeProvider buildBytecodeProvider(String providerName) { + public static BytecodeProvider buildDefaultBytecodeProvider() { return new org.hibernate.bytecode.internal.none.BytecodeProviderImpl(); } + @Substitute + public BytecodeProvider initiateService(Map configurationValues, ServiceRegistryImplementor registry) { + return buildDefaultBytecodeProvider(); + } + static class SubstituteOnlyIfPresent implements Predicate { @Override public boolean test(String type) { try { Class clazz = Class.forName(type, false, getClass().getClassLoader()); - clazz.getDeclaredMethod("buildBytecodeProvider", String.class); + clazz.getDeclaredMethod("buildDefaultBytecodeProvider"); + clazz.getDeclaredMethod("initiateService", Map.class, ServiceRegistryImplementor.class); return true; } catch (ClassNotFoundException | NoClassDefFoundError | NoSuchMethodException ex) { return false; diff --git a/integrations/cdi/hibernate-cdi/src/main/java/module-info.java b/integrations/cdi/hibernate-cdi/src/main/java/module-info.java index 0b52fa4553d..9c304b434f5 100644 --- a/integrations/cdi/hibernate-cdi/src/main/java/module-info.java +++ b/integrations/cdi/hibernate-cdi/src/main/java/module-info.java @@ -39,6 +39,7 @@ requires transitive jakarta.inject; requires jakarta.persistence; requires transitive jakarta.transaction; + requires transitive net.bytebuddy; requires org.graalvm.nativeimage; requires transitive org.hibernate.orm.core; diff --git a/integrations/cdi/hibernate-cdi/src/main/resources/META-INF/native-image/io.helidon.integrations.cdi/helidon-integrations-cdi-hibernate/native-image.properties b/integrations/cdi/hibernate-cdi/src/main/resources/META-INF/native-image/io.helidon.integrations.cdi/helidon-integrations-cdi-hibernate/native-image.properties index f7b8f6944ef..7f4c670e23f 100644 --- a/integrations/cdi/hibernate-cdi/src/main/resources/META-INF/native-image/io.helidon.integrations.cdi/helidon-integrations-cdi-hibernate/native-image.properties +++ b/integrations/cdi/hibernate-cdi/src/main/resources/META-INF/native-image/io.helidon.integrations.cdi/helidon-integrations-cdi-hibernate/native-image.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2024 Oracle and/or its affiliates. +# Copyright (c) 2024, 2025 Oracle and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,4 +14,6 @@ # limitations under the License. # -Args=-H:ReflectionConfigurationResources=${.}/reflect-config-additional.json +Args=-H:ReflectionConfigurationResources=${.}/reflect-config-additional.json \ + -H:ClassInitialization=org.hibernate.bytecode.enhance.internal.bytebuddy.ByteBuddyEnhancementContext:run_time \ + -H:ClassInitialization=org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyHelper:run_time diff --git a/integrations/cdi/hibernate-cdi/src/main/resources/META-INF/native-image/io.helidon.integrations.cdi/helidon-integrations-cdi-hibernate/reflect-config.json b/integrations/cdi/hibernate-cdi/src/main/resources/META-INF/native-image/io.helidon.integrations.cdi/helidon-integrations-cdi-hibernate/reflect-config.json index 807da722185..0e170346e9f 100644 --- a/integrations/cdi/hibernate-cdi/src/main/resources/META-INF/native-image/io.helidon.integrations.cdi/helidon-integrations-cdi-hibernate/reflect-config.json +++ b/integrations/cdi/hibernate-cdi/src/main/resources/META-INF/native-image/io.helidon.integrations.cdi/helidon-integrations-cdi-hibernate/reflect-config.json @@ -2147,5 +2147,13 @@ ] } ] + }, + { + "name": "org.hibernate.event.spi.PostUpsertEventListener[]", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "unsafeAllocated": true } ] \ No newline at end of file diff --git a/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/chirp/TestJpaTransactionScopedSynchronizedEntityManager.java b/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/chirp/TestJpaTransactionScopedSynchronizedEntityManager.java index 81095105a49..ca43d7b0f98 100644 --- a/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/chirp/TestJpaTransactionScopedSynchronizedEntityManager.java +++ b/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/chirp/TestJpaTransactionScopedSynchronizedEntityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023 Oracle and/or its affiliates. + * Copyright (c) 2019, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -292,9 +292,9 @@ void testJpaTransactionScopedSynchronizedEntityManager() assertThat(transactionScopedContext.isActive(), is(true)); // Remove the Author we successfully committed before. We - // have to merge because author1 became detached a few lines - // above. - author1 = em.merge(author1); + // have to find because author1 became detached a few lines + // above and it is not allowed to attach it again with merge. + author1 = em.find(Author.class, Integer.valueOf(1)); assertThat(author1, notNullValue()); assertThat(em.contains(author1), is(true)); em.remove(author1); @@ -313,13 +313,15 @@ void testJpaTransactionScopedSynchronizedEntityManager() // tables. assertTableRowCount(dataSource, "AUTHOR", 0); - // Start a new transaction, merge our detached author1, and + // Start a new transaction, persist our detached author1, and // commit. This will bump the author's ID and put a row in // the database. tm.begin(); assertThat(em.isJoinedToTransaction(), is(true)); assertThat(transactionScopedContext.isActive(), is(true)); - author1 = em.merge(author1); + author1 = new Author("Abraham Lincoln"); + em.persist(author1); + em.merge(author1); tm.commit(); assertThat(em.isJoinedToTransaction(), is(false)); assertThat(em.contains(author1), is(false)); diff --git a/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/chirp/TestRollbackScenarios.java b/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/chirp/TestRollbackScenarios.java index 84337a54659..42bee034da5 100644 --- a/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/chirp/TestRollbackScenarios.java +++ b/integrations/cdi/jpa-cdi/src/test/java/io/helidon/integrations/cdi/jpa/chirp/TestRollbackScenarios.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023 Oracle and/or its affiliates. + * Copyright (c) 2019, 2025 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -276,6 +276,8 @@ void testRollbackScenarios() assertThat(tm.getStatus(), is(Status.STATUS_ACTIVE)); assertThat(em.isJoinedToTransaction(), is(true)); assertThat(em.contains(author), is(false)); + author = new Author("John Kennedy"); + em.persist(author); author = em.merge(author); em.remove(author); tm.commit();