Skip to content

Commit

Permalink
[RESTEASY-2174][RESTEASY-2175] ResteasyProviderFactory refactoring / …
Browse files Browse the repository at this point in the history
…optimization (#1879)

* TCCL-based cache of initial client ResteasyProviderFactory

* Get rid of exceptionMapper in RPF (use sortedExceptionMappers)

* Reduce number of objects created for each new RPF instance

* RPF refactoring to split the class into some smaller / more readable ones and to allow reducing memory allocation in case the RPF is needed only on client or server side

* Minor cleanup of MediaTypeMap

* Adding MediaType cache

* Replacing Class#newInstance method usage in RPF (deprecated in JDK9)

* Some reasonable sizing of ConcurrentHashMaps in RPF (based on the number of existing implementations in RESTEasy for the various keys)

* Adding MediaType -> String (reverse) map

* Simple bench test to measure performance of RPF usage on client side
  • Loading branch information
asoldano committed Mar 1, 2019
1 parent ef7bac3 commit ea17ab7
Show file tree
Hide file tree
Showing 41 changed files with 2,129 additions and 1,150 deletions.
Expand Up @@ -57,7 +57,10 @@ public ClientConfiguration(final ClientConfiguration parent)


public void setProperties(Map<String, Object> newProps) public void setProperties(Map<String, Object> newProps)
{ {
providerFactory.setProperties(newProps); if (newProps != null && !newProps.isEmpty())
{
providerFactory.setProperties(newProps);
}
} }


protected ResteasyProviderFactory getProviderFactory() protected ResteasyProviderFactory getProviderFactory()
Expand Down
Expand Up @@ -2,7 +2,9 @@


import javax.ws.rs.RuntimeType; import javax.ws.rs.RuntimeType;


import org.jboss.resteasy.core.ResteasyProviderFactoryImpl; import org.jboss.resteasy.core.providerfactory.ClientHelper;
import org.jboss.resteasy.core.providerfactory.NOOPServerHelper;
import org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;


/** /**
Expand All @@ -26,4 +28,11 @@ public RuntimeType getRuntimeType()
{ {
return RuntimeType.CLIENT; return RuntimeType.CLIENT;
} }

@Override
protected void initializeUtils()
{
clientHelper = new ClientHelper(this);
serverHelper = NOOPServerHelper.INSTANCE;
}
} }
Expand Up @@ -9,12 +9,13 @@
import org.jboss.resteasy.client.jaxrs.engines.ClientHttpEngineBuilder43; import org.jboss.resteasy.client.jaxrs.engines.ClientHttpEngineBuilder43;
import org.jboss.resteasy.client.jaxrs.i18n.LogMessages; import org.jboss.resteasy.client.jaxrs.i18n.LogMessages;
import org.jboss.resteasy.client.jaxrs.i18n.Messages; import org.jboss.resteasy.client.jaxrs.i18n.Messages;
import org.jboss.resteasy.core.ResteasyProviderFactoryImpl; import org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;


import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.ws.rs.RuntimeType;
import javax.ws.rs.core.Configuration; import javax.ws.rs.core.Configuration;


import java.security.KeyStore; import java.security.KeyStore;
Expand Down Expand Up @@ -316,8 +317,7 @@ public ResteasyProviderFactory getProviderFactory()
if (providerFactory == null) if (providerFactory == null)
{ {
// create a new one // create a new one
providerFactory = new LocalResteasyProviderFactory(ResteasyProviderFactory.newInstance()); providerFactory = new LocalResteasyProviderFactory(RegisterBuiltin.getClientInitializedResteasyProviderFactory(Thread.currentThread().getContextClassLoader()));
RegisterBuiltin.register(providerFactory);


if (ResteasyProviderFactory.peekInstance() != null) if (ResteasyProviderFactory.peekInstance() != null)
{ {
Expand Down Expand Up @@ -451,7 +451,13 @@ public ResteasyClientBuilderImpl register(Object component, Map<Class<?>, Intege
@Override @Override
public ResteasyClientBuilderImpl withConfig(Configuration config) public ResteasyClientBuilderImpl withConfig(Configuration config)
{ {
providerFactory = new LocalResteasyProviderFactory(new ResteasyProviderFactoryImpl()); providerFactory = new ResteasyProviderFactoryImpl() {
@Override
public RuntimeType getRuntimeType()
{
return RuntimeType.CLIENT;
}
};
providerFactory.setProperties(config.getProperties()); providerFactory.setProperties(config.getProperties());
for (Class clazz : config.getClasses()) for (Class clazz : config.getClasses())
{ {
Expand Down
Expand Up @@ -133,9 +133,9 @@ public static ResteasyProviderFactory newInstance()
try try
{ {
return (ResteasyProviderFactory) Thread.currentThread().getContextClassLoader() return (ResteasyProviderFactory) Thread.currentThread().getContextClassLoader()
.loadClass("org.jboss.resteasy.core.ResteasyProviderFactoryImpl").newInstance(); .loadClass("org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl").getDeclaredConstructor().newInstance();
} }
catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) catch (Exception e)
{ {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
Expand Down
@@ -1,5 +1,6 @@
package org.jboss.resteasy.core; package org.jboss.resteasy.core;


import org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages; import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
import org.jboss.resteasy.spi.ApplicationException; import org.jboss.resteasy.spi.ApplicationException;
import org.jboss.resteasy.spi.Failure; import org.jboss.resteasy.spi.Failure;
Expand Down Expand Up @@ -55,7 +56,7 @@ protected Response executeExactExceptionMapper(Throwable exception, RESTEasyTrac
if (logger == null) if (logger == null)
logger = RESTEasyTracingLogger.empty(); logger = RESTEasyTracingLogger.empty();


ExceptionMapper mapper = providerFactory.getExceptionMappers().get(exception.getClass()); ExceptionMapper mapper = providerFactory.getExceptionMapperForClass(exception.getClass());
if (mapper == null) return null; if (mapper == null) return null;
mapperExecuted = true; mapperExecuted = true;
long timestamp = logger.timestamp("EXCEPTION_MAPPING"); long timestamp = logger.timestamp("EXCEPTION_MAPPING");
Expand All @@ -75,7 +76,7 @@ protected Response executeExceptionMapperForClass(Throwable exception, Class cla
{ {
if (logger == null) if (logger == null)
logger = RESTEasyTracingLogger.empty(); logger = RESTEasyTracingLogger.empty();
ExceptionMapper mapper = providerFactory.getExceptionMappers().get(clazz); ExceptionMapper mapper = providerFactory.getExceptionMapperForClass(clazz);
if (mapper == null) return null; if (mapper == null) return null;
mapperExecuted = true; mapperExecuted = true;
long timestamp = logger.timestamp("EXCEPTION_MAPPING"); long timestamp = logger.timestamp("EXCEPTION_MAPPING");
Expand Down Expand Up @@ -123,7 +124,7 @@ protected Response executeExceptionMapper(Throwable exception, RESTEasyTracingLo
Class causeClass = exception.getClass(); Class causeClass = exception.getClass();
while (mapper == null) { while (mapper == null) {
if (causeClass == null) break; if (causeClass == null) break;
mapper = providerFactory.getExceptionMappers().get(causeClass); mapper = providerFactory.getExceptionMapperForClass(causeClass);
if (mapper == null) causeClass = causeClass.getSuperclass(); if (mapper == null) causeClass = causeClass.getSuperclass();
} }


Expand Down
Expand Up @@ -42,6 +42,8 @@
@SuppressWarnings({"unchecked", "rawtypes"}) @SuppressWarnings({"unchecked", "rawtypes"})
public class InjectorFactoryImpl implements InjectorFactory public class InjectorFactoryImpl implements InjectorFactory
{ {
public static final InjectorFactoryImpl INSTANCE = new InjectorFactoryImpl();

@Override @Override
public ConstructorInjector createConstructor(Constructor constructor, ResteasyProviderFactory providerFactory) public ConstructorInjector createConstructor(Constructor constructor, ResteasyProviderFactory providerFactory)
{ {
Expand Down
Expand Up @@ -115,14 +115,14 @@ public int compareTo(Entry<?> entry)
} }
} }


private static Pattern COMPOSITE_PATTERN = Pattern.compile("([^\\+]+)\\+(.+)"); private static final Pattern COMPOSITE_PATTERN = Pattern.compile("([^\\+]+)\\+(.+)");


// Composite subtypes are of the pattern *+subtype i.e. *+xml, *+json // Composite subtypes are of the pattern *+subtype i.e. *+xml, *+json
public static Pattern COMPOSITE_SUBTYPE_WILDCARD_PATTERN = Pattern.compile("\\*\\+(.+)"); public static final Pattern COMPOSITE_SUBTYPE_WILDCARD_PATTERN = Pattern.compile("\\*\\+(.+)");




// This composite is subtype+* i.e. atom+* rss+* // This composite is subtype+* i.e. atom+* rss+*
public static Pattern WILD_SUBTYPE_COMPOSITE_PATTERN = Pattern.compile("([^\\+]+)\\+\\*"); public static final Pattern WILD_SUBTYPE_COMPOSITE_PATTERN = Pattern.compile("([^\\+]+)\\+\\*");


private static class SubtypeMap<T> private static class SubtypeMap<T>
{ {
Expand Down Expand Up @@ -252,14 +252,7 @@ public MediaTypeMap<T> clone()
return clone; return clone;
} }


public Map<CachedMediaTypeAndClass, List<T>> getClassCache() private static class CachedMediaTypeAndClass
{
return classCache;
}



public static class CachedMediaTypeAndClass
{ {
// we need a weak reference because of possible hot deployment // we need a weak reference because of possible hot deployment
// Although, these reference should get cleared up with any add() invocation // Although, these reference should get cleared up with any add() invocation
Expand Down
Expand Up @@ -2,6 +2,9 @@


import org.jboss.resteasy.annotations.Stream; import org.jboss.resteasy.annotations.Stream;
import org.jboss.resteasy.core.interception.jaxrs.PostMatchContainerRequestContext; import org.jboss.resteasy.core.interception.jaxrs.PostMatchContainerRequestContext;
import org.jboss.resteasy.core.providerfactory.NOOPClientHelper;
import org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl;
import org.jboss.resteasy.core.providerfactory.ServerHelper;
import org.jboss.resteasy.core.registry.SegmentNode; import org.jboss.resteasy.core.registry.SegmentNode;
import org.jboss.resteasy.plugins.server.resourcefactory.SingletonResource; import org.jboss.resteasy.plugins.server.resourcefactory.SingletonResource;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages; import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
Expand Down Expand Up @@ -108,7 +111,14 @@ public Class<?> getResourceClass()
} }
}; };


this.resourceMethodProviderFactory = new ResteasyProviderFactoryImpl(providerFactory); this.resourceMethodProviderFactory = new ResteasyProviderFactoryImpl(providerFactory) {
@Override
protected void initializeUtils()
{
clientHelper = NOOPClientHelper.INSTANCE;
serverHelper = new ServerHelper(this);
}
};
for (DynamicFeature feature : providerFactory.getServerDynamicFeatures()) for (DynamicFeature feature : providerFactory.getServerDynamicFeatures())
{ {
feature.configure(resourceInfo, new DynamicFeatureContextDelegate(resourceMethodProviderFactory)); feature.configure(resourceInfo, new DynamicFeatureContextDelegate(resourceMethodProviderFactory));
Expand Down Expand Up @@ -224,7 +234,14 @@ public void cleanup()


public void registryUpdated(JaxrsInterceptorRegistry registry) public void registryUpdated(JaxrsInterceptorRegistry registry)
{ {
this.resourceMethodProviderFactory = new ResteasyProviderFactoryImpl(parentProviderFactory); this.resourceMethodProviderFactory = new ResteasyProviderFactoryImpl(parentProviderFactory) {
@Override
protected void initializeUtils()
{
clientHelper = NOOPClientHelper.INSTANCE;
serverHelper = new ServerHelper(this);
}
};
for (DynamicFeature feature : parentProviderFactory.getServerDynamicFeatures()) for (DynamicFeature feature : parentProviderFactory.getServerDynamicFeatures())
{ {
feature.configure(resourceInfo, new FeatureContextDelegate(resourceMethodProviderFactory)); feature.configure(resourceInfo, new FeatureContextDelegate(resourceMethodProviderFactory));
Expand Down
Expand Up @@ -29,6 +29,7 @@
import javax.ws.rs.ext.ReaderInterceptor; import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.WriterInterceptor; import javax.ws.rs.ext.WriterInterceptor;


import org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages; import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
import org.jboss.resteasy.spi.AsyncResponseProvider; import org.jboss.resteasy.spi.AsyncResponseProvider;
import org.jboss.resteasy.spi.AsyncStreamProvider; import org.jboss.resteasy.spi.AsyncStreamProvider;
Expand Down Expand Up @@ -504,12 +505,6 @@ public <T extends Throwable> ExceptionMapper<T> getExceptionMapper(Class<T> type
return getDelegate().getExceptionMapper(type); return getDelegate().getExceptionMapper(type);
} }


@Override
public Map<Class<?>, ExceptionMapper> getExceptionMappers()
{
return ((ResteasyProviderFactoryImpl)getDelegate()).getExceptionMappers();
}

@Override @Override
public <T> AsyncResponseProvider<T> getAsyncResponseProvider(Class<T> type) public <T> AsyncResponseProvider<T> getAsyncResponseProvider(Class<T> type)
{ {
Expand Down
@@ -1,6 +1,6 @@
package org.jboss.resteasy.core.interception.jaxrs; package org.jboss.resteasy.core.interception.jaxrs;


import org.jboss.resteasy.core.ResteasyProviderFactoryImpl; import org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl;
import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages; import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages;
import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
Expand Down
@@ -1,7 +1,7 @@
package org.jboss.resteasy.core.interception.jaxrs; package org.jboss.resteasy.core.interception.jaxrs;


import org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure; import org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure;
import org.jboss.resteasy.core.ResteasyProviderFactoryImpl; import org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl;
import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.tracing.RESTEasyTracingLogger; import org.jboss.resteasy.tracing.RESTEasyTracingLogger;
Expand Down

0 comments on commit ea17ab7

Please sign in to comment.