RequestScopeTest.java
/*
* Copyright (c) 2012, 2025 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.tests.e2e.common.process.internal;
import java.lang.reflect.Type;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import org.glassfish.jersey.inject.hk2.Hk2RequestScope;
import org.glassfish.jersey.internal.inject.ForeignDescriptor;
import org.glassfish.jersey.process.internal.RequestScope;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.utilities.AbstractActiveDescriptor;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test of the {@link RequestScope request scope}.
*
* @author Miroslav Fuksa
*/
public class RequestScopeTest {
@Test
public void testScopeWithCreatedInstance() {
final RequestScope requestScope = new Hk2RequestScope();
assertNull(requestScope.suspendCurrent());
final Hk2RequestScope.Instance context = (Hk2RequestScope.Instance) requestScope.createContext();
ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
context.put(inhab, "1");
requestScope.runInScope(context, () -> {
assertEquals("1", context.get(inhab));
context.release();
assertEquals("1", context.get(inhab));
});
assertNull(context.get(inhab));
}
@Test
public void testScopeReleaseInsideScope() {
final RequestScope requestScope = new Hk2RequestScope();
assertNull(requestScope.suspendCurrent());
final Hk2RequestScope.Instance instance = (Hk2RequestScope.Instance) requestScope.createContext();
ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
instance.put(inhab, "1");
requestScope.runInScope(instance, () -> {
final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
assertEquals(internalInstance, instance);
assertEquals("1", instance.get(inhab));
instance.release();
assertEquals("1", instance.get(inhab));
});
assertEquals("1", instance.get(inhab));
instance.release();
assertNull(instance.get(inhab));
}
@Test
public void testScopeWithImplicitInstance() throws Exception {
final RequestScope requestScope = new Hk2RequestScope();
assertNull(requestScope.suspendCurrent());
ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
final Hk2RequestScope.Instance instance = requestScope.runInScope(() -> {
final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
assertNull(internalInstance.get(inhab));
internalInstance.put(inhab, "1");
assertEquals("1", internalInstance.get(inhab));
return internalInstance;
});
assertEquals("1", instance.get(inhab));
instance.release();
assertNull(instance.get(inhab));
}
@Test
public void testScopeWithTwoInternalTasks() throws Exception {
final RequestScope requestScope = new Hk2RequestScope();
assertNull(requestScope.suspendCurrent());
ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
final Hk2RequestScope.Instance instance = requestScope.runInScope(() -> {
final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
final Hk2RequestScope.Instance anotherInstance = requestScope.runInScope(() -> {
final Hk2RequestScope.Instance currentInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
assertTrue(!currentInstance.equals(internalInstance));
currentInstance.put(inhab, "1");
return currentInstance;
});
assertTrue(!anotherInstance.equals(internalInstance));
assertEquals("1", anotherInstance.get(inhab));
anotherInstance.release();
assertNull(anotherInstance.get(inhab));
return internalInstance;
});
instance.release();
assertNull(instance.get(inhab));
}
@Test
public void testMultipleGetInstanceCalls() throws Exception {
final RequestScope requestScope = new Hk2RequestScope();
assertNull(requestScope.suspendCurrent());
ForeignDescriptor inhab = ForeignDescriptor.wrap(new TestProvider("a"));
final Hk2RequestScope.Instance instance = requestScope.runInScope(() -> {
final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.suspendCurrent();
internalInstance.put(inhab, "1");
requestScope.suspendCurrent();
requestScope.suspendCurrent();
requestScope.suspendCurrent();
requestScope.suspendCurrent();
return internalInstance;
});
assertEquals("1", instance.get(inhab));
instance.release();
assertEquals("1", instance.get(inhab));
instance.release();
assertEquals("1", instance.get(inhab));
instance.release();
assertEquals("1", instance.get(inhab));
instance.release();
assertEquals("1", instance.get(inhab));
instance.release();
assertNull(instance.get(inhab));
}
@Test
public void testOrderOfRelease() {
final RequestScope requestScope = new Hk2RequestScope();
final AtomicInteger instanceRelease = new AtomicInteger(0);
final Hk2RequestScope.Instance instance = requestScope.runInScope(() -> {
final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.current();
for (int index = 1; index != 10; index++) {
final int in = index;
TestProvider testProvider = new TestProvider(String.valueOf(in)) {
@Override
public int hashCode() {
return super.hashCode() + in;
}
};
final ForeignDescriptor fd = ForeignDescriptor.wrap(testProvider, new Consumer<Object>() {
@Override
public void accept(Object o) {
instanceRelease.set(instanceRelease.get() * 10 + in);
}
});
internalInstance.put(fd, String.valueOf(index));
}
return internalInstance;
});
instance.release();
Assertions.assertEquals(987654321, instanceRelease.get());
}
@Test
public void testMultipleReleases() throws InterruptedException {
final RequestScope requestScope = new Hk2RequestScope();
final AtomicBoolean passed = new AtomicBoolean(true);
final int CNT = 200;
Thread[] thread = new Thread[CNT];
Hk2RequestScope.Instance instance = requestScope.runInScope(() -> {
final Hk2RequestScope.Instance internalInstance = (Hk2RequestScope.Instance) requestScope.current();
for (int index = 1; index != CNT; index++) {
TestProvider testProvider = new TestProvider(String.valueOf(index)) {
@Override
public int hashCode() {
return super.hashCode() + Integer.parseInt(id);
}
};
final ForeignDescriptor fd = ForeignDescriptor.wrap(testProvider, new Consumer<Object>() {
@Override
public void accept(Object o) {
// noop
}
});
internalInstance.put(fd, String.valueOf(index));
for (int i = 0; i != CNT; i++) {
thread[i] = new Thread(new Runnable() {
@Override
public void run() {
final long waitTime = (int) (Math.random() * 5 + 1) * 10L;
try {
Thread.sleep(waitTime);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
internalInstance.release();
} catch (Throwable throwable) {
passed.set(false);
}
}
});
}
for (int i = 0; i != CNT; i++) {
thread[i].start();
}
}
return internalInstance;
});
for (int i = 0; i != CNT; i++) {
thread[i].join();
}
Assertions.assertTrue(passed.get());
}
/**
* Test request scope inhabitant.
*/
public static class TestProvider extends AbstractActiveDescriptor<String> {
public final String id;
public TestProvider(final String id) {
super();
this.id = id;
}
@Override
public Class<?> getImplementationClass() {
return String.class;
}
@Override
public Type getImplementationType() {
return getImplementationClass();
}
@Override
public String create(final ServiceHandle<?> root) {
return id;
}
}
}