primefaces graphicimage CDI bean doesn't work - primefaces

i had some problem showing images retrieved by my db.
View caller:
<p:graphicImage value="#{appController.image}" height="200 px" >
<f:param name="oid" value="#{item.oid}" />
</p:graphicImage>
Controller:
#Named("appController")
#ApplicationScoped
public class AppController {
#Inject
private MultimediaFacade multimediaFacade;
public StreamedContent getImage() throws IOException {
System.out.println("getting image")
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
} else {
// So, browser is requesting the image. Return a real StreamedContent with the image bytes.
String imageId = context.getExternalContext().getRequestParameterMap().get("oid");
int oid=Integer.parseInt(imageId);
System.out.println(oid);
Multimedia image = multimediaFacade.find(oid);
System.out.println(Arrays.toString(image.getFileBlob()));
return new DefaultStreamedContent(new ByteArrayInputStream(image.getFileBlob()));
}
}
}
this code shows nothing and it looks like the method is never called (never print in console)!
after days of trial changing the scope, i tried to use #ManagedBean instead of #Named, and it works!!!
can someone explain me why this work only with #ManagedBean and not with #Named?

Check that you have javax.enterprise.context.ApplicationScoped in imports.
If you have a different import for #ApplicationScoped (e.g. javax.faces.bean.ApplicationScoped), then you need to configure CDI to discover all beans instead of only those with CDI annotations (which is the default)
To tun discovery for all beans, either add empty beans.xml into WEB-INF directory, or if you already have beans.xml there, add bean-discovery-mode="all" into the <beans> element, like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="annotated">
</beans>

Related

How to Mock Service class while writing a Junit for Spring-ws endpoint

I have created a Spring SOAP based webservice which retrives data from my DB , I am able to test the service through SOAP UI , but now I am trying to add few functionalites for the service and I want to add some Junits for the service , Please find my Endpoint and Junit details below.
My End Point Class
#Endpoint
public class CountryEndPoint {
private static final String NAMESPACE_URI = "http://tutorialspoint/schemas";
#Autowired
CountryRepository countryRepository;
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
#ResponsePayload
public GetCountryResponse getCountry(#RequestPayload GetCountryRequest request) throws JDOMException {
Country country = countryRepository.findCountry(request.getName());
GetCountryResponse response = new GetCountryResponse();
response.setCountry(country);
return response;
}
}
Spring-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sws="http://www.springframework.org/schema/web-services"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan
base-package="com.tutorialspoint" />
<sws:annotation-driven />
<bean id="schema"
class="org.springframework.core.io.ClassPathResource">
<constructor-arg index="0" value="*.xsd" />
</bean>
</beans>
Junit-Test calss
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "/spring-context.xml")
public class CustomerEndPointTest {
#Autowired
private ApplicationContext applicationContext;
#Autowired
private ResourceLoader resourceLoader;
private MockWebServiceClient mockClient;
private Resource schema = new ClassPathResource("countries.xsd");
#Before
public void createClient() {
mockClient = MockWebServiceClient.createClient(applicationContext);
GenericApplicationContext ctx = (GenericApplicationContext) applicationContext;
final XmlBeanDefinitionReader definitionReader = new XmlBeanDefinitionReader(ctx);
definitionReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
definitionReader.setNamespaceAware(true);
}
#Test
public void testCountryEndpoint() throws Exception {
Resource request = resourceLoader.getResource("request.xml");
Resource response = resourceLoader.getResource("response.xml");
mockClient.sendRequest(withPayload(request)).
andExpect(payload(response)).
andExpect(validPayload(schema));
}
}
I am able to run the test case with out any issue but my problem is I am not able to mock my service class (CountryRepository) mock the the code below.
Country country = countryRepository.findCountry(request.getName());
Does any one have any suggessions on this?
From your test case, I suppose your are trying to mock the CrudRepository object from inside a webservice call: That would be called integration testing. You need to make a choice for unit testing:
Test the request, and assert its response http status code (for example),
Or test the getCountry method inside your CountryEndPoint class. Doing both options at the same time would be considered an integration test.
I will try to answer considering the unit test case, using option 2. I think it will give you better insights for the future.
You are injecting the dependency of the CountryRepository on your CountryEndPoint class. You need to do the same on your testing class. For example, a basic setup would be:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "/spring-context.xml")
public class CustomerEndPointTest {
#InjectMocks
private CountryEndPoint countryEndPoint;
#Mock
private CountryRepository countryRepository;
#Test
public void testCountryEndpoint() throws Exception {
Mockito.when(countryRepository //...
countryEndPoint.getCountry(request //build a request object and pass it here.
//assertions...
}
}
Then, whenever a method from CountryRepository is invoked, it will be invoked from the mock instead. This is only possibly because of the injection of the mock via annotations.
If you actually send a request, using a HTTP client (like you intended), you cannot mock the methods being invoked inside your controller class, because you are not manipulating and assigning the instances yourself, and thus are not able to determine what is a mock, and what is not.

How to show a dynamic image in PrimeFaces 6.1 [duplicate]

I am using PrimeFaces 5.3 <p:fileUpload> to upload a PNG image and I would like to show a preview of it in <p:graphicImage> before saving in database.
Here's a MCVE:
<h:form enctype="multipart/form-data">
<p:fileUpload value="#{bean.uploadedFile}" mode="simple" />
<p:graphicImage value="#{bean.image}" />
<p:commandButton action="#{bean.preview}" ajax="false" value="Preview" />
</h:form>
private UploadedFile uploadedFile;
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void preview() {
// NOOP for now.
}
public StreamedContent getImage() {
if (uploadedFile == null) {
return new DefaultStreamedContent();
} else {
return new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()), "image/png");
}
}
No error occurring on the backing bean, and the image won't be load and display at front-end. The client mentions that the image returned a 404 not found error.
Your problem is two-fold. It failed because the uploaded file contents is request scoped and because the image is requested in a different HTTP request. To better understand the inner working, carefully read the answers on following closely related Q&A:
Display dynamic image from database with p:graphicImage and StreamedContent
How to choose the right bean scope?
To solve the first problem, you need to read the uploaded file contents immediately in the action method associated with the form submit. In your specific case, that would look like:
private UploadedFile uploadedFile;
private byte[] fileContents;
public void preview() {
fileContents = uploadedFile.getContents();
}
// ...
To solve the second problem, your best bet is to use the data URI scheme. This makes it possible to render the image directly in the very same response and therefore you can safely use a #ViewScoped bean without facing "context not active" issues or saving the byte[] in session or disk in order to enable serving the image in a different request. Browser support on data URI scheme is currently pretty good. Replace the entire <p:graphicImage> with below:
<ui:fragment rendered="#{not empty bean.uploadedFile}">
<img src="data:image/png;base64,#{bean.imageContentsAsBase64}" />
</ui:fragment>
public String getImageContentsAsBase64() {
return Base64.getEncoder().encodeToString(imageContents);
}
Note: I assume that Java 8 is available to you as java.util.Base64 was only introduced in that version. In case you're using an older Java version, use DatatypeConverter.printBase64Binary(imageContents) instead.
In case you happen to use JSF utility library OmniFaces, you can also just use its <o:graphicImage> component instead which is on contrary to <p:graphicImage> capable of directly referencing a byte[] and InputStream bean property and rendering a data URI.
<o:graphicImage value="#{bean.imageContents}" dataURI="true" rendered="#{not empty bean.imageContents}">

Insert XmlFile (or other) from camel route to mongoDB

I've been trying to insert a XML file into mongoDB with camel and I can't manage to make it work.
I've followed this tutorial for the first steps:
http://www.pretechsol.com/2014/09/apache-camel-mongodb-component-example.html
In my route, I convert it in JSON then use 'convertBodyTo(string.class) for mongo to recognize the file.
The code works well with regular route (sending the file to another folder for example). But when I run it for mongoDB, all I get in the console is my Process message again and again with my databased never being filled.As I don't receive any error message, I don't know how to find where the problem come from.
The mongoDB name, ip, users, password have been already checked multiple times.
I would be very grateful if someone could help me on this one. Here is the files I am using. (I will spare you the process file).
camel-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="myDb" class="com.mongodb.Mongo">
<constructor-arg index="0">
<bean class="com.mongodb.MongoURI">
<constructor-arg index="0"
value="mongodb://username:password#192.168.3.29:27017/db" />
</bean>
</constructor-arg>
</bean>
<bean id="mongodb" class="org.apache.camel.component.mongodb.MongoDbComponent"></bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="camelRoute" />
</camelContext>
<bean id="camelRoute" class="infotel.camel.project01.CamelRoute" />
Here is my RoutingFile:
#Component
public class CamelRoute extends SpringRouteBuilder {
final Processor myProcessor = new MyProcessor();
final Processor myProcessorMongo = new MyProcessorMongo();
final XmlJsonDataFormat xmlJsonFormat = new XmlJsonDataFormat();
#Override
public void configure() {
xmlJsonFormat.setForceTopLevelObject(true);
from("file:xml_files?noop=true").marshal(xmlJsonFormat).convertBodyTo(String.class).process(myProcessorMongo)
.to("mongodb:myDb?database=test_bignav&collection=doc&operation=insert");
}
}
And finally here is my main:
public class MyMain {
public static void main(String[] args) throws Exception {
ApplicationContext context =
new ClassPathXmlApplicationContext("META-INF/spring/camel-context.xml");
}
}
Thanks a lot.
Edit:
Here is MyProcessorMongo edited to get the error:
public class MyProcessorMongo implements Processor{
public void process(Exchange exchange) throws Exception {
System.out.println("\n file transfered to mongo: "+ exchange.getIn().getHeader("CamelFileName"));
exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class).printStackTrace();
}
}
Enable tracing with trace="true":
<camelContext trace="true" xmlns="http://camel.apache.org/schema/spring">
Dirty but quick, to get the error you can add this to you configure() method before your from :
.onException(Exception.class).handled(true).process(new Processor() {
#Override
public void process(Exchange exchange) {
exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class).printStackTrace();
}
})
The handled(true) prevents your message from being processed again and again.
thanks for your help I have been able to get the error message.
The problem actually came from mongoDB itself and not camel or code. With the change on users the connection works and I'm able to insert document inside a collection.
Remove the ".process(myProcessorMongo)" from route configuration . Input xml-> json conversion->string conversion -> Mongodb. Above route will work. And you are passing the exchange object to myProcessorMongo but Out message is null so nothing will be inserted into MongoDB . Put exchange.getOut().getBody(); in the myProcessorMongo and print it.If its coming as null u have to get the input message from exchange Obj and set it back it in to Out message property in the exchange Object.

Jersey JAXB Based JSON support

I am trying to use Jersey's capabilities to produce JSON from my web-service methods.
Everything worked well but then I discovered that for a list of objects JSON representation contains something like enclosing root tag. I found out that I can configure JAXB Based JSON support with JSONConfiguration.natural() to produce a desirable result. So I wrote the following
#Provider
#Produces(MediaType.APPLICATION_JSON)
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
private final JAXBContext context;
private final Set<Class> types;
private final Class[] cTypes = {TrRegion.class};
public JAXBContextResolver() throws Exception {
this.types = new HashSet(Arrays.asList(cTypes));
this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), cTypes);
}
#Override
public JAXBContext getContext(Class<?> objectType) {
return (types.contains(objectType)) ? context : null;
}
}
And plugged it in like this
public class WebServiceApplication extends Application {
#Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> resources = new HashSet<Class<?>>();
resources.add(OrderInfrastructureResource.class);
resources.add(OrderResource.class);
resources.add(JAXBContextResolver.class);
return resources;
}
}
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.[...].WebServiceApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
But for some reason I always get
java.lang.IllegalStateException: No JAXB provider found for the following JAXB context: class com.sun.xml.bind.v2.runtime.JAXBContextImpl
at com.sun.jersey.json.impl.JSONHelper.getJaxbProvider(JSONHelper.java:106) [jersey-json-1.17.jar:1.17]
at com.sun.jersey.json.impl.JSONHelper.getJaxbProvider(JSONHelper.java:106) [jersey-json-1.17.jar:1.17]
at com.sun.jersey.json.impl.DefaultJaxbXmlDocumentStructure.getXmlDocumentStructure(DefaultJaxbXmlDocumentStructure.java:76) [jersey-json-1.17.jar:1.17]
at com.sun.jersey.json.impl.writer.Stax2JacksonWriter.<init>(Stax2JacksonWriter.java:169) [jersey-json-1.17.jar:1.17]
at com.sun.jersey.json.impl.Stax2JsonFactory.createWriter(Stax2JsonFactory.java:105) [jersey-json-1.17.jar:1.17]
at com.sun.jersey.json.impl.provider.entity.JSONListElementProvider.writeList(JSONListElementProvider.java:133) [jersey-json-1.17.jar:1.17]
Can someone tell me why?
When I change the line
this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), cTypes);
to
this.context = new JSONJAXBContext(JSONConfiguration.mapped().build(), cTypes);
it begins to work but gives enclosing root tag(well it is the same as not specifying any ContextResolver). Strange.(Strange meaning, that the difference is only in mapping type I provide).
I try to run my app on Jboss 7.1.1 with Restesy disabled(I have removed lines <extension module="org.jboss.as.jaxrs"/> and <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/> from my standalone.xml file). Also I use com.sun.jersey.spi.spring.container.servlet.SpringServlet as Jersey servlet.
Please, tell me what am I missing.
What could be the problem?
Apparently I was missing jaxb-impl library for my application so I just added jBoss' com.sun.xml.bind module in my jboss-deployment-structure file as following:
<dependencies>
<module name="com.sun.xml.bind" />
<module name="org.codehaus.jackson.jackson-core-asl" />
<module name="org.codehaus.jackson.jackson-jaxrs" />
<module name="org.codehaus.jackson.jackson-mapper-asl" />
<module name="org.codehaus.jackson.jackson-xc" />
</dependencies>

Spring 3.0.5 - Adding #ModelAttribute to handler method signature results in JsonMappingException

I'm not sure whether this is a misconfiguration on my part, a misunderstanding of what can be accomplished via #ModelAttribute and automatic JSON content conversion, or a bug in either Spring or Jackson. If it turns out to be the latter, of course, I'll file an issue with the appropriate folks.
I've encountered a problem with adding a #ModelAttribute to a controller's handler method. The intent of the method is to expose a bean that's been populated from a form or previous submission, but I can reproduce the issue without actually submitting data into the bean.
I'm using the Spring mvc-showcase sample. It's currently using Spring 3.1, but I first encountered, and am able to reproduce, this issue on my 3.0.5 setup. The mvc-showcase sample uses a pretty standard servlet-context.xml:
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven conversion-service="conversionService">
<argument-resolvers>
<beans:bean class="org.springframework.samples.mvc.data.custom.CustomArgumentResolver"/>
</argument-resolvers>
</annotation-driven>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- Imports user-defined #Controller beans that process client requests -->
<beans:import resource="controllers.xml" />
<!-- Only needed because we install custom converters to support the examples in the org.springframewok.samples.mvc.convert package -->
<beans:bean id="conversionService" class="org.springframework.samples.mvc.convert.CustomConversionServiceFactoryBean" />
<!-- Only needed because we require fileupload in the org.springframework.samples.mvc.fileupload package -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
</beans:beans>
The controllers.xml referenced in the file simply sets up the relevant component-scan and view-controller for the root path. The relevant snippet is below.
controllers.xml
<!-- Maps '/' requests to the 'home' view -->
<mvc:view-controller path="/" view-name="home"/>
<context:component-scan base-package="org.springframework.samples.mvc" />
The test bean which I am attempting to deliver is a dead-simple POJO.
TestBean.java
package org.springframework.samples.mvc.test;
public class TestBean {
private String testField = "test#example.com";
public String getTestField() {
return testField;
}
public void setTestField(String testField) {
this.testField = testField;
}
}
And finally, the controller, which is also simple.
TestController.java
package org.springframework.samples.mvc.test;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
#RequestMapping("test/*")
public class TestController {
#ModelAttribute("testBean")
public TestBean getTestBean() {
return new TestBean();
}
#RequestMapping(value = "beanOnly", method = RequestMethod.POST)
public #ResponseBody
TestBean testBean(#ModelAttribute("testBean") TestBean bean) {
return bean;
}
#RequestMapping(value = "withoutModel", method = RequestMethod.POST)
public #ResponseBody
Model testWithoutModel(Model model) {
model.addAttribute("result", "success");
return model;
}
#RequestMapping(value = "withModel", method = RequestMethod.POST)
public #ResponseBody
Model testWithModel(Model model, #ModelAttribute("testBean") TestBean bean) {
bean.setTestField("This is the new value of testField");
model.addAttribute("result", "success");
return model;
}
}
If I call the controller via the mapped path /mvc-showcase/test/beanOnly, I get a JSON representation of the bean, as expected. Calling the withoutModel handler delivers a JSON representation of the Spring Model object associated with the call. It includes the implicit #ModelAttribute from the initial declaration in the return value, but the bean is unavailable to the method. If I wish to process the results of a form submission, for example, and return a JSON response message, then I need that attribute.
The last method adds the #ModelAttribute, and this is where the trouble comes up. Calling /mvc-showcase/test/withModel causes an exception.
In my 3.0.5 installation, I get a JsonMappingException caused by a lack of serializer for FormattingConversionService. In the 3.1.0 sample, the exception is caused by lack of serializer for DefaultConversionService. I'll include the 3.1 exception here; it seems to have the same root cause, even if the path is a bit different.
3.1 org.codehaus.jackson.map.JsonMappingException
org.codehaus.jackson.map.JsonMappingException: No serializer found for class org.springframework.format.support.DefaultFormattingConversionService and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.validation.support.BindingAwareModelMap["org.springframework.validation.BindingResult.testBean"]->org.springframework.validation.BeanPropertyBindingResult["propertyAccessor"]->org.springframework.beans.BeanWrapperImpl["conversionService"])
at org.codehaus.jackson.map.ser.StdSerializerProvider$1.failForEmpty(StdSerializerProvider.java:89)
at org.codehaus.jackson.map.ser.StdSerializerProvider$1.serialize(StdSerializerProvider.java:62)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:272)
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:147)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:272)
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:147)
at org.codehaus.jackson.map.ser.MapSerializer.serializeFields(MapSerializer.java:207)
at org.codehaus.jackson.map.ser.MapSerializer.serialize(MapSerializer.java:140)
at org.codehaus.jackson.map.ser.MapSerializer.serialize(MapSerializer.java:22)
at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:315)
at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:242)
at org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:1030)
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.writeInternal(MappingJacksonHttpMessageConverter.java:153)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:181)
at org.springframework.web.servlet.mvc.method.annotation.support.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:121)
at org.springframework.web.servlet.mvc.method.annotation.support.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101)
at org.springframework.web.servlet.mvc.method.annotation.support.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:81)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:64)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter.invokeHandlerMethod(RequestMappingHandlerMethodAdapter.java:505)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter.handleInternal(RequestMappingHandlerMethodAdapter.java:468)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at
...
So, is there some configuration I am missing that should allow the Jackson converter to properly handle a response derived from a handler with #ModelAttribute in the method signature? If not, any thoughts as to whether this is more likely a Spring bug or a Jackson bug? I'm leaning toward Spring, at this point.
It looks like a Spring config problem, when serializing to JSON the DefaultFormattingConversionService is empty and Jackson (by default) will throw an exception if a bean is empty see FAIL_ON_EMPTY_BEANS in the features documentation. But I am not clear why the bean is empty.
It should work if you set FAIL_ON_EMPTY_BEANS to false, but still doesn't really explain why it is happening in the first place.
DefaultFormattingConversionService is new to 3.1 - it extends the FormattingConversionService which explains the different exceptions between 3.0.5 and 3.1.
I do not think it is a Jackson problem, although a new version of Jackson (1.8.0) was released only 3 days ago so you could try that also.
I will try to reproduce this locally.