diff --git a/health/health-checks/src/main/java/module-info.java b/health/health-checks/src/main/java/module-info.java index 22bb21e3645..651e69c2008 100644 --- a/health/health-checks/src/main/java/module-info.java +++ b/health/health-checks/src/main/java/module-info.java @@ -33,5 +33,5 @@ exports io.helidon.health.checks; // required for CDI - opens io.helidon.health.checks to weld.core.impl; + opens io.helidon.health.checks to weld.core.impl, io.helidon.microprofile.cdi; } diff --git a/microprofile/access-log/src/main/java/module-info.java b/microprofile/access-log/src/main/java/module-info.java index 9d49455b837..b4673d9afd0 100644 --- a/microprofile/access-log/src/main/java/module-info.java +++ b/microprofile/access-log/src/main/java/module-info.java @@ -29,7 +29,7 @@ exports io.helidon.microprofile.accesslog; // this is needed for CDI extensions that use non-public observer methods - opens io.helidon.microprofile.accesslog to weld.core.impl; + opens io.helidon.microprofile.accesslog to weld.core.impl, io.helidon.microprofile.cdi; provides Extension with io.helidon.microprofile.accesslog.AccessLogCdiExtension; } diff --git a/microprofile/cdi/src/main/java/io/helidon/microprofile/cdi/HelidonProxyServices.java b/microprofile/cdi/src/main/java/io/helidon/microprofile/cdi/HelidonProxyServices.java index 5ecb9e81404..67031991e1c 100644 --- a/microprofile/cdi/src/main/java/io/helidon/microprofile/cdi/HelidonProxyServices.java +++ b/microprofile/cdi/src/main/java/io/helidon/microprofile/cdi/HelidonProxyServices.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.IdentityHashMap; import java.util.Map; +import java.util.logging.Level; import java.util.logging.Logger; import io.helidon.common.NativeImageHelper; @@ -32,6 +33,9 @@ class HelidonProxyServices implements ProxyServices { private static final Logger LOGGER = Logger.getLogger(HelidonProxyServices.class.getName()); + private static final String WELD_JAVAX_PREFIX = "org.jboss.weldx."; + private static final String WELD_JAVA_PREFIX = "org.jboss.weld."; + // a cache of all classloaders (this should be empty in most cases, as we use a single class loader in Helidon) private final Map classLoaders = Collections.synchronizedMap(new IdentityHashMap<>()); private final ClassLoader contextCl; @@ -69,14 +73,20 @@ public boolean supportsClassDefining() { public Class defineClass(Class originalClass, String className, byte[] classBytes, int off, int len) throws ClassFormatError { - if (samePackage(originalClass, className)) { - // when we need to define a class in the same package (to see package local fields and methods) - // we cannot use a classloader, as the new class would be in the same package, but in a different - // classloader, preventing it from seeing these fields/methods - return defineClassSamePackage(originalClass, className, classBytes, off, len); - } else { - // use a custom classloader to define classes in a new package - return wrapCl(originalClass.getClassLoader()).doDefineClass(originalClass, className, classBytes, off, len); + if (weldInternalProxyClassName(className)) { + // this is special case - these classes are defined in a non-existent package + // and we need to use a classloader (public lookup will not allow this, and private lookup is not + // possible for an empty package) + return wrapCl(originalClass.getClassLoader()) + .doDefineClass(originalClass, className, classBytes, off, len); + } + // any other class should be defined using a private lookup + try { + return defineClassPrivateLookup(originalClass, className, classBytes, off, len); + } catch (Exception e) { + LOGGER.log(Level.FINEST, "Failed to create class " + className + " using private lookup", e); + + throw e; } } @@ -88,12 +98,21 @@ public Class defineClass(Class originalClass, int len, ProtectionDomain protectionDomain) throws ClassFormatError { - if (samePackage(originalClass, className)) { - return defineClassSamePackage(originalClass, className, classBytes, off, len); - } else { + if (weldInternalProxyClassName(className)) { + // this is special case - these classes are defined in a non-existent package + // and we need to use a classloader (public lookup will not allow this, and private lookup is not + // possible for an empty package) return wrapCl(originalClass.getClassLoader()) .doDefineClass(originalClass, className, classBytes, off, len, protectionDomain); } + // any other class should be defined using a private lookup + try { + return defineClassPrivateLookup(originalClass, className, classBytes, off, len); + } catch (Exception e) { + LOGGER.log(Level.FINEST, "Failed to create class " + className + " using private lookup", e); + + throw e; + } } @Override @@ -101,7 +120,11 @@ public Class loadClass(Class originalClass, String classBinaryName) throws return wrapCl(originalClass.getClassLoader()).loadClass(classBinaryName); } - private Class defineClassSamePackage(Class originalClass, String className, byte[] classBytes, int off, int len) { + private boolean weldInternalProxyClassName(String className) { + return className.startsWith(WELD_JAVAX_PREFIX) || className.startsWith(WELD_JAVA_PREFIX); + } + + private Class defineClassPrivateLookup(Class originalClass, String className, byte[] classBytes, int off, int len) { if (NativeImageHelper.isRuntime()) { throw new IllegalStateException("Cannot define class in native image. Class name: " + className + ", original " + "class: " + originalClass @@ -110,39 +133,64 @@ private Class defineClassSamePackage(Class originalClass, String className LOGGER.finest("Defining class " + className + " original class: " + originalClass.getName()); + MethodHandles.Lookup lookup; + try { - Module classModule = originalClass.getModule(); - if (!myModule.canRead(classModule)) { + // lookup class name "guessed" from the class name of the proxy + // proxy name must contain the $ - if it does not, we just use the originalClass as that is safe + int index = className.indexOf('$'); + + Class lookupClass; + if (index < 0) { + LOGGER.finest(() -> "Attempt to define a proxy class without a $ in its name. Class name: " + className + "," + + " original class name: " + originalClass.getName()); + lookupClass = originalClass; + } else { + // I would like to create a private lookup in the same package as the proxied class, so let's do it + // use the "extracted" lookup class name, if that fails, use the original class + lookupClass = tryLoading(originalClass, className.substring(0, index)); + } + + Module lookupClassModule = lookupClass.getModule(); + if (!myModule.canRead(lookupClassModule)) { // we need to read the module to be able to create a private lookup in it // it also needs to open the package we are doing the lookup in - myModule.addReads(classModule); + myModule.addReads(lookupClassModule); } + // next line would fail if the module does not open its package, with a very meaningful error message - MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(originalClass, MethodHandles.lookup()); - if (classBytes.length == len) { - return lookup.defineClass(classBytes); - } else { - byte[] bytes = new byte[len]; - System.arraycopy(classBytes, off, bytes, 0, len); - return lookup.defineClass(bytes); - } + lookup = MethodHandles.privateLookupIn(lookupClass, MethodHandles.lookup()); } catch (IllegalAccessException e) { throw new RuntimeException("Failed to define class " + className, e); } + + return defineClass(lookup, className, classBytes, off, len); } - private boolean samePackage(Class originalClass, String className) { - String origPackage = originalClass.getPackageName(); - String newPackage = packageName(className); - return newPackage.equals(origPackage); + private Class tryLoading(Class originalClass, String className) { + try { + return originalClass.getClassLoader().loadClass(className); + } catch (Exception e) { + LOGGER.log(Level.FINEST, "Attempt to load class " + className + " failed.", e); + return originalClass; + } } - private String packageName(String className) { - int index = className.lastIndexOf('.'); - if (index > 0) { - return className.substring(0, index); + private Class defineClass(MethodHandles.Lookup lookup, String className, byte[] classBytes, int off, int len) { + try { + byte[] definitionBytes; + + if (classBytes.length == len) { + definitionBytes = classBytes; + } else { + definitionBytes = new byte[len]; + System.arraycopy(classBytes, off, definitionBytes, 0, len); + } + + return lookup.defineClass(definitionBytes); + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to define class " + className, e); } - return ""; } private ClassDefiningCl wrapCl(ClassLoader origCl) { diff --git a/microprofile/config/src/main/java/module-info.java b/microprofile/config/src/main/java/module-info.java index 15ce3099d00..5d59995beb5 100644 --- a/microprofile/config/src/main/java/module-info.java +++ b/microprofile/config/src/main/java/module-info.java @@ -31,7 +31,7 @@ exports io.helidon.microprofile.config; // this is needed for CDI extensions that use non-public observer methods - opens io.helidon.microprofile.config to weld.core.impl; + opens io.helidon.microprofile.config to weld.core.impl, io.helidon.microprofile.cdi; provides javax.enterprise.inject.spi.Extension with io.helidon.microprofile.config.ConfigCdiExtension; } diff --git a/microprofile/fault-tolerance/src/main/java/module-info.java b/microprofile/fault-tolerance/src/main/java/module-info.java index 5cd0370e38f..78facb8d3c4 100644 --- a/microprofile/fault-tolerance/src/main/java/module-info.java +++ b/microprofile/fault-tolerance/src/main/java/module-info.java @@ -42,7 +42,7 @@ exports io.helidon.microprofile.faulttolerance; // needed when running with modules - to make private methods accessible - opens io.helidon.microprofile.faulttolerance to weld.core.impl; + opens io.helidon.microprofile.faulttolerance to weld.core.impl, io.helidon.microprofile.cdi; provides javax.enterprise.inject.spi.Extension with io.helidon.microprofile.faulttolerance.FaultToleranceExtension; } diff --git a/microprofile/health/src/main/java/module-info.java b/microprofile/health/src/main/java/module-info.java index 323e2d571ab..30c7076bdb5 100644 --- a/microprofile/health/src/main/java/module-info.java +++ b/microprofile/health/src/main/java/module-info.java @@ -38,7 +38,7 @@ exports io.helidon.microprofile.health; // this is needed for CDI extensions that use non-public observer methods - opens io.helidon.microprofile.health to weld.core.impl; + opens io.helidon.microprofile.health to weld.core.impl, io.helidon.microprofile.cdi; uses io.helidon.microprofile.health.HealthCheckProvider; diff --git a/microprofile/jwt-auth/src/main/java/module-info.java b/microprofile/jwt-auth/src/main/java/module-info.java index 73732a840c4..4365a72b89c 100644 --- a/microprofile/jwt-auth/src/main/java/module-info.java +++ b/microprofile/jwt-auth/src/main/java/module-info.java @@ -41,7 +41,7 @@ exports io.helidon.microprofile.jwt.auth; // this is needed for CDI extensions that use non-public observer methods - opens io.helidon.microprofile.jwt.auth to weld.core.impl; + opens io.helidon.microprofile.jwt.auth to weld.core.impl, io.helidon.microprofile.cdi; provides io.helidon.security.providers.common.spi.AnnotationAnalyzer with io.helidon.microprofile.jwt.auth.JwtAuthAnnotationAnalyzer; provides io.helidon.security.spi.SecurityProviderService with io.helidon.microprofile.jwt.auth.JwtAuthProviderService; diff --git a/microprofile/metrics/src/main/java/module-info.java b/microprofile/metrics/src/main/java/module-info.java index 13295670106..545f50fe239 100644 --- a/microprofile/metrics/src/main/java/module-info.java +++ b/microprofile/metrics/src/main/java/module-info.java @@ -37,7 +37,7 @@ exports io.helidon.microprofile.metrics; // this is needed for CDI extensions that use non-public observer methods - opens io.helidon.microprofile.metrics to weld.core.impl; + opens io.helidon.microprofile.metrics to weld.core.impl, io.helidon.microprofile.cdi; provides javax.enterprise.inject.spi.Extension with io.helidon.microprofile.metrics.MetricsCdiExtension; } diff --git a/microprofile/openapi/src/main/java/module-info.java b/microprofile/openapi/src/main/java/module-info.java index aa07c3bcc31..c9181c6eb7a 100644 --- a/microprofile/openapi/src/main/java/module-info.java +++ b/microprofile/openapi/src/main/java/module-info.java @@ -33,7 +33,7 @@ exports io.helidon.microprofile.openapi; // this is needed for CDI extensions that use non-public observer methods - opens io.helidon.microprofile.openapi to weld.core.impl; + opens io.helidon.microprofile.openapi to weld.core.impl, io.helidon.microprofile.cdi; provides Extension with OpenApiCdiExtension; } diff --git a/microprofile/security/src/main/java/module-info.java b/microprofile/security/src/main/java/module-info.java index 878860ffbc7..1eafa54a60d 100644 --- a/microprofile/security/src/main/java/module-info.java +++ b/microprofile/security/src/main/java/module-info.java @@ -31,7 +31,7 @@ exports io.helidon.microprofile.security; // this is needed for CDI extensions that use non-public observer methods - opens io.helidon.microprofile.security to weld.core.impl; + opens io.helidon.microprofile.security to weld.core.impl, io.helidon.microprofile.cdi; provides javax.enterprise.inject.spi.Extension with io.helidon.microprofile.security.SecurityCdiExtension; } diff --git a/microprofile/server/src/main/java/module-info.java b/microprofile/server/src/main/java/module-info.java index 5158ce58fb9..c04977b3a68 100644 --- a/microprofile/server/src/main/java/module-info.java +++ b/microprofile/server/src/main/java/module-info.java @@ -46,5 +46,5 @@ io.helidon.microprofile.server.JaxRsCdiExtension; // needed when running with modules - to make private methods accessible - opens io.helidon.microprofile.server to weld.core.impl; + opens io.helidon.microprofile.server to weld.core.impl, io.helidon.microprofile.cdi; } diff --git a/microprofile/tracing/src/main/java/module-info.java b/microprofile/tracing/src/main/java/module-info.java index 45e4a048cc8..34fcccec7c9 100644 --- a/microprofile/tracing/src/main/java/module-info.java +++ b/microprofile/tracing/src/main/java/module-info.java @@ -47,7 +47,7 @@ exports io.helidon.microprofile.tracing; // this is needed for CDI extensions that use non-public observer methods - opens io.helidon.microprofile.tracing to weld.core.impl,hk2.utils; + opens io.helidon.microprofile.tracing to weld.core.impl,hk2.utils, io.helidon.microprofile.cdi; provides Extension with io.helidon.microprofile.tracing.TracingCdiExtension; provides org.glassfish.jersey.internal.spi.AutoDiscoverable with io.helidon.microprofile.tracing.MpTracingAutoDiscoverable; diff --git a/microprofile/websocket/src/main/java/module-info.java b/microprofile/websocket/src/main/java/module-info.java index 3ff03032627..3938e79f3bf 100644 --- a/microprofile/websocket/src/main/java/module-info.java +++ b/microprofile/websocket/src/main/java/module-info.java @@ -36,7 +36,7 @@ exports io.helidon.microprofile.tyrus; // this is needed for CDI extensions that use non-public observer methods - opens io.helidon.microprofile.tyrus to weld.core.impl; + opens io.helidon.microprofile.tyrus to weld.core.impl, io.helidon.microprofile.cdi; provides javax.enterprise.inject.spi.Extension with io.helidon.microprofile.tyrus.WebSocketCdiExtension; } diff --git a/microprofile/weld/weld-core-impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java b/microprofile/weld/weld-core-impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java index f5f5e667de8..827691c0663 100644 --- a/microprofile/weld/weld-core-impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java +++ b/microprofile/weld/weld-core-impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java @@ -79,13 +79,16 @@ /* * This class is copied from Weld sources. - * The only modified method is createCompoundProxyName. + * Modified methods: + * - getProxyName + * - createCompoundProxyName + * * Why? * In original Weld, the name is generated with bean identifier that is based on identity hashCode - and that is OK as * long as you run in a single JVM (which is the case with hotspot). * When running in native image, we go through the process of generating proxies at build time (in GraalVM when building the * native image) and then running them from the native image. - * As these are two separate instances of JVM, we get different identity has codes, and as a result different class names + * As these are two separate instances of JVM, we get different identity hash codes, and as a result different class names * at compile time and at runtime. The Helidon change ensures these names are equal and we can reuse the generated proxy * classes. * @@ -271,8 +274,14 @@ static String getProxyName(String contextId, Class proxiedBeanType, Set iface : typeInfo.getInterfaces()) { @@ -308,6 +317,33 @@ public void addInterfacesFromTypeClosure(Set typeClosure, Class< /* * Helidon modification + * + * This is used when there is no enclosing type and we may have multiple interfaces + * This method ensures the superinterface is the base of the name + */ + private static String createProxyName(TypeInfo typeInfo) { + Class superInterface = typeInfo.getSuperInterface(); + StringBuilder name = new StringBuilder(); + List interfaces = new ArrayList(); + for (Class type : typeInfo.getInterfaces()) { + if (!type.equals(superInterface)) { + interfaces.add(uniqueName(type)); + } + } + + Collections.sort(interfaces); + for (final String iface : interfaces) { + name.append(iface); + name.append('$'); + } + + return superInterface.getName() + '$' + name; + } + + /* + * Helidon modification + * + * Compound name is used when more than one interface needs to be proxied. */ private static String createCompoundProxyName(String contextId, Bean bean, TypeInfo typeInfo, StringBuilder name) { final List interfaces = new ArrayList(); diff --git a/security/integration/jersey/src/main/java/module-info.java b/security/integration/jersey/src/main/java/module-info.java index fcf00aecaf3..2b72a1c1e62 100644 --- a/security/integration/jersey/src/main/java/module-info.java +++ b/security/integration/jersey/src/main/java/module-info.java @@ -39,7 +39,7 @@ exports io.helidon.security.integration.jersey; // needed for jersey injection - opens io.helidon.security.integration.jersey to hk2.locator,hk2.utils,weld.core.impl; + opens io.helidon.security.integration.jersey to hk2.locator,hk2.utils,weld.core.impl, io.helidon.microprofile.cdi; uses io.helidon.security.providers.common.spi.AnnotationAnalyzer; } diff --git a/security/security/src/main/java/module-info.java b/security/security/src/main/java/module-info.java index 900c2054b0c..99df07d3f4b 100644 --- a/security/security/src/main/java/module-info.java +++ b/security/security/src/main/java/module-info.java @@ -43,7 +43,7 @@ exports io.helidon.security.internal to io.helidon.security.integration.jersey, io.helidon.security.integration.webserver, io.helidon.security.integration.grpc; // needed for CDI integration - opens io.helidon.security to weld.core.impl; + opens io.helidon.security to weld.core.impl, io.helidon.microprofile.cdi; uses io.helidon.security.spi.SecurityProviderService; } diff --git a/tests/apps/bookstore/common/src/main/java/module-info.java b/tests/apps/bookstore/common/src/main/java/module-info.java index 9a2a6761ea5..6873d919396 100644 --- a/tests/apps/bookstore/common/src/main/java/module-info.java +++ b/tests/apps/bookstore/common/src/main/java/module-info.java @@ -21,7 +21,7 @@ requires jakarta.enterprise.cdi.api; - opens io.helidon.tests.apps.bookstore.common to weld.core.impl; + opens io.helidon.tests.apps.bookstore.common to weld.core.impl, io.helidon.microprofile.cdi; exports io.helidon.tests.apps.bookstore.common; } diff --git a/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/BeanProducer.java b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/BeanProducer.java new file mode 100644 index 00000000000..a5125d59723 --- /dev/null +++ b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/BeanProducer.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 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.tests.integration.nativeimage.mp1; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; + +import io.helidon.tests.integration.nativeimage.mp1.other.ProducedBean; + +@ApplicationScoped +public class BeanProducer { + public static final String VALUE = "hi there"; + + @Produces + @ApplicationScoped + public ProducedBean produceBean() { + return new ProducedBean(VALUE); + } +} diff --git a/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/Mp1Main.java b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/Mp1Main.java index 5671c175fea..50bcc65a054 100644 --- a/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/Mp1Main.java +++ b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/Mp1Main.java @@ -177,6 +177,9 @@ private static void testBean(int port, String jwtToken) { // CDI - (tested indirectly by other tests) // Server - capability to start JAX-RS (tested indirectly by other tests) + // produce a bean with package local method + invoke(collector, "Produced bean", BeanProducer.VALUE, aBean::produced); + // Configuration invoke(collector, "Config injection", "Properties message", aBean::config); diff --git a/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/TestBean.java b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/TestBean.java index f9714b8710f..72dc7ddba6f 100644 --- a/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/TestBean.java +++ b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/TestBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020 Oracle and/or its affiliates. */ package io.helidon.tests.integration.nativeimage.mp1; @@ -14,6 +14,8 @@ import javax.inject.Inject; import io.helidon.microprofile.server.ServerCdiExtension; +import io.helidon.tests.integration.nativeimage.mp1.other.BeanProcessor; +import io.helidon.tests.integration.nativeimage.mp1.other.ProducedBean; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.faulttolerance.Asynchronous; @@ -40,6 +42,9 @@ public class TestBean { @Inject private BeanManager beanManager; + @Inject + private ProducedBean producedBean; + private final AtomicInteger retries = new AtomicInteger(); @Timed @@ -109,4 +114,8 @@ public String timeout() { public CompletionStage asynchronous() { return CompletableFuture.completedFuture("Async response"); } + + public String produced() { + return BeanProcessor.getProducedName(producedBean); + } } diff --git a/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/other/BeanProcessor.java b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/other/BeanProcessor.java new file mode 100644 index 00000000000..04438ca0700 --- /dev/null +++ b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/other/BeanProcessor.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 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.tests.integration.nativeimage.mp1.other; + +public final class BeanProcessor { + + public static String getProducedName(ProducedBean bean) { + Class sampleClass = ProducedBean.class; + Class proxyClass = bean.getClass(); + + Package samplePackage = sampleClass.getPackage(); + Package proxyPackage = proxyClass.getPackage(); + + System.out.println(samplePackage); + System.out.println(proxyPackage); + System.out.println("Equals: " + samplePackage.equals(proxyPackage)); + + String name = bean.getName(); + return name; + } + +} diff --git a/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/other/ProducedBean.java b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/other/ProducedBean.java new file mode 100644 index 00000000000..710c60ce822 --- /dev/null +++ b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/other/ProducedBean.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020 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.tests.integration.nativeimage.mp1.other; + +import java.util.Objects; + +/** + * A bean produced by a producer in a different package. + */ +public class ProducedBean { + + private final String name; + + /** + * Constructor to create a new instance outside of CDI. + * + * @param name name to use + */ + public ProducedBean(final String name) { + this.name = Objects.requireNonNull(name); + } + + // Add public to make it work + String getName() { + return name; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProducedBean myClass = (ProducedBean) o; + return Objects.equals(name, myClass.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } +} diff --git a/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/other/package-info.java b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/other/package-info.java new file mode 100644 index 00000000000..e2c09cfbd69 --- /dev/null +++ b/tests/integration/native-image/mp-1/src/main/java/io/helidon/tests/integration/nativeimage/mp1/other/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 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. + */ +/** + * This package exists to make sure we can do proxies that have working + * package local + */ +package io.helidon.tests.integration.nativeimage.mp1.other; \ No newline at end of file diff --git a/tests/integration/native-image/mp-1/src/main/java/module-info.java b/tests/integration/native-image/mp-1/src/main/java/module-info.java index c554275ec6d..292c029f1ac 100644 --- a/tests/integration/native-image/mp-1/src/main/java/module-info.java +++ b/tests/integration/native-image/mp-1/src/main/java/module-info.java @@ -37,9 +37,11 @@ requires io.helidon.health.checks; exports io.helidon.tests.integration.nativeimage.mp1; + exports io.helidon.tests.integration.nativeimage.mp1.other; // opens is needed to inject private fields, create classes in the same package (proxy) opens io.helidon.tests.integration.nativeimage.mp1 to weld.core.impl, hk2.utils, io.helidon.microprofile.cdi; + opens io.helidon.tests.integration.nativeimage.mp1.other to weld.core.impl, io.helidon.microprofile.cdi; // we need to open the static resource on classpath directory to everybody, as otherwise // static content will not see it diff --git a/tests/integration/native-image/mp-3/src/main/java/module-info.java b/tests/integration/native-image/mp-3/src/main/java/module-info.java index 6168ba6cb57..03f803a435f 100644 --- a/tests/integration/native-image/mp-3/src/main/java/module-info.java +++ b/tests/integration/native-image/mp-3/src/main/java/module-info.java @@ -4,5 +4,5 @@ exports io.helidon.tests.integration.nativeimage.mp3; - opens io.helidon.tests.integration.nativeimage.mp3 to weld.core.impl,hk2.utils; + opens io.helidon.tests.integration.nativeimage.mp3 to weld.core.impl,hk2.utils, io.helidon.microprofile.cdi; } \ No newline at end of file