Issue 1:
David Sean Taylor opened SPR-3426 and commented

please also see:

http://issues.apache.org/jira/browse/JS2-689

I know the contention is occurring in Java JDK code, not in Spring itself.

I would like to suggest that Spring provides an improvement: an alternative implementation for multithreaded applications

Pasted in issue from Apache JIRA system:

It appears that Spring prototype (non-singleton) bean factory creations cause synchronization contention issues under load.

The NavigationalState and PortalURL beans are created several times per request.

Under load with JMeter tests, the synchronization of Java Bean support code (in the JDK), called by Spring's bean factory, was causing severe performance degradation.

Removing this bottleneck improved performance by 5X.

I've attached the Java source from the package java.beans. I believe its these synchronized methods of the java.beans.PropertyEditorManager class that are causing the contention:

private static synchronized void initialize() {

private static synchronized void load(Class targetType, String name) {

See attached screenshot for performance results before and after removal of prototypes (replaced by constructors).

Using a 4 processor CPU really brings the contention issue to the forefront.

When we have hundreds of requests active, there are over 90 blocked threads in the findEditor stack frame:

Thread t@98: (state = BLOCKED)

java.beans.PropertyEditorManager.findEditor(java.lang.Class) @bci=0, line=75 (Compiled frame; information may be imprecise)

org.springframework.beans.TypeConverterDelegate.convertIfNecessary(java.lang.String, java.lang.Object, java.lang.Object, java.lang.Class, java.beans.PropertyDescriptor, org.springframework.core.MethodParameter) @bci=115, line=174 (Compiled frame)

org.springframework.beans.TypeConverterDelegate.convertIfNecessary(java.lang.Object, java.lang.Class, org.springframework.core.MethodParameter) @bci=7, line=95 (Compiled frame)

org.springframework.beans.factory.support.AbstractBeanFactory.doTypeConversionIfNecessary(org.springframework.beans.TypeConverter, java.lang.Object, java.lang.Class, org.springframework.core.MethodParameter) @bci=47, line=761 (Compiled frame)

org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition) @bci=191, line=126 (Compiled frame)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition) @bci=12, line=683 (Compiled frame)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[]) @bci=224, line=380 (Compiled frame)

org.springframework.beans.factory.support.AbstractBeanFactory.getBean(java.lang.String, java.lang.Class, java.lang.Object[]) @bci=362, line=264 (Compiled frame)

org.springframework.beans.factory.support.AbstractBeanFactory.getBean(java.lang.String, java.lang.Class) @bci=4, line=160 (Compiled frame)

org.apache.jetspeed.container.state.impl.JetspeedNavigationalStateComponent.createURL(javax.servlet.http.HttpServletRequest, java.lang.String) @bci=29, line=131 (Compiled frame)

org.apache.jetspeed.pipeline.JetspeedPipeline$Invocation.invokeNex

My first solution was to remove the Spring prototype code and replace it with straight constructors (replacing commented code below):

public PortalURL createURL( HttpServletRequest request, String characterEncoding )
{
//PortalURL url = (PortalURL) beanFactory.getBean(urlBeanName, PortalURL.class); <--- **** used to be one line prototype creation, commented out....
NavigationalStateCodec codec = (NavigationalStateCodec)beanFactory.getBean("NavigationalStateCodec");
JetspeedCache cache = (JetspeedCache)beanFactory.getBean("portletContentCache");
NavigationalState navState = new SessionFullNavigationalState( codec, cache);
PortalContext context = (PortalContext)beanFactory.getBean("PortalContext");
PortalURL url = new PathInfoEncodingPortalURL(navState, context);

Perhaps it could be configured as:

public PortalURL createURL( HttpServletRequest request, String characterEncoding )
{
if (useSpringToWireBeans)
{
PortalURL url = (PortalURL) beanFactory.getBean(urlBeanName, PortalURL.class);

}

else

{

NavigationalStateCodec codec = (NavigationalStateCodec)beanFactory.getBean("NavigationalStateCodec");

JetspeedCache cache = (JetspeedCache)beanFactory.getBean("portletContentCache");

NavigationalState navState = new SessionFullNavigationalState( codec, cache);

PortalContext context = (PortalContext)beanFactory.getBean("PortalContext");

PortalURL url = new PathInfoEncodingPortalURL(navState, context);

Affects: 2.0 final

Issue Links:

#7667 Spring performance is insufficient for intensive work at short scopes ("duplicates")

#8039 Improve performance of AbstractBeanFactory for high-concurrent-load applications

Issue 2:
Rossen Stoyanchev opened SPR-8410 and commented

The ContentNegotiatingViewResolver provides a range of options for configuring content negotiation based on the 'Accept' header, by path extension, or by request parameter. However when writing to the response via @ResponseBody only the 'Accept' header is used (see #12175). Furthermore, it's not possible to combine all options in the request mapping of a single method (see #11163, #12378).

This is an umbrella ticket to improve how content negotiation options are configured and to equalize the choices throughout request mappings, @ResponseBody methods, and ContentNegotiatingViewResolver.

Affects: 3.1 M1

Sub-tasks:

#12288 Allow valid file extension paths for content negotiation to be specified

#13064 Introduce ContentNegotiationStrategy abstraction

#13065 Enhance "produces" condition to use the new ContentNegotiationManager type

#13066 Enhance RequestResponseBodyMethodProcessor and HttpEntityMethodProcessor to use new the ContentNegotiationManager type

#13067 Enhance ContentNegotiatingViewResolver to use the new ContentNegotiationManager type

#13068 Update the MVC Java config and the MVC namespace to support content negotiation options

#13120 Configure PatternsRequestCondition with information that allows it to do a smart suffix pattern match

Issue Links:

#13190 Spring MVC - Ability to use a Converter based on the Path Extension instead of Accep Header. ("is duplicated by")

#13282 Allow customization of ContentNegotiatingViewResolver by making some of its methods protected

#13791 Add extension element to Spring Web MVC @RequestMapping annotation

#11658 Add content-negotiation to RequestBody and ResponseBody processing ("supersedes")

#11163 @RequestMapping should support accept header and url extension ("supersedes")

#12378 @RequestMapping should support alternative between a header and a url extension ("supersedes")

#12175 Introduce request parameter based content negotiation for ResponseBody / HttpMessageConverter approach ("supersedes")

6 votes, 9 watchers