forked from eclipse-ee4j/jersey
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow SupplierClassBinding in ThreadScope in CDI
Signed-off-by: jansupol <[email protected]>
- Loading branch information
Showing
14 changed files
with
554 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
...ain/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierThreadScopeClassBean.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License v. 2.0, which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* This Source Code may also be made available under the following Secondary | ||
* Licenses when the conditions for such availability set forth in the | ||
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | ||
* version 2 with the GNU Classpath Exception, which is available at | ||
* https://www.gnu.org/software/classpath/license.html. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | ||
*/ | ||
|
||
package org.glassfish.jersey.inject.weld.internal.bean; | ||
|
||
import org.glassfish.jersey.internal.inject.SupplierClassBinding; | ||
import org.glassfish.jersey.internal.inject.SupplierInstanceBinding; | ||
import org.glassfish.jersey.internal.util.collection.LazyValue; | ||
import org.glassfish.jersey.internal.util.collection.Value; | ||
import org.glassfish.jersey.internal.util.collection.Values; | ||
import org.jboss.weld.bean.proxy.BeanInstance; | ||
import org.jboss.weld.bean.proxy.ProxyFactory; | ||
import org.jboss.weld.manager.BeanManagerImpl; | ||
|
||
import javax.enterprise.context.Dependent; | ||
import javax.enterprise.context.spi.CreationalContext; | ||
import javax.ws.rs.RuntimeType; | ||
import java.lang.annotation.Annotation; | ||
import java.util.concurrent.atomic.AtomicReference; | ||
import java.util.function.Supplier; | ||
|
||
|
||
/** | ||
* Creates an implementation of {@link javax.enterprise.inject.spi.Bean} interface using Jersey's {@link SupplierInstanceBinding}. | ||
* Binding provides the information about the bean also called {@link javax.enterprise.inject.spi.BeanAttributes} information. | ||
* The {@code Bean} does not use {@link org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget} because serves already | ||
* created proxy, therefore the create operation just return provided instance without any other contextual operation | ||
* (produce, inject, destroy). | ||
* <p> | ||
* This bean is special and is used only for service registered as a {@link org.glassfish.jersey.internal.inject.PerThread} and | ||
* works through the proxy which serves the correct instance per the given thread. | ||
* <p> | ||
* Register example: | ||
* <pre> | ||
* AbstractBinder { | ||
* @Override | ||
* protected void configure() { | ||
* bindFactory(MyFactoryInjectionSupplier.class) | ||
* .to(MyBean.class) | ||
* .in(PerThread.class); | ||
* } | ||
* } | ||
* </pre> | ||
* Inject example: | ||
* <pre> | ||
* @Path("/") | ||
* public class MyResource { | ||
* @Inject | ||
* private MyBean myBean; | ||
* } | ||
* </pre> | ||
*/ | ||
class SupplierThreadScopeClassBean extends JerseyBean<Object> { | ||
private final LazyValue<ThreadScopeBeanInstance<Object>> beanInstance; | ||
private final SupplierClassBinding binding; | ||
private final LazyValue<Object> proxy; | ||
private final AtomicReference<CreationalContext> creationalContextAtomicReference = new AtomicReference<>(); | ||
|
||
SupplierThreadScopeClassBean(RuntimeType runtimeType, | ||
SupplierClassBinding binding, | ||
SupplierClassBean supplierClassBean, | ||
BeanManagerImpl beanManager) { | ||
super(runtimeType, binding); | ||
this.binding = binding; | ||
this.beanInstance = Values.lazy((Value<ThreadScopeBeanInstance<Object>>) () -> { | ||
Supplier supplierInstance = supplierClassBean.create(creationalContextAtomicReference.get()); | ||
ThreadScopeBeanInstance scopeBeanInstance = | ||
new ThreadScopeBeanInstance(supplierInstance, this, beanManager.getContextId()); | ||
return scopeBeanInstance; | ||
}); | ||
this.proxy = Values.lazy((Value<Object>) () -> createClientProxy(beanInstance.get(), beanManager.getContextId())); | ||
} | ||
|
||
@Override | ||
public Class<? extends Annotation> getScope() { | ||
return Dependent.class; | ||
} | ||
|
||
@Override | ||
public Object create(CreationalContext<Object> ctx) { | ||
creationalContextAtomicReference.set(ctx); | ||
return proxy.get(); | ||
} | ||
|
||
@Override | ||
public void destroy(Object instance, CreationalContext<Object> creationalContext) { | ||
if (beanInstance.isInitialized()) { | ||
this.beanInstance.get().dispose(); | ||
} | ||
} | ||
|
||
@Override | ||
public Class<?> getBeanClass() { | ||
return (Class<?>) this.binding.getContracts().iterator().next(); | ||
} | ||
|
||
private <T> T createClientProxy(BeanInstance beanInstance, String contextId) { | ||
ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this); | ||
return factory.create(beanInstance); | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
...src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ThreadScopeBeanInstance.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License v. 2.0, which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* This Source Code may also be made available under the following Secondary | ||
* Licenses when the conditions for such availability set forth in the | ||
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | ||
* version 2 with the GNU Classpath Exception, which is available at | ||
* https://www.gnu.org/software/classpath/license.html. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | ||
*/ | ||
|
||
package org.glassfish.jersey.inject.weld.internal.bean; | ||
|
||
import org.jboss.weld.bean.StringBeanIdentifier; | ||
import org.jboss.weld.bean.proxy.ContextBeanInstance; | ||
|
||
import javax.enterprise.inject.spi.Bean; | ||
import javax.enterprise.inject.spi.PassivationCapable; | ||
import java.lang.reflect.Method; | ||
import java.util.WeakHashMap; | ||
import java.util.function.Supplier; | ||
|
||
/** | ||
* {@link org.glassfish.jersey.internal.inject.PerThread} scope bean instance used from | ||
* {@link InitializableSupplierThreadScopeBean} and {@link SupplierThreadScopeClassBean}. | ||
* | ||
* @param <T> Typed of the bean supplied by a {@code Supplier}. | ||
*/ | ||
class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> { | ||
|
||
private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>(); | ||
|
||
private final Supplier<T> supplier; | ||
|
||
/** | ||
* Creates a new invocation handler with supplier which provides a current injected value in proper scope. | ||
* | ||
* @param supplier provider of the value. | ||
*/ | ||
ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) { | ||
super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId); | ||
this.supplier = supplier; | ||
} | ||
|
||
@Override | ||
public Object invoke(Object obj, Method method, Object... arguments) throws Throwable { | ||
Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get()); | ||
return super.invoke(instance, method, arguments); | ||
} | ||
|
||
public void dispose() { | ||
this.instances.clear(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.