ee.jakarta.tck.concurrent.spec.Platform.anno.AnnotationServlet Maven / Gradle / Ivy
/*
* Copyright (c) 2024 Contributors to the Eclipse Foundation
*
* 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 ee.jakarta.tck.concurrent.spec.Platform.anno;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static jakarta.enterprise.concurrent.ContextServiceDefinition.APPLICATION;
import static jakarta.enterprise.concurrent.ContextServiceDefinition.TRANSACTION;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import ee.jakarta.tck.concurrent.common.context.IntContext;
import ee.jakarta.tck.concurrent.common.context.StringContext;
import ee.jakarta.tck.concurrent.common.qualifiers.CustomQualifier1;
import ee.jakarta.tck.concurrent.common.qualifiers.CustomQualifier2;
import ee.jakarta.tck.concurrent.common.qualifiers.InvalidQualifier3;
import ee.jakarta.tck.concurrent.common.qualifiers.OverwrittenQualifier4;
import ee.jakarta.tck.concurrent.framework.TestServlet;
import jakarta.annotation.Resource;
import jakarta.ejb.EJB;
import jakarta.enterprise.concurrent.ContextService;
import jakarta.enterprise.concurrent.ContextServiceDefinition;
import jakarta.enterprise.concurrent.ManagedExecutorDefinition;
import jakarta.enterprise.concurrent.ManagedExecutorService;
import jakarta.enterprise.concurrent.ManagedScheduledExecutorDefinition;
import jakarta.enterprise.concurrent.ManagedScheduledExecutorService;
import jakarta.enterprise.concurrent.ManagedThreadFactory;
import jakarta.enterprise.concurrent.ManagedThreadFactoryDefinition;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.spi.CDI;
import jakarta.inject.Inject;
import jakarta.servlet.annotation.WebServlet;
import jakarta.transaction.Status;
import jakarta.transaction.UserTransaction;
@ContextServiceDefinition(
name = "java:app/concurrent/ContextE",
qualifiers = {CustomQualifier1.class},
cleared = {"IntContext"},
propagated = {APPLICATION, "StringContext"},
unchanged = {TRANSACTION})
@ManagedExecutorDefinition(
name = "java:app/concurrent/ExecutorE",
context = "java:app/concurrent/ContextE",
qualifiers = {CustomQualifier2.class},
maxAsync = 3)
@ManagedScheduledExecutorDefinition(
name = "java:app/concurrent/ScheduledExecutorE",
context = "java:app/concurrent/ContextE",
qualifiers = {CustomQualifier1.class, CustomQualifier2.class},
maxAsync = 2,
hungTaskThreshold = 200000)
@ManagedThreadFactoryDefinition(
name = "java:app/concurrent/ThreadFactoryE",
context = "java:app/concurrent/ContextE",
qualifiers = OverwrittenQualifier4.class, // overwritten via web.xml
priority = 6
)
@WebServlet("/AnnotationServlet")
@Dependent
public class AnnotationServlet extends TestServlet {
private static final long serialVersionUID = 1L;
private static final long MAX_WAIT_SECONDS = TimeUnit.MINUTES.toSeconds(2);
private static final Runnable NOOP_RUNNABLE = () -> { };
@EJB
private AnnotationTestBeanInterface enterpriseBean;
@Resource
private UserTransaction tx;
private Integer executeCallableWithContext(final ContextService svc, final int value) throws Exception {
try {
IntContext.set(value);
Callable result = svc.contextualCallable(() -> {
return IntContext.get();
});
return result.call();
} finally {
IntContext.set(0);
}
}
// Context Services
@Inject
private ContextService injectedDefContextSvc;
@Inject
@CustomQualifier1
private ContextService injectedContextE;
public void testAnnoDefinedContextServiceQualifiers() throws Throwable {
assertAll("Context Service Tests",
() -> assertNotNull(injectedDefContextSvc,
"Default contextService was not registered with default qualifier."),
() -> assertNotNull(injectedContextE,
"Annotation defined contextService was not registered with required qualifier."),
() -> assertTrue(CDI.current().select(ContextService.class, InvalidQualifier3.Literal.get()).isUnsatisfied(),
"A contextService was satisfied with a qualifier which was not defined in it's annotation")
);
// Verify injected and looked up default context service are the same
ContextService lookupDefContextSvc = InitialContext.doLookup("java:comp/DefaultContextService");
Integer expected1 = executeCallableWithContext(lookupDefContextSvc, 95);
Integer actual1 = executeCallableWithContext(injectedDefContextSvc, 95);
assertEquals(expected1, actual1, "Default Context Service behavior differed between injection and lookup");
// Verify injected and looked up annotation defined context service are the same
ContextService lookupContextE = InitialContext.doLookup("java:app/concurrent/ContextE");
assertEquals(Integer.valueOf(0), executeCallableWithContext(lookupContextE, 65),
"Annotation defined Context Service that was looked up did not clear the IntContext as configured.");
assertEquals(Integer.valueOf(0), executeCallableWithContext(injectedContextE, 85),
"Annotation defined Context Service that was injected based on a qualifier did not clear the IntContext as configured.");
}
// Managed Executor Services
@Inject
private ManagedExecutorService injectedDefMES;
@Inject
@CustomQualifier2
private ManagedExecutorService injectedMESE;
public void testAnnoDefinedManagedExecutorSvcQualifiers() throws Throwable {
assertAll("Managed Executor Service Tests",
() -> assertNotNull(injectedDefMES,
"Default managedExecutorService was not registered with default qualifier."),
() -> assertNotNull(injectedMESE,
"Annotation defined managedExecutorService was not registered with required qualifiers."),
() -> assertTrue(CDI.current().select(ManagedExecutorService.class, CustomQualifier2.Literal.get(), InvalidQualifier3.Literal.get()).isUnsatisfied(),
"A managedExecutorService was satisfied with both a required and non-required qualifier.")
);
// Verify injected and looked up default ManagedExecutorService behave the same
ManagedExecutorService lookupDefMES = InitialContext.doLookup("java:comp/DefaultManagedExecutorService");
ContextService lookupDefContextSvc = lookupDefMES.getContextService();
ContextService extractedDefContextSvc = injectedDefMES.getContextService();
Integer expected1 = executeCallableWithContext(lookupDefContextSvc, 95);
Integer actual1 = executeCallableWithContext(extractedDefContextSvc, 95);
assertEquals(expected1, actual1, "Default ManagedExecutorService behavior via context service differed between injection and lookup");
// Verify injected and looked up annotation defined ManagedExecutorService behave the same
ManagedExecutorService lookupMESE = InitialContext.doLookup("java:app/concurrent/ExecutorE");
ContextService lookupContextE = lookupMESE.getContextService();
ContextService extractedContextE = injectedMESE.getContextService();
assertEquals(Integer.valueOf(0), executeCallableWithContext(lookupContextE, 65),
"Annotation defined and looked up ManagedExecutorService was configured with a context service that did not clear the IntContext as configured.");
assertEquals(Integer.valueOf(0), executeCallableWithContext(extractedContextE, 85),
"Annotation defined and injected ManagedExecutorService was configured with a context service that did not clear the IntContext as configured.");
}
// Managed Scheduled Executor Services
@Inject
private ManagedScheduledExecutorService injectedDefMSES;
@Inject
@CustomQualifier1
@CustomQualifier2
private ManagedScheduledExecutorService injectedMSESE;
public void testAnnoDefinedManagedScheduledExecutorSvcQualifers() throws Throwable {
assertAll("Managed Scheduled Executor Service Tests",
() -> assertNotNull(injectedDefMSES,
"Default managedScheduledExecutorService was not registered with default qualifier."),
() -> assertNotNull(injectedMSESE,
"Annotation defined managedScheduledExecutorService was not registered with required qualifiers."),
() -> assertTrue(CDI.current().select(ManagedScheduledExecutorService.class, CustomQualifier1.Literal.get()).isResolvable(),
"A managedScheduledExecutorService was not satisfied with one of two configured qualifiers.")
);
// Verify injected and looked up default ManagedScheduledExecutorService behave the same
ManagedScheduledExecutorService lookupDefMSES = InitialContext.doLookup("java:comp/DefaultManagedScheduledExecutorService");
ContextService lookupDefContextSvc = lookupDefMSES.getContextService();
ContextService extractedDefContextSvc = injectedDefMSES.getContextService();
Integer expected1 = executeCallableWithContext(lookupDefContextSvc, 95);
Integer actual1 = executeCallableWithContext(extractedDefContextSvc, 95);
assertEquals(expected1, actual1, "Default ManagedScheduledExecutorService behavior via context service differed between injection and lookup");
// Verify injected and looked up annotation defined ManagedExecutorService behave the same
ManagedScheduledExecutorService lookupMSESE = InitialContext.doLookup("java:app/concurrent/ScheduledExecutorE");
ContextService lookupContextE = lookupMSESE.getContextService();
ContextService extractedContextE = injectedMSESE.getContextService();
assertEquals(Integer.valueOf(0), executeCallableWithContext(lookupContextE, 65),
"Annotation defined and looked up ManagedScheduledExecutorService was configured with a context service that did not clear the IntContext as configured.");
assertEquals(Integer.valueOf(0), executeCallableWithContext(extractedContextE, 85),
"Annotation defined and injected ManagedScheduledExecutorService was configured with a context service that did not clear the IntContext as configured.");
}
// Managed Thread Factory
@Inject
private ManagedThreadFactory injectedDefMTF;
@Resource(lookup = "java:app/concurrent/ThreadFactoryE")
private ManagedThreadFactory resourceMTFE;
// Qualifier on @ManagedThreadFactoryDefinition is only overridden in web mode
public void testAnnoDefinedManagedThreadFactoryQualifersFull() throws Throwable {
ManagedThreadFactory lookupDefMTF = InitialContext.doLookup("java:comp/DefaultManagedThreadFactory");
ManagedThreadFactory lookupMTFE = InitialContext.doLookup("java:app/concurrent/ThreadFactoryE");
assertAll("Thread Factory Tests",
() -> assertNotNull(injectedDefMTF,
"Default managedThreadFactory was not registered with default qualifier."),
() -> assertEquals(lookupDefMTF.newThread(NOOP_RUNNABLE).getPriority(), injectedDefMTF.newThread(NOOP_RUNNABLE).getPriority(),
"Default managedThreadFactory from injection and lookup did not have the same priority."),
() -> assertNotNull(resourceMTFE,
"Annotation defined managedThreadFactory with qualifiers could not be found via @Resource."),
() -> assertEquals(lookupMTFE.newThread(NOOP_RUNNABLE).getPriority(), resourceMTFE.newThread(NOOP_RUNNABLE).getPriority(),
"The managedThreadFactory from resource injection and lookup did not have the same priority."),
() -> assertTrue(CDI.current().select(ManagedThreadFactory.class, OverwrittenQualifier4.Literal.get()).isResolvable(),
"A managedThreadFactory was not satisfied with a required qualifier that was not overwritten by a deployment descriptor.")
);
}
// Qualifier on @ManagedThreadFactoryDefinition is overridden in web mode
public void testAnnoDefinedManagedThreadFactoryQualifersWeb() throws Throwable {
ManagedThreadFactory lookupDefMTF = InitialContext.doLookup("java:comp/DefaultManagedThreadFactory");
ManagedThreadFactory lookupMTFE = InitialContext.doLookup("java:app/concurrent/ThreadFactoryE");
assertAll("Thread Factory Tests",
() -> assertNotNull(injectedDefMTF,
"Default managedThreadFactory was not registered with default qualifier."),
() -> assertEquals(lookupDefMTF.newThread(NOOP_RUNNABLE).getPriority(), injectedDefMTF.newThread(NOOP_RUNNABLE).getPriority(),
"Default managedThreadFactory from injection and lookup did not have the same priority."),
() -> assertNotNull(resourceMTFE,
"Annotation defined managedThreadFactory with no qualifiers could not be found via @Resource."),
() -> assertEquals(lookupMTFE.newThread(NOOP_RUNNABLE).getPriority(), resourceMTFE.newThread(NOOP_RUNNABLE).getPriority(),
"The managedThreadFactory from resource injection and lookup did not have the same priority."),
() -> assertTrue(CDI.current().select(ManagedThreadFactory.class, OverwrittenQualifier4.Literal.get()).isUnsatisfied(),
"A managedThreadFactory was satisfied with a required qualifier that should have been overwritten by the deployment descriptor.")
);
}
public void testAnnotationDefinesContextService() throws Throwable {
ContextService contextSvc = InitialContext.doLookup("java:app/concurrent/ContextE");
Callable checkContextAndGetTransactionStatus;
tx.begin();
try {
IntContext.set(1001);
StringContext.set("testAnnotationDefinesContextService-1");
checkContextAndGetTransactionStatus = contextSvc.contextualCallable(() -> {
assertEquals(0, IntContext.get()); // cleared
assertEquals("testAnnotationDefinesContextService-1", StringContext.get()); // propagated
assertNotNull(InitialContext.doLookup("java:app/concurrent/ExecutorE")); // propagated
return tx.getStatus(); // unchanged
});
StringContext.set("testAnnotationDefinesContextService-2");
int status = checkContextAndGetTransactionStatus.call();
assertEquals(Status.STATUS_ACTIVE, status);
assertEquals(1001, IntContext.get()); // restored
assertEquals("testAnnotationDefinesContextService-2", StringContext.get()); // restored
} finally {
IntContext.set(0);
StringContext.set(null);
tx.rollback();
}
int status = checkContextAndGetTransactionStatus.call();
assertEquals(Status.STATUS_NO_TRANSACTION, status);
}
public void testAnnotationDefinesManagedExecutor() throws Throwable {
LinkedBlockingQueue © 2015 - 2025 Weber Informatics LLC | Privacy Policy