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

Commit 5f23719

Browse files
Michal GajdošGerrit Code Review
authored andcommitted
Merge "JERSEY-2320: EJB singleton bean registered as an exception mapper causes deployment failure. - added test case and fixed the original issue - added EJB stateless bean as exception mapper - made sure both EJB beans get properly injected"
2 parents e0f2002 + 0c9848e commit 5f23719

File tree

11 files changed

+485
-38
lines changed

11 files changed

+485
-38
lines changed

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

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,30 +41,37 @@
4141
package org.glassfish.jersey.internal;
4242

4343
import java.lang.reflect.ParameterizedType;
44+
import java.lang.reflect.Proxy;
4445
import java.lang.reflect.Type;
4546
import java.lang.reflect.TypeVariable;
47+
import java.util.Collection;
48+
import java.util.Comparator;
49+
import java.util.LinkedHashMap;
4650
import java.util.LinkedHashSet;
51+
import java.util.List;
4752
import java.util.Map;
53+
import java.util.Map.Entry;
4854
import java.util.Set;
55+
import java.util.SortedSet;
4956
import java.util.TreeMap;
57+
import java.util.TreeSet;
5058
import java.util.logging.Level;
5159
import java.util.logging.Logger;
52-
53-
import javax.ws.rs.ProcessingException;
54-
import javax.ws.rs.ext.ExceptionMapper;
55-
5660
import javax.inject.Inject;
5761
import javax.inject.Singleton;
58-
62+
import javax.ws.rs.ProcessingException;
63+
import javax.ws.rs.ext.ExceptionMapper;
64+
import org.glassfish.hk2.api.ActiveDescriptor;
65+
import org.glassfish.hk2.api.ServiceHandle;
66+
import org.glassfish.hk2.api.ServiceLocator;
67+
import org.glassfish.hk2.utilities.binding.AbstractBinder;
68+
import org.glassfish.jersey.internal.inject.CustomAnnotationImpl;
5969
import org.glassfish.jersey.internal.inject.Providers;
6070
import org.glassfish.jersey.internal.util.ReflectionHelper;
6171
import org.glassfish.jersey.internal.util.collection.ClassTypePair;
6272
import org.glassfish.jersey.spi.ExceptionMappers;
6373
import org.glassfish.jersey.spi.ExtendedExceptionMapper;
6474

65-
import org.glassfish.hk2.api.ServiceLocator;
66-
import org.glassfish.hk2.utilities.binding.AbstractBinder;
67-
6875
/**
6976
* {@link ExceptionMappers Exception mappers} implementation that aggregates
7077
* exception mappers and server as the main entry point for exception mapper
@@ -73,6 +80,7 @@
7380
* @author Paul Sandoz
7481
* @author Santiago Pericas-Geertsen (Santiago.PericasGeertsen at oracle.com)
7582
* @author Marek Potociar (marek.potociar at oracle.com)
83+
* @author Jakub Podlesak (jakub.podlesak at oracle.com)
7684
*/
7785
public class ExceptionMapperFactory implements ExceptionMappers {
7886
private static final Logger LOGGER = Logger.getLogger(ExceptionMapperFactory.class.getName());
@@ -90,10 +98,10 @@ protected void configure() {
9098

9199
private static class ExceptionMapperType {
92100

93-
ExceptionMapper mapper;
101+
ServiceHandle<ExceptionMapper> mapper;
94102
Class<? extends Throwable> exceptionType;
95103

96-
public ExceptionMapperType(final ExceptionMapper mapper, final Class<? extends Throwable> exceptionType) {
104+
public ExceptionMapperType(final ServiceHandle<ExceptionMapper> mapper, final Class<? extends Throwable> exceptionType) {
97105
this.mapper = mapper;
98106
this.exceptionType = exceptionType;
99107
}
@@ -121,7 +129,7 @@ private <T extends Throwable> ExceptionMapper<T> find(final Class<T> type, final
121129
for (final ExceptionMapperType mapperType : exceptionMapperTypes) {
122130
final int d = distance(type, mapperType.exceptionType);
123131
if (d >= 0) {
124-
orderedMappers.put(d, mapperType.mapper);
132+
orderedMappers.put(d, mapperType.mapper.getService());
125133
}
126134
}
127135

@@ -156,10 +164,44 @@ private <T extends Throwable> ExceptionMapper<T> find(final Class<T> type, final
156164
*/
157165
@Inject
158166
public ExceptionMapperFactory(final ServiceLocator locator) {
159-
for (final ExceptionMapper<?> mapper : Providers.getAllProviders(locator, ExceptionMapper.class)) {
160-
final Class<? extends Throwable> c = getExceptionType(mapper.getClass());
161-
if (c != null) {
162-
exceptionMapperTypes.add(new ExceptionMapperType(mapper, c));
167+
168+
final Collection<ServiceHandle<ExceptionMapper>> mapperHandles =
169+
Providers.getAllServiceHandles(locator, ExceptionMapper.class);
170+
171+
for (ServiceHandle<ExceptionMapper> mapperHandle : mapperHandles) {
172+
173+
final ExceptionMapper mapper = mapperHandle.getService();
174+
175+
if (Proxy.isProxyClass(mapper.getClass())) {
176+
177+
SortedSet<Class<? extends ExceptionMapper>> mapperTypes
178+
= new TreeSet<Class<? extends ExceptionMapper>>(new Comparator<Class<? extends ExceptionMapper>>() {
179+
180+
@Override
181+
public int compare(Class<? extends ExceptionMapper> o1, Class<? extends ExceptionMapper> o2) {
182+
return o1.isAssignableFrom(o2) ? -1 : 1;
183+
}
184+
});
185+
186+
final Set<Type> contracts = mapperHandle.getActiveDescriptor().getContractTypes();
187+
for (Type contract : contracts) {
188+
if (contract instanceof Class &&
189+
ExceptionMapper.class.isAssignableFrom((Class<?>)contract) && contract != ExceptionMapper.class) {
190+
mapperTypes.add((Class<? extends ExceptionMapper>) contract);
191+
}
192+
}
193+
194+
if (!mapperTypes.isEmpty()) {
195+
final Class<? extends Throwable> c = getExceptionType(mapperTypes.first());
196+
if (c != null) {
197+
exceptionMapperTypes.add(new ExceptionMapperType(mapperHandle, c));
198+
}
199+
}
200+
} else {
201+
final Class<? extends Throwable> c = getExceptionType(mapper.getClass());
202+
if (c != null) {
203+
exceptionMapperTypes.add(new ExceptionMapperType(mapperHandle, c));
204+
}
163205
}
164206
}
165207
}
@@ -258,4 +300,4 @@ private Class getResolvedType(final Type t, final Class c, final Class dc) {
258300
return null;
259301
}
260302
}
261-
}
303+
}

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

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public void dispose(final T instance) {
182182
* @return set of all available default service provider instances for the contract.
183183
*/
184184
public static <T> Set<T> getProviders(final ServiceLocator locator, final Class<T> contract) {
185-
final Collection<ServiceHandle<T>> hk2Providers = getAllServiceHandles(locator, contract);
185+
final Collection<ServiceHandle<T>> hk2Providers = getServiceHandles(locator, contract);
186186
return getClasses(hk2Providers);
187187
}
188188

@@ -196,7 +196,7 @@ public static <T> Set<T> getProviders(final ServiceLocator locator, final Class<
196196
* @return set of all available service provider instances for the contract.
197197
*/
198198
public static <T> Set<T> getCustomProviders(final ServiceLocator locator, final Class<T> contract) {
199-
final Collection<ServiceHandle<T>> hk2Providers = getAllServiceHandles(locator, contract, new CustomAnnotationImpl());
199+
final Collection<ServiceHandle<T>> hk2Providers = getServiceHandles(locator, contract, new CustomAnnotationImpl());
200200
return getClasses(hk2Providers);
201201
}
202202

@@ -223,8 +223,8 @@ public static <T> Iterable<T> getAllProviders(final ServiceLocator locator, fina
223223
* @return iterable of all available ranked service providers for the contract. Return value is never null.
224224
*/
225225
public static <T> Iterable<RankedProvider<T>> getAllRankedProviders(final ServiceLocator locator, final Class<T> contract) {
226-
final List<ServiceHandle<T>> providers = getAllServiceHandles(locator, contract, new CustomAnnotationImpl());
227-
providers.addAll(getAllServiceHandles(locator, contract));
226+
final List<ServiceHandle<T>> providers = getServiceHandles(locator, contract, new CustomAnnotationImpl());
227+
providers.addAll(getServiceHandles(locator, contract));
228228

229229
final LinkedHashMap<ActiveDescriptor<T>, RankedProvider<T>> providerMap =
230230
new LinkedHashMap<ActiveDescriptor<T>, RankedProvider<T>>();
@@ -308,7 +308,33 @@ public static <T> Iterable<T> getAllProviders(final ServiceLocator locator,
308308
return sortRankedProviders(comparator, getAllRankedProviders(locator, contract));
309309
}
310310

311-
private static <T> List<ServiceHandle<T>> getAllServiceHandles(final ServiceLocator locator, final Class<T> contract,
311+
/**
312+
* Get collection of all {@link ServiceHandle}s bound for providers (custom and default) registered for the given service provider contract
313+
* in the underlying {@link ServiceLocator HK2 service locator} container.
314+
*
315+
* @param <T> service provider contract Java type.
316+
* @param locator underlying HK2 service locator.
317+
* @param contract service provider contract.
318+
* @return set of all available service provider instances for the contract
319+
*/
320+
public static <T> Collection<ServiceHandle<T>> getAllServiceHandles(final ServiceLocator locator, final Class<T> contract) {
321+
final List<ServiceHandle<T>> providers = getServiceHandles(locator, contract, new CustomAnnotationImpl());
322+
providers.addAll(getServiceHandles(locator, contract));
323+
324+
final LinkedHashMap<ActiveDescriptor, ServiceHandle<T>> providerMap =
325+
new LinkedHashMap<ActiveDescriptor, ServiceHandle<T>>();
326+
327+
for (final ServiceHandle<T> provider : providers) {
328+
final ActiveDescriptor key = provider.getActiveDescriptor();
329+
if (!providerMap.containsKey(key)) {
330+
providerMap.put(key, provider);
331+
}
332+
}
333+
334+
return providerMap.values();
335+
}
336+
337+
private static <T> List<ServiceHandle<T>> getServiceHandles(final ServiceLocator locator, final Class<T> contract,
312338
final Annotation... qualifiers) {
313339

314340
final List<ServiceHandle<T>> allServiceHandles = qualifiers == null ?
@@ -335,20 +361,8 @@ private static <T> List<ServiceHandle<T>> getAllServiceHandles(final ServiceLoca
335361
* {@link Comparator comparator}.
336362
*/
337363
public static <T> Iterable<T> getAllProviders(final ServiceLocator locator, final Class<T> contract, final Comparator<T> comparator) {
338-
final List<ServiceHandle<T>> providers = getAllServiceHandles(locator, contract, new CustomAnnotationImpl());
339-
providers.addAll(getAllServiceHandles(locator, contract));
340-
341-
final LinkedHashMap<ActiveDescriptor, ServiceHandle<T>> providerMap =
342-
new LinkedHashMap<ActiveDescriptor, ServiceHandle<T>>();
343-
344-
for (final ServiceHandle<T> provider : providers) {
345-
final ActiveDescriptor key = provider.getActiveDescriptor();
346-
if (!providerMap.containsKey(key)) {
347-
providerMap.put(key, provider);
348-
}
349-
}
350364

351-
final List<T> providerList = new ArrayList<T>(getClasses(providerMap.values()));
365+
final List<T> providerList = new ArrayList<T>(getClasses(getAllServiceHandles(locator, contract)));
352366

353367
if (comparator != null) {
354368
Collections.sort(providerList, comparator);
@@ -377,7 +391,7 @@ private static <T> Set<T> getClasses(final Collection<ServiceHandle<T>> hk2Provi
377391
* @return set of all available service provider instances for the contract.
378392
*/
379393
public static <T> SortedSet<T> getProviders(final ServiceLocator locator, final Class<T> contract, final Comparator<T> comparator) {
380-
final Collection<ServiceHandle<T>> hk2Providers = getAllServiceHandles(locator, contract);
394+
final Collection<ServiceHandle<T>> hk2Providers = getServiceHandles(locator, contract);
381395
if (hk2Providers.isEmpty()) {
382396
return Sets.newTreeSet(comparator);
383397
} else {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3+
*
4+
* Copyright (c) 2014 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.tests.ejb.resources;
42+
43+
/**
44+
* Custom exception. Part of JERSEY-2320 reproducer.
45+
* This one serves as a base for other exceptions
46+
* mapped by {@link EjbExceptionMapperOne} and {@link EjbExceptionMapperTwo}.
47+
*
48+
* @author Jakub Podlesak (jakub.podlesak at oracle.com)
49+
*/
50+
public class CustomBaseException extends Exception {
51+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3+
*
4+
* Copyright (c) 2014 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.tests.ejb.resources;
42+
43+
/**
44+
* Custom exception. Part of JERSEY-2320 reproducer.
45+
* This one gets mapped by {@link EjbExceptionMapperOne}.
46+
*
47+
* @author Jakub Podlesak (jakub.podlesak at oracle.com)
48+
*/
49+
public class CustomExceptionOne extends CustomBaseException {
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3+
*
4+
* Copyright (c) 2014 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.tests.ejb.resources;
42+
43+
/**
44+
* Custom exception. Part of JERSEY-2320 reproducer.
45+
* This one gets mapped by {@link EjbExceptionMapperTwo}.
46+
*
47+
* @author Jakub Podlesak (jakub.podlesak at oracle.com)
48+
*/
49+
public class CustomExceptionTwo extends CustomBaseException {
50+
}

0 commit comments

Comments
 (0)