mirror of
https://github.com/jlengrand/helidon.git
synced 2026-03-10 08:21:17 +00:00
Support for bean producers in different package than beans that have … (#2241)
* Support for bean producers in different package than beans that have package local methods. * Update to proxy services - name is generated with super interface first - proxy classes are defined using private lookup - proxy classes are defined using a class loader for weld specific packages Signed-off-by: Tomas Langer <tomas.langer@oracle.com>
This commit is contained in:
@@ -33,5 +33,5 @@ module io.helidon.health.checks {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ module io.helidon.microprofile.accesslog {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.security.ProtectionDomain;
|
||||
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 @@ import org.jboss.weld.serialization.spi.ProxyServices;
|
||||
|
||||
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<ClassLoader, ClassDefiningCl> classLoaders = Collections.synchronizedMap(new IdentityHashMap<>());
|
||||
private final ClassLoader contextCl;
|
||||
@@ -69,14 +73,20 @@ class HelidonProxyServices implements ProxyServices {
|
||||
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 @@ class HelidonProxyServices implements ProxyServices {
|
||||
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 @@ class HelidonProxyServices implements ProxyServices {
|
||||
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 @@ class HelidonProxyServices implements ProxyServices {
|
||||
|
||||
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 String packageName(String className) {
|
||||
int index = className.lastIndexOf('.');
|
||||
if (index > 0) {
|
||||
return className.substring(0, index);
|
||||
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 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) {
|
||||
|
||||
@@ -31,7 +31,7 @@ module io.helidon.microprofile.config {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ module io.helidon.microprofile.faulttolerance {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ module io.helidon.microprofile.health {
|
||||
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;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ module io.helidon.microprofile.jwt.auth {
|
||||
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;
|
||||
|
||||
@@ -33,7 +33,7 @@ module io.helidon.microprofile.openapi {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ module io.helidon.microprofile.security {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -46,5 +46,5 @@ module io.helidon.microprofile.server {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ module io.helidon.microprofile.tracing {
|
||||
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;
|
||||
|
||||
@@ -36,7 +36,7 @@ module io.helidon.microprofile.tyrus {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -79,13 +79,16 @@ import static org.jboss.weld.util.reflection.Reflections.cast;
|
||||
|
||||
/*
|
||||
* 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 @@ public class ProxyFactory<T> implements PrivilegedAction<T> {
|
||||
|
||||
if (typeInfo.getSuperClass() == Object.class) {
|
||||
final StringBuilder name = new StringBuilder();
|
||||
//interface only bean.
|
||||
className = createCompoundProxyName(contextId, bean, typeInfo, name) + PROXY_SUFFIX;
|
||||
|
||||
// for classes that do not have an enclosing class, we want the super interface to be first
|
||||
if (proxiedBeanType.getEnclosingClass() == null) {
|
||||
return createProxyName(typeInfo) + PROXY_SUFFIX;
|
||||
} else {
|
||||
//interface only bean.
|
||||
className = createCompoundProxyName(contextId, bean, typeInfo, name) + PROXY_SUFFIX;
|
||||
}
|
||||
} else {
|
||||
boolean typeModified = false;
|
||||
for (Class<?> iface : typeInfo.getInterfaces()) {
|
||||
@@ -308,6 +317,33 @@ public class ProxyFactory<T> implements PrivilegedAction<T> {
|
||||
|
||||
/*
|
||||
* 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<String> interfaces = new ArrayList<String>();
|
||||
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<String> interfaces = new ArrayList<String>();
|
||||
|
||||
@@ -39,7 +39,7 @@ module io.helidon.security.integration.jersey {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ module io.helidon.security {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ module io.helidon.tests.apps.bookstore.common {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -177,6 +177,9 @@ public final class Mp1Main {
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -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.enterprise.inject.spi.BeanManager;
|
||||
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 class TestBean {
|
||||
public CompletionStage<String> asynchronous() {
|
||||
return CompletableFuture.completedFuture("Async response");
|
||||
}
|
||||
|
||||
public String produced() {
|
||||
return BeanProcessor.getProducedName(producedBean);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -37,9 +37,11 @@ module helidon.tests.nimage.mp {
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user