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

Commit 036b3bb

Browse files
author
Michal Gajdos
committed
JERSEY-2517: Create mechanism to automatically register features/providers
even when autodiscoverable and metainf/services mechanisms are disabled - introduced internal SPI ForcedAutoDiscoverable - BV, WADL, JSON-P, Monitoring migrated to ForcedAutoDiscoverable - added new test + updated older ones - note in migration guide Change-Id: I120f0e695980e90e86085f34b23608d9a3876027 Signed-off-by: Michal Gajdos <[email protected]>
1 parent c15bdd6 commit 036b3bb

File tree

20 files changed

+454
-156
lines changed

20 files changed

+454
-156
lines changed

core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,11 @@ public Set<Object> getInstances() {
353353
}
354354

355355
public void configureAutoDiscoverableProviders(ServiceLocator locator) {
356-
commonConfig.configureAutoDiscoverableProviders(locator);
356+
commonConfig.configureAutoDiscoverableProviders(locator, false);
357+
}
358+
359+
public void configureForcedAutoDiscoverableProviders(ServiceLocator locator) {
360+
commonConfig.configureAutoDiscoverableProviders(locator, true);
357361
}
358362

359363
public void configureMetaProviders(ServiceLocator locator) {
@@ -385,6 +389,8 @@ private ClientRuntime initRuntime() {
385389
if (!CommonProperties.getValue(runtimeCfgState.getProperties(), RuntimeType.CLIENT,
386390
CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, Boolean.FALSE, Boolean.class)) {
387391
runtimeCfgState.configureAutoDiscoverableProviders(locator);
392+
} else {
393+
runtimeCfgState.configureForcedAutoDiscoverableProviders(locator);
388394
}
389395

390396
// Configure binders and features.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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.internal.spi;
42+
43+
/**
44+
* A service provider contract for JAX-RS and Jersey components that need to be automatically discovered and registered in
45+
* {@link javax.ws.rs.core.Configuration runtime configurations}.
46+
* <p/>
47+
* A component implementing this contract becomes auto-discoverable by adding a new entry with fully qualified name of its
48+
* implementation class name to a {@code org.glassfish.jersey.internal.spi.AutoDiscoverable} file in the {@code
49+
* META-INF/services} directory.
50+
* <p/>
51+
* Implementations of this contract are always {@link #configure(javax.ws.rs.core.FeatureContext) configured} regardless of
52+
* values of properties {@link org.glassfish.jersey.CommonProperties#FEATURE_AUTO_DISCOVERY_DISABLE} and
53+
* {@link org.glassfish.jersey.CommonProperties#METAINF_SERVICES_LOOKUP_DISABLE}.
54+
*
55+
* @author Michal Gajdos (michal.gajdos at oracle.com)
56+
* @see org.glassfish.jersey.internal.spi.AutoDiscoverable
57+
*/
58+
public interface ForcedAutoDiscoverable extends AutoDiscoverable {
59+
}

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

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,33 @@
4343
import java.util.Arrays;
4444
import java.util.Collection;
4545
import java.util.Collections;
46+
import java.util.Comparator;
4647
import java.util.HashMap;
4748
import java.util.HashSet;
4849
import java.util.LinkedList;
4950
import java.util.List;
5051
import java.util.Map;
5152
import java.util.Set;
53+
import java.util.TreeSet;
5254
import java.util.logging.Level;
5355
import java.util.logging.Logger;
5456

5557
import javax.ws.rs.ConstrainedTo;
58+
import javax.ws.rs.Priorities;
5659
import javax.ws.rs.RuntimeType;
5760
import javax.ws.rs.core.Configuration;
5861
import javax.ws.rs.core.Feature;
5962
import javax.ws.rs.core.FeatureContext;
6063

64+
import javax.annotation.Priority;
65+
6166
import org.glassfish.jersey.ExtendedConfig;
6267
import org.glassfish.jersey.internal.LocalizationMessages;
68+
import org.glassfish.jersey.internal.ServiceFinder;
6369
import org.glassfish.jersey.internal.inject.Injections;
6470
import org.glassfish.jersey.internal.inject.Providers;
6571
import org.glassfish.jersey.internal.spi.AutoDiscoverable;
72+
import org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable;
6673
import org.glassfish.jersey.internal.util.PropertiesHelper;
6774
import org.glassfish.jersey.model.ContractProvider;
6875
import org.glassfish.jersey.process.Inflector;
@@ -88,7 +95,7 @@ public class CommonConfig implements FeatureContext, ExtendedConfig {
8895
private static final Logger LOGGER = Logger.getLogger(CommonConfig.class.getName());
8996
private static final Function<Object, Binder> CAST_TO_BINDER = new Function<Object, Binder>() {
9097
@Override
91-
public Binder apply(Object input) {
98+
public Binder apply(final Object input) {
9299
return Binder.class.cast(input);
93100
}
94101
};
@@ -171,7 +178,7 @@ public boolean equals(final Object obj) {
171178
if (!(obj instanceof FeatureRegistration)) {
172179
return false;
173180
}
174-
FeatureRegistration other = (FeatureRegistration) obj;
181+
final FeatureRegistration other = (FeatureRegistration) obj;
175182

176183
return (featureClass == other.featureClass)
177184
|| (feature != null && (feature == other.feature || feature.equals(other.feature)));
@@ -206,7 +213,7 @@ public int hashCode() {
206213
* or not should the component class registration continue
207214
* towards a successful completion.
208215
*/
209-
public CommonConfig(RuntimeType type, Predicate<ContractProvider> registrationStrategy) {
216+
public CommonConfig(final RuntimeType type, final Predicate<ContractProvider> registrationStrategy) {
210217
this.type = type;
211218

212219
this.properties = new HashMap<String, Object>();
@@ -291,7 +298,7 @@ public Object getProperty(final String name) {
291298
}
292299

293300
@Override
294-
public boolean isProperty(String name) {
301+
public boolean isProperty(final String name) {
295302
return PropertiesHelper.isProperty(getProperty(name));
296303
}
297304

@@ -311,17 +318,17 @@ public boolean isEnabled(final Feature feature) {
311318
}
312319

313320
@Override
314-
public boolean isRegistered(Object component) {
321+
public boolean isRegistered(final Object component) {
315322
return componentBag.getInstances().contains(component);
316323
}
317324

318325
@Override
319-
public boolean isRegistered(Class<?> componentClass) {
326+
public boolean isRegistered(final Class<?> componentClass) {
320327
return componentBag.getRegistrations().contains(componentClass);
321328
}
322329

323330
@Override
324-
public Map<Class<?>, Integer> getContracts(Class<?> componentClass) {
331+
public Map<Class<?>, Integer> getContracts(final Class<?> componentClass) {
325332
final ContractProvider model = componentBag.getModel(componentClass);
326333
return (model == null) ? Collections.<Class<?>, Integer>emptyMap() : model.getContractMap();
327334
}
@@ -439,7 +446,7 @@ public CommonConfig register(final Class<?> componentClass, final Class<?>... co
439446
}
440447

441448
@Override
442-
public CommonConfig register(final Class<?> componentClass, Map<Class<?>, Integer> contracts) {
449+
public CommonConfig register(final Class<?> componentClass, final Map<Class<?>, Integer> contracts) {
443450
checkComponentClassNotNull(componentClass);
444451
if (componentBag.register(componentClass, contracts, getModelEnhancer(componentClass))) {
445452
processFeatureRegistration(null, componentClass);
@@ -487,7 +494,7 @@ public CommonConfig register(final Object component, final Class<?>... contracts
487494
}
488495

489496
@Override
490-
public CommonConfig register(final Object component, Map<Class<?>, Integer> contracts) {
497+
public CommonConfig register(final Object component, final Map<Class<?>, Integer> contracts) {
491498
checkProviderNotNull(component);
492499
final Class<?> componentClass = component.getClass();
493500
if (componentBag.register(component, contracts, getModelEnhancer(componentClass))) {
@@ -497,8 +504,8 @@ public CommonConfig register(final Object component, Map<Class<?>, Integer> cont
497504
return this;
498505
}
499506

500-
private void processFeatureRegistration(Object component, Class<?> componentClass) {
501-
ContractProvider model = componentBag.getModel(componentClass);
507+
private void processFeatureRegistration(final Object component, final Class<?> componentClass) {
508+
final ContractProvider model = componentBag.getModel(componentClass);
502509
if (model.getContracts().contains(Feature.class)) {
503510
@SuppressWarnings("unchecked")
504511
final FeatureRegistration registration = (component != null) ?
@@ -518,7 +525,7 @@ private void processFeatureRegistration(Object component, Class<?> componentClas
518525
* @param config external configuration state to replace the configuration of this configurable instance.
519526
* @return the updated common configuration instance.
520527
*/
521-
public CommonConfig loadFrom(Configuration config) {
528+
public CommonConfig loadFrom(final Configuration config) {
522529
if (config instanceof CommonConfig) {
523530
// If loading from CommonConfig then simply copy properties and check whether given config has been initialized.
524531
final CommonConfig commonConfig = (CommonConfig) config;
@@ -554,19 +561,19 @@ public CommonConfig loadFrom(Configuration config) {
554561
return this;
555562
}
556563

557-
private Set<Class<?>> asNewIdentitySet(Class<?>... contracts) {
558-
Set<Class<?>> result = Sets.newIdentityHashSet();
564+
private Set<Class<?>> asNewIdentitySet(final Class<?>... contracts) {
565+
final Set<Class<?>> result = Sets.newIdentityHashSet();
559566
result.addAll(Arrays.asList(contracts));
560567
return result;
561568
}
562569

563-
private void checkProviderNotNull(Object provider) {
570+
private void checkProviderNotNull(final Object provider) {
564571
if (provider == null) {
565572
throw new IllegalArgumentException(LocalizationMessages.COMPONENT_CANNOT_BE_NULL());
566573
}
567574
}
568575

569-
private void checkComponentClassNotNull(Class<?> componentClass) {
576+
private void checkComponentClassNotNull(final Class<?> componentClass) {
570577
if (componentClass == null) {
571578
throw new IllegalArgumentException(LocalizationMessages.COMPONENT_CLASS_CANNOT_BE_NULL());
572579
}
@@ -576,17 +583,40 @@ private void checkComponentClassNotNull(Class<?> componentClass) {
576583
* Configure {@link AutoDiscoverable auto-discoverables} in the HK2 service locator.
577584
*
578585
* @param locator locator in which the auto-discoverables should be configured.
586+
* @param forcedOnly defines whether all or only forced auto-discoverables should be configured.
579587
*/
580-
public void configureAutoDiscoverableProviders(final ServiceLocator locator) {
588+
public void configureAutoDiscoverableProviders(final ServiceLocator locator, final boolean forcedOnly) {
581589
// Check whether meta providers have been initialized for a config this config has been loaded from.
582590
if (!disableMetaProviderConfiguration) {
583-
for (final AutoDiscoverable autoDiscoverable : Providers.getProviders(locator, AutoDiscoverable.class)) {
591+
final Set<AutoDiscoverable> providers = new TreeSet<AutoDiscoverable>(new Comparator<AutoDiscoverable>() {
592+
@Override
593+
public int compare(final AutoDiscoverable o1, final AutoDiscoverable o2) {
594+
final int p1 = o1.getClass().isAnnotationPresent(Priority.class)
595+
? o1.getClass().getAnnotation(Priority.class).value() : Priorities.USER;
596+
final int p2 = o2.getClass().isAnnotationPresent(Priority.class)
597+
? o2.getClass().getAnnotation(Priority.class).value() : Priorities.USER;
598+
599+
final int compare = Integer.compare(p1, p2);
600+
return compare == 0 ? -1 : compare;
601+
}
602+
});
603+
604+
// Forced (always invoked).
605+
providers.addAll(Arrays.asList(
606+
ServiceFinder.find(ForcedAutoDiscoverable.class, true).toArray()));
607+
608+
// Regular.
609+
if (!forcedOnly) {
610+
providers.addAll(Providers.getProviders(locator, AutoDiscoverable.class));
611+
}
612+
613+
for (final AutoDiscoverable autoDiscoverable : providers) {
584614
final ConstrainedTo constrainedTo = autoDiscoverable.getClass().getAnnotation(ConstrainedTo.class);
585615

586616
if (constrainedTo == null || type.equals(constrainedTo.value())) {
587617
try {
588618
autoDiscoverable.configure(this);
589-
} catch (Exception e) {
619+
} catch (final Exception e) {
590620
LOGGER.log(Level.FINE,
591621
LocalizationMessages.AUTODISCOVERABLE_CONFIGURATION_FAILED(autoDiscoverable.getClass()), e);
592622
}
@@ -618,14 +648,14 @@ public void configureMetaProviders(final ServiceLocator locator) {
618648
}
619649

620650
private Set<Binder> configureBinders(final ServiceLocator locator, final Set<Binder> configured) {
621-
Set<Binder> allConfigured = Sets.newIdentityHashSet();
651+
final Set<Binder> allConfigured = Sets.newIdentityHashSet();
622652
allConfigured.addAll(configured);
623653

624654
final Collection<Binder> binders = getBinders(configured);
625655
if (!binders.isEmpty()) {
626656
final DynamicConfiguration dc = Injections.getConfiguration(locator);
627657

628-
for (Binder binder : binders) {
658+
for (final Binder binder : binders) {
629659
binder.bind(dc);
630660
allConfigured.add(binder);
631661
}
@@ -640,7 +670,7 @@ private Collection<Binder> getBinders(final Set<Binder> configured) {
640670
Collections2.transform(componentBag.getInstances(ComponentBag.BINDERS_ONLY), CAST_TO_BINDER),
641671
new Predicate<Binder>() {
642672
@Override
643-
public boolean apply(Binder binder) {
673+
public boolean apply(final Binder binder) {
644674
return !configured.contains(binder);
645675
}
646676
});
@@ -651,7 +681,7 @@ private void configureFeatures(final ServiceLocator locator,
651681
final List<FeatureRegistration> unprocessed) {
652682

653683
FeatureContextWrapper featureContextWrapper = null;
654-
for (FeatureRegistration registration : unprocessed) {
684+
for (final FeatureRegistration registration : unprocessed) {
655685
if (processed.contains(registration)) {
656686
LOGGER.config(LocalizationMessages.FEATURE_HAS_ALREADY_BEEN_PROCESSED(registration.getFeatureClass()));
657687
continue;
@@ -677,7 +707,7 @@ private void configureFeatures(final ServiceLocator locator,
677707
// init lazily
678708
featureContextWrapper = new FeatureContextWrapper(this, locator);
679709
}
680-
boolean success = feature.configure(featureContextWrapper);
710+
final boolean success = feature.configure(featureContextWrapper);
681711

682712
if (success) {
683713
processed.add(registration);
@@ -691,21 +721,21 @@ private void configureFeatures(final ServiceLocator locator,
691721
}
692722

693723
private List<FeatureRegistration> resetRegistrations() {
694-
List<FeatureRegistration> result = new ArrayList<FeatureRegistration>(newFeatureRegistrations);
724+
final List<FeatureRegistration> result = new ArrayList<FeatureRegistration>(newFeatureRegistrations);
695725
newFeatureRegistrations.clear();
696726
return result;
697727
}
698728

699729
@Override
700-
public boolean equals(Object o) {
730+
public boolean equals(final Object o) {
701731
if (this == o) {
702732
return true;
703733
}
704734
if (!(o instanceof CommonConfig)) {
705735
return false;
706736
}
707737

708-
CommonConfig that = (CommonConfig) o;
738+
final CommonConfig that = (CommonConfig) o;
709739

710740
if (type != that.type) {
711741
return false;

core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ private void initialize() {
380380
if (!CommonProperties.getValue(runtimeConfig.getProperties(), RuntimeType.SERVER,
381381
CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, Boolean.FALSE, Boolean.class)) {
382382
runtimeConfig.configureAutoDiscoverableProviders(locator);
383+
} else {
384+
runtimeConfig.configureForcedAutoDiscoverableProviders(locator);
383385
}
384386

385387
// Configure binders and features.

core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ public State setProperties(Map<String, ?> properties) {
291291
}
292292

293293
@Override
294-
public void configureAutoDiscoverableProviders(final ServiceLocator locator) {
294+
public void configureAutoDiscoverableProviders(final ServiceLocator locator, final boolean forcedOnly) {
295295
throw new IllegalStateException(LocalizationMessages.RC_NOT_MODIFIABLE());
296296
}
297297

@@ -788,7 +788,16 @@ final ComponentBag getComponentBag() {
788788
* @param locator service locator to obtain auto-discoverables from.
789789
*/
790790
final void configureAutoDiscoverableProviders(final ServiceLocator locator) {
791-
state.configureAutoDiscoverableProviders(locator);
791+
state.configureAutoDiscoverableProviders(locator, false);
792+
}
793+
794+
/**
795+
* Configure forced auto-discoverables.
796+
*
797+
* @param locator service locator to obtain auto-discoverables from.
798+
*/
799+
final void configureForcedAutoDiscoverableProviders(final ServiceLocator locator) {
800+
state.configureAutoDiscoverableProviders(locator, true);
792801
}
793802

794803
/**

0 commit comments

Comments
 (0)