Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit 26d0f15

Browse files
author
Adam Lindenthal
committed
Merge pull request #173 from jordmoz/master
JERSEY-2291: Enable HK2 Immediate scope to support HK2 @Immediate services.
2 parents a7f358a + 3e9fccb commit 26d0f15

File tree

3 files changed

+143
-20
lines changed

3 files changed

+143
-20
lines changed

core-client/src/test/java/org/glassfish/jersey/client/ShutdownHookLeakTest.java

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,29 +39,29 @@
3939
*/
4040
package org.glassfish.jersey.client;
4141

42+
import static org.hamcrest.CoreMatchers.is;
43+
import static org.hamcrest.number.OrderingComparison.lessThan;
44+
import static org.junit.Assert.assertThat;
45+
46+
import java.lang.ref.WeakReference;
4247
import java.lang.reflect.Field;
4348
import java.util.Collection;
4449

4550
import javax.ws.rs.client.Client;
4651
import javax.ws.rs.client.ClientBuilder;
47-
import javax.ws.rs.client.Invocation.Builder;
4852
import javax.ws.rs.client.WebTarget;
4953

5054
import org.junit.Test;
5155

52-
import static org.hamcrest.CoreMatchers.equalTo;
53-
import static org.hamcrest.CoreMatchers.is;
54-
import static org.hamcrest.number.OrderingComparison.lessThan;
55-
import static org.junit.Assert.assertThat;
56-
5756
/**
5857
* Reproducer for JERSEY-2786.
5958
*
6059
* @author Jakub Podlesak (jakub.podlesak at oracle.com)
6160
*/
6261
public class ShutdownHookLeakTest {
6362

64-
private final int ITERATIONS = 1000;
63+
private static final int ITERATIONS = 4000;
64+
private static final int THRESHOLD = ITERATIONS * 2 / 3;
6565

6666
@Test
6767
public void testShutdownHookDoesNotLeak() throws Exception {
@@ -71,27 +71,41 @@ public void testShutdownHookDoesNotLeak() throws Exception {
7171
final Collection shutdownHooks = getShutdownHooks(client);
7272

7373
for (int i = 0; i < ITERATIONS; i++) {
74-
WebTarget target2 = target.property("Washington", "Irving");
75-
Builder req = target2.request().property("how", "now").property("and", "what");
76-
req.buildGet().property("Irving", "Washington").property("Thomas", "Alva");
74+
// Create/Initialize client runtime.
75+
target.property("Washington", "Irving")
76+
.request()
77+
.property("how", "now")
78+
.buildGet()
79+
.property("Irving", "Washington");
7780
}
7881

79-
assertThat(
80-
"shutdown hook deque size should not copy number of property invocation",
81-
// 66 % seems like a reasonable threshold for this test to keep it stable
82-
shutdownHooks.size(), is(lessThan(2 * ITERATIONS / 3)));
82+
System.gc();
8383

84-
client.close();
84+
int notEnqueued = 0;
85+
int notNull = 0;
86+
for (Object o : shutdownHooks) {
87+
if (((WeakReference<JerseyClient.ShutdownHook>) o).get() != null) {
88+
notNull++;
89+
}
90+
if (!((WeakReference<JerseyClient.ShutdownHook>) o).isEnqueued()) {
91+
notEnqueued++;
92+
}
93+
}
8594

8695
assertThat(
87-
"shutdown hook deque size should be empty after Client closed",
88-
shutdownHooks.size(), is(equalTo(0)));
96+
"Non-null shutdown hook references count should not copy number of property invocation",
97+
// 66 % seems like a reasonable threshold for this test to keep it stable
98+
notNull, is(lessThan(THRESHOLD)));
8999

100+
assertThat(
101+
"Shutdown hook references count not enqueued in the ReferenceQueue should not copy number of property invocation",
102+
// 66 % seems like a reasonable threshold for this test to keep it stable
103+
notEnqueued, is(lessThan(THRESHOLD)));
90104
}
91105

92-
private Collection getShutdownHooks(javax.ws.rs.client.Client client) throws NoSuchFieldException, IllegalAccessException {
93-
JerseyClient jerseyClient = (JerseyClient) client;
94-
Field shutdownHooksField = JerseyClient.class.getDeclaredField("shutdownHooks");
106+
private Collection getShutdownHooks(final Client client) throws NoSuchFieldException, IllegalAccessException {
107+
final JerseyClient jerseyClient = (JerseyClient) client;
108+
final Field shutdownHooksField = JerseyClient.class.getDeclaredField("shutdownHooks");
95109
shutdownHooksField.setAccessible(true);
96110
return (Collection) shutdownHooksField.get(jerseyClient);
97111
}

core-common/src/main/java/org/glassfish/jersey/internal/inject/Injections.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ private static ServiceLocator _createLocator(final String name, final ServiceLoc
139139

140140
result.setNeutralContextClassLoader(false);
141141
ServiceLocatorUtilities.enablePerThreadScope(result);
142+
ServiceLocatorUtilities.enableImmediateScope(result);
142143

143144
for (final Binder binder : binders) {
144145
bind(result, binder);
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3+
*
4+
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
5+
*
6+
* The contents of this file are subject to the terms of either the GNU
7+
* General Public License Version 2 only ("GPL") or the Common Development
8+
* and Distribution License("CDDL") (collectively, the "License"). You
9+
* may not use this file except in compliance with the License. You can
10+
* obtain a copy of the License at
11+
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
12+
* or packager/legal/LICENSE.txt. See the License for the specific
13+
* language governing permissions and limitations under the License.
14+
*
15+
* When distributing the software, include this License Header Notice in each
16+
* file and include the License file at packager/legal/LICENSE.txt.
17+
*
18+
* GPL Classpath Exception:
19+
* Oracle designates this particular file as subject to the "Classpath"
20+
* exception as provided by Oracle in the GPL Version 2 section of the License
21+
* file that accompanied this code.
22+
*
23+
* Modifications:
24+
* If applicable, add the following below the License Header, with the fields
25+
* enclosed by brackets [] replaced by your own identifying information:
26+
* "Portions Copyright [year] [name of copyright owner]"
27+
*
28+
* Contributor(s):
29+
* If you wish your version of this file to be governed by only the CDDL or
30+
* only the GPL Version 2, indicate your decision by adding "[Contributor]
31+
* elects to include this software in this distribution under the [CDDL or GPL
32+
* Version 2] license." If you don't indicate a single choice of license, a
33+
* recipient has the option to distribute your version of this file under
34+
* either the CDDL, the GPL Version 2 or to extend the choice of license to
35+
* its licensees as provided above. However, if you add GPL Version 2 code
36+
* and therefore, elected the GPL Version 2 license, then the option applies
37+
* only if the new code is made subject to such option by the copyright
38+
* holder.
39+
*/
40+
41+
package org.glassfish.jersey.internal.inject;
42+
43+
import static org.junit.Assert.assertTrue;
44+
45+
import java.util.concurrent.CountDownLatch;
46+
import java.util.concurrent.TimeUnit;
47+
48+
import javax.inject.Inject;
49+
50+
import org.glassfish.hk2.api.Immediate;
51+
import org.glassfish.hk2.api.ServiceLocator;
52+
import org.glassfish.hk2.utilities.binding.AbstractBinder;
53+
import org.junit.Test;
54+
55+
/**
56+
* Test for the {@link Injections} class.
57+
*
58+
* @author Jord Sonneveld ([email protected])
59+
*
60+
*/
61+
public class InjectionsTest {
62+
63+
/**
64+
* Verify that services marked with the HK2 Immediate annotation are indeed
65+
* created "immediately" (or at least "soon").
66+
*
67+
* Because Immediate services are instantiated in a separate thread, we use
68+
* a {@link CountDownLatch} to wait for the service to be created.
69+
*
70+
* After the {@link ServiceLocator} is created, we specifically do not call
71+
* any more methods on it: the locator must instantiate the Immediate
72+
* service without any further prompting to the locator.
73+
*
74+
* @throws InterruptedException if awaiting on the latch is interrupted.
75+
*/
76+
@Test
77+
public void testHK2ImmediateAnnotation() throws InterruptedException {
78+
final CountDownLatch latch = new CountDownLatch(1);
79+
80+
@SuppressWarnings("unused") // It is unused by design
81+
ServiceLocator sl = Injections.createLocator(new AbstractBinder() {
82+
@Override
83+
protected void configure() {
84+
bind(latch).to(CountDownLatch.class);
85+
bind(ImmediateMe.class).to(ImmediateMe.class).in(
86+
Immediate.class);
87+
}
88+
});
89+
90+
// 10 seconds is a LONG time. It should be faster than that. However, 10
91+
// seconds gives us a reasonable upper limit to wait in case the test
92+
// fails.
93+
assertTrue("Latch should be unlocked within 10 seconds.",
94+
latch.await(10, TimeUnit.SECONDS));
95+
}
96+
97+
/**
98+
* Helper class for testing Immediate services.
99+
*
100+
*/
101+
public static final class ImmediateMe {
102+
@Inject
103+
public ImmediateMe(CountDownLatch latch) {
104+
latch.countDown();
105+
}
106+
}
107+
108+
}

0 commit comments

Comments
 (0)