Sending data from client to server in Spring - java

I am developing a web application using spring MVC, Hiberbate and MySQL database. I am trying to send data to server from a client, but I can not do it.
In detail,
I want to send my JSON data to http://localhost:8080/app/test . In my test controller I want to get the data which comes from the client and write it to screen or save it to db. I have been searching about 3 days and I have tried many strategies to do it, but I can not.

You must explicitly tell spring to use a json parser.
For instance, here is a piece of my DispatcherServlet config :
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
Jackson Must be in your classpath.
Then you write a method like this one in your annotated controller :
#RequestMapping(value = "/test", method = RequestMethod.POST)
public void myMethod(#RequestBody MyObject object) {
//... do what you want with the object
}
You just have to send an JSON object with properties that match the ones in MyObject, via a POST request.

Related

Why the Mongodb queries become slowly

I setup a Java web application project which is based on MongoDB. The DAO of the this project is implemented by MongoDB Java driver; I didn't use the Spring Data for MongoDB.
I'm getting a performance problem. If the application sends a query to the database, the response time is about 17ms. But if I used the Jmeter -- which mocked about 300 users -- the response time of 90%Line is about 1300ms. The response time is intolerable. I tried to find the reason, but I don't know.
Also, there is the MongoUri String:
mongo.uri=mongodb://192.168.1.172:27017,192.168.1.172:22222,192.168.1.172:33333/?replicaSet=yyyy&maxPoolSize=100&ssl=false&readPreference=secondaryPreferred&connectTimeoutMS=10000&socketTimeoutMS=10000&safe=false&
The query is just like a query for an objectID, like db.collection.find( { _id: xxxx } ). Also, I've constructed the index on _id.
mongo.xml
<bean id="uri" class="com.mongodb.MongoClientURI">
<constructor-arg value="${mongo.uri}"></constructor-arg>
</bean>
<bean id="mongoClient" class="com.mongodb.MongoClient">
<constructor-arg ref="uri"></constructor-arg>
</bean>
<bean id="mongoCollectionDao" class="com.xxx.api.domain.dao.impl.MongoCollectionDao" lazy-init="false">
<constructor-arg name="mongoClient" ref="mongoClient"></constructor-arg>
<constructor-arg name="mongoDatabaseName" value="${mongo.database}"></constructor-arg>
</bean>
Could anyone explain what's going wrong here?

New to Spring and Jackson 2. What does this bean declaration allow for in a Spring MVC application?

I have inherited a spring MVC project that basically has several controllers. I came across a declaration in an xml file. Apparently, this declaration allows for writing rest-based services and clients. Could someone explain with an example the apparent magic these declarations allow for?
<bean id="restClient" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<util:list>
<bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
<bean id="formMessageConverter" class="org.springframework.http.converter.FormHttpMessageConverter"/>
</util:list>
</property>
</bean>
Thank you in advance.
resttemplate by spring , provided to convert your java object to desired output(html string, xml, json etc) during the service call over the network, and inturn the received response from the service will be unmarshalled back to java object or desired datatype.
<property name="messageConverters">
<util:list>
<bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
<bean id="formMessageConverter" class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean id="messageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter" />
</util:list>
//marhsaller and unmarshaller
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<property name="marshaller" ref="jaxbMarshaller"></property>
<property name="unmarshaller" ref="jaxbMarshaller"></property>
<property name="supportedMediaTypes">
<list>
<value>application/xml</value>
<value>text/xml</value>
<value>json</value>
</list>
</property>
through above configuration resttemplate will use those appropriate converters to handle different datatypes, as i said it may be html, json or application xml
all we are doing is, with out writing java code , we are configuring the resttemplate and will be in spring context , this configuration applies where ever your resttemplate been used.
i have example here
let us say we invoke a service to check an user is valid user or not
class User{
string userId;
string password;
}
and service response with some code as 1 is valid and 0 as invalid
class ValidUser{
int validCode;
}
first you need to marshall into any of the acceptable datatype , let us have application/xml
all i am doing here is through config file
to above configuration i am adding jaxb marshaller and unmarshaller (see above config)
i have configured both marshaller and unmarshaller, and i am telling the acceptable datatypes which both should use while marshalling and unmarshalling
and finally, the below configuration tells the java objects which are acceptable during marshalling (request.User will be converted to xml) and unmarshalling (xml to convert back to response.validUser)
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.request.user</value>
<value>com.response.validUser</value>
</list>
</property>
</bean>
on here comes the java code
here you directly pass your java object , and your resttemplate will marshall it without any hassle !!!
User user = new User();
user.setName('test');
user.setPassword('password');
// setting media type as xml, and telling convert my user java obj to xml
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<User> entity = new HttpEntity<User> (user , headers);
ResponseEntity<validUser> responseEntity = rest.exchange(URL, HttpMethod.POST, entity, validUser.class);
// let us assume that service response for valid user <validCode>1<validCode>
//then validuserreponse obj will have code as 1, let us say valid user.
ValidUser validUserResponse = responseEntity.getBody();
like wise you can also handle plain html text
headers.setContentType(MediaType.TEXT_HTML);
HttpEntity<String> entity = new HttpEntity<String>(htmlString, headers);
ResponseEntity<String> htmlStringresponse = rest.postForEntity(URL, entity, String.class);
if you see, the above java code, dont have any message converter code, marshaller and unmarshaller logic, all done in one liner with use of spring configuration.

Spring MappingJacksonJsonView, how to tell to use it instead of JSP view?

I'm trying to use MappingJacksonJsonView with Spring 3.0, without success. I don't know what I'm doing wrong, I think the problem is that I don't know how to tell to use the MappingJacksonJsonView to render a request. I tried to use the same name for view name and bean name of MappingJacksonView, but didn't work. I built a sample test application here: https://github.com/stivlo/restjson
In web.xml I've defined ContextLoaderListener and the mapping for dispatcherServlet.
In servlet-context.xml I've added
<mvc:annotation-driven/>
and
<bean name="jsonView"
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
In org.obliquid.restjson.web.ToDoList.java I set the logical view name as jsonView.
However, instead of using MappingJacksonJsonView, it looks for a JSP file, according to my JSP mapping.
message /restjson/WEB-INF/jsp/jsonView.jsp
description The requested resource (/restjson/WEB-INF/jsp/jsonView.jsp)
is not available.
What should I change to use MappingJacksonJsonView as a renderer?
UPDATE 1: In following tests I've found that if I add the following to my servlet-context.xml, JSON rendering works, but my other view, rendered as JSP (home) is not working anymore.
<!-- Resolve views based on string names -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
UPDATE 2: I removed the BeanNameViewResolver and changed my ToDoList.java to return directly the Collection to be converted in JSON, instead of ModelAndView, with a #ResponseBody annotation, as follows:
#RequestMapping("/toDoList")
public #ResponseBody List<ToDoItem> test() {
List<ToDoItem> toDoList = new ArrayList<ToDoItem>();
toDoList.add(new ToDoItem(1, "First thing, first"));
toDoList.add(new ToDoItem(1, "After that, do the second task"));
return toDoList;
}
In this way it works. Even though the mapping is even more "magical". It makes me wonder, if a similar renderer exists for XML for instance, how does Spring know which renderer to pick?
Spring will use Accept header sent by the client to return most appropriate view. Here you will find my complete Spring MVC application that returns both JSON and XML.
As you can see, I only needed:
<mvc:annotation-driven />
I also used the same annotations: #RequestMapping to map request to a method and #ResponseBody to tell Spring that what I am returning from the controller is the actual response. It might however need some tweaking/formatting, and here Spring takes care of marshalling your object into most appropriate type like JSON.
You should do it this way:
In your xml file set the following: set
<mvc:annotation-driven />
After it you need to set Jackson serializer:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
after it you can use it in your Controller:
#RequestMapping(value="/getObjects",method = RequestMethod.POST)
#ResponseBody
public List<MyObject> getCategories(){
List<MyObject> objects = daoService.gettAllObjects();
return objects;
}
Adding the following worked in my case
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="0" />
</bean>
So basically we should try to resolve any view as a bean first
you will need to see ContentNegotiatingViewResolver,and set defaultviews property to MappingJacksonJsonView, and #ResponseBody uses HttpMessageConverter to instead of ViewSolver,see the differences between them
http://ufasoli.blogspot.com/2013/08/viewresolver-vs-messageconverter-spring.html

Convert SOAP to a virtual Restful service?

Is there a way to use my SOAP web service(spring-ws, java) as a XML based RESTful service virtually?
I don't want to re-write whole my SOAP web service into RESTful from scratch in java, but I need to access it through iphone using REST, which they already have easy native support.
XMLGateway, Proxys..? or some extra java code? since my SOAP request and response is simply an XML file why can't I modify it to be used by a REST service?
Or without changing changing any logic and xml parsing in my application is that easy to add jax-rs annotations and create a rest request xml?
my config spring file is like this:
<bean id="webServicePluginDescriptor"
class="com.mysite.ws.configuration.MyWebservicePluginDescriptor" />
<bean id="payloadMapping"
class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<property name="defaultEndpoint" ref="inferenceEndPoint" />
<property name="interceptors">
<list>
<ref local="validatingInterceptor" />
<ref local="payLoadInterceptor" />
</list>
</property>
</bean>
<bean id="payLoadInterceptor"
class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" />
<bean id="validatingInterceptor"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema"
value="classpath:/wsdl/Request.xsd" />
<property name="validateRequest" value="true" />
<property name="validateResponse" value="false" />
</bean>
<bean id="PropertyResource" class="com.mysite.ws.im.PropertyResource">
<property name="resource"
value="/WEB-INF/client-specific/InferenceMachine.properties" />
</bean>
<bean id="inferenceEndPoint" class="com.mysite.ws.web.InferenceEndPoint">
<property name="messageWebService" ref="messageWebService" />
</bean>
<bean id="messageWebService" class="com.mysite.ws.service.MessageWebService"
scope="request">
<aop:scoped-proxy />
<property name="inferenceService" ref="inferenceService" />
</bean>
<bean id="Request" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:/wsdl/Request.xsd" />
</bean>
<bean id="Response" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:/wsdl/Response.xsd" />
</bean>
<bean id="Error" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:/wsdl/Error.xsd" />
</bean>
<bean id="mwsid"
class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
<constructor-arg value="classpath:/wsdl/mtchwsdl.wsdl" />
</bean>
<bean id="inferenceService" class="com.mysite.ws.im.InferenceService"
scope="request">
<aop:scoped-proxy />
<property name="webServiceConfiguration" ref="wsPlayerConfiguration" />
<property name="properties">
<bean class="com.mysite.ws.im.PropertyResource">
<property name="resource"
value="/WEB-INF/client-specific/InferenceMachine.properties" />
</bean>
</property>
</bean>
<!-- ~~~~~~~ Application beans ~~~~~~~ -->
<bean id="wsPlayerConfiguration"
class="com.mysite.ws.configuration.WebServiceConfiguration"
scope="request">
<aop:scoped-proxy />
<property name="playerConfiguration" ref="playerConfiguration"></property>
<property name="configurationSetup" ref="configurationSetup"></property>
</bean>
and this is my endpoint class:
/**
* The EndPoint of the Web Service Application. This class gets the raw
* SOAP-body message from the Spring Payload Dispatcher and sends the message to
* the #see MessageService class. After it has gotten the response XML message
* it returns this back to the Spring Payload Dispatcher.
*/
public class InferenceEndPoint extends AbstractJDomPayloadEndpoint {
private MessageWebService messageWebService;
public InferenceEndPoint() {
}
#Override
protected Element invokeInternal(Element inferenceRequest) throws Exception {
Element ret = messageWebService.handleRequest(inferenceRequest);
return ret;
}
/**
* #param messageWebService
*/
public void setMessageWebService(MessageWebService messageWebService) {
this.messageWebService = messageWebService;
}
}
any ideas?
Spring-WS just adds some annotations to your beans and then you have Spring beans doing most of the heavy lifting. Presumably you have some classes annotated with #Endpoint, #PayloadRoot and the like. You should be able to re-use all of these in one of three ways.
If your Spring-WS endpoint classes are adapter pattern style (e.g. your Endpoint class is injected with a POJO service that does the real work), then you could do a similar adapter-style Spring MVC Controller (where REST exists in Spring 3.0).
If you have your annotations directly on your business logic class, then in theory, you should be able to just sprinkle on some more annotations (might get a little busy-looking).
If you have Spring-WS beans that are POX (and not SOAP), then you might be able to get away with some fancy URL mappings to give them more RESTful looking URLs
To migrate to the Spring 3 for REST support, add the appropriate #RequestMapping and another annotations to expose them as REST services to match specific URLs. While you're adding, you might as well remove the old #PayloadRoots and #Endpoint, but that may not be a big deal. Of course if you leave old Spring-WS annotations around, you'll still need the Spring-WS jars on your classpath, but as long as you are not using a Spring-WS servlet nor any other other beans in your Spring file - you should be okay (in theory...).
The biggest gotchas will be:
Don't forget to remove Spring-WS beans from your Spring file
DO remember to add the Spring MVC beans to your Spring file, and most importantly different Dispatcher servlet
REST security in Spring will be provided by Spring Security, not the same SOAP interceptors found in Spring-WS, so that will be a complete overhaul. The good news is that Spring Security is actually pretty easy to work with
Looking at your code, it's very difficult to tell what the best approach would be. REST and SOAP are really quite different ways of imagining how a web-based service interface could work: SOAP is all about method calls, and REST is all about resources, representations and links. To convert, you have to start from your underlying abstract API.
If your basic API is one of “I give you a document, you give me a response document” and there's no exposure of anything other than that, it's a very SOAP-oriented model. You can model that in REST through POSTing a document and getting a response, but it's not at all elegant. If you can instead think of your interface in terms of “here's an overall resource, with properties I can set, and certain operations I can do” then that maps to REST far more easily (the overall resource is represented as a document full of links to individual property resources and operations, and the individual properties can be GET and PUT – and possibly DELETEd – as necessary). Which style you've got… well, it looks a lot like you've got the first, but I'm only guessing because determining it for real would require looking at more of your code than you've shown.
There's nothing stopping you from send POST filled with XML to get results filled with XML back.
The simplest thing to do is somehow capture the SOAP requests going back and forth, and simply turn the request in to a template with the blanks being your parameters, and then using XPath on the resulting XML to pull your results out.
The only nit being you might need SOAPAction header in your POST, but likely not.
It's really no big deal. If you have dozens of methods, it's more of a pain. Also, if you're using any of the encryption parts of SOAP, then it's more of a pain. But if just a few, in the end it's just XML, and a bulk of that XML is boilerplate, so looked at that way, it's pretty straightforward.
Addenda:
If you have back end logic that you want to front with a more HTTP friendly service, then JAX-RS can to that quite easily, but it would require coding on the server end.
If you have an existing SOAP web service that you wish to use, then forget the whole SOAP part of the equation, and simply treat it as an HTTP web service that uses XML payloads. It's still SOAP, but you're not using any SOAP tooling on the client side. You're simply assembling XML payloads on the client requests (from templates would be easiest, IMHO), and consuming XML payloads as a result, and trading these over HTTP.
Depending on how many different methods on the existing web service you intend to call gives you an idea of the scope of the work involved. It's simple work (once you can view the payloads easily), but it's still work. If you only have a few methods, especially if the interface is stable and not changing, it's far easier to just work with the raw XML than learn and fight some new unfamiliar framework.
This is how I solved that problem, using Spring Boot + Spring Integration.
Having a WSDL of the SOAP WS, I used maven-jaxb2-plugin to have my Java POJO's generated at build time.
Optionally, you could create transformations to adapt those classes and attributes to what the REST client expected.
Using Spring Integration, I mapped every REST endpoint to a SOAP gateway like this:
#Bean
public IntegrationFlow myFlow(GenericTransformer reqTransformer, GenericTransformer resTransformer) {
return IntegrationFlows
.from(this.getRestGateway(POST, "/api/entity", MyRestResponse.class))
.transform(reqTransformer)
.handle(this.getSoapGateway("gwBean"))
.enrichHeaders(h -> h.header(HttpHeaders.STATUS_CODE, HttpStatus.OK))
.transform(resTransformer)
.logAndReply();
}
private HttpRequestHandlingMessagingGateway getRestGateway(HttpMethod method, String path, Class payloadType) {
HttpRequestHandlingMessagingGateway httpGateway = new HttpRequestHandlingMessagingGateway();
RequestMapping requestMapping = new RequestMapping();
requestMapping.setMethods(method);
requestMapping.setPathPatterns(path);
httpGateway.setRequestMapping(requestMapping);
httpGateway.setReplyTimeout(timeout);
httpGateway.setRequestPayloadTypeClass(payloadType);
httpGateway.setMessageConverters(asList(jsonConverter));
return httpGateway;
}
private MarshallingWebServiceOutboundGateway getSoapGateway(String nameBean) {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(generatedClassesPackage);
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
messageFactory.setSoapVersion(SoapVersion.SOAP_12);
messageFactory.afterPropertiesSet();
MarshallingWebServiceOutboundGateway webServiceGateway = new MarshallingWebServiceOutboundGateway(soapUri, marshaller);
webServiceGateway.setMessageFactory(messageFactory);
webServiceGateway.setBeanName(nombreBean);
return webServiceGateway;
}

Spring REST | MappingJacksonHttpMessageConverter produces invalid JSON

I've implemented a RESTful web service with Spring. The service responds in XML or JSON based on the Accept header. Here's the context.xml mapping:
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
<bean id="xmlMessageConverter"
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="xstreamMarshaller"/>
<property name="supportedMediaTypes" value="application/xml"/>
</bean>
<bean id="jsonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="prefixJson" value="false"/>
<property name="supportedMediaTypes" value="application/json"/>
</bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list id="beanList">
<ref bean="xmlMessageConverter"/>
<ref bean="jsonHttpMessageConverter"/>
</util:list>
</property>
</bean>
Here is my controller method:
#Controller
#RequestMapping(value = "/entityService")
class RestfulEntityService {
#Resource
private EntityService entityService;
#ResponseBody
#RequestMapping(value = "/getAllEntities", method = RequestMethod.GET)
public List<Entity> getAllEntities() {
return entityService.getAllEntities();
}
}
The XML response is valid, however, when the client sets the Accept header to application/json, the response is invalid JSON.
Here is the JSON response sample:
[{"id":3,"attributes":[{"id":18,"attributeValue":null,"attributeName":"mobile","attributeType":"varchar(40)","entity":{"id":3,"attributes":[{"id":18,"attributeValue":null,"attributeName":"mobile","attributeType":"varchar(40)","entity":{"id":3,"attributes":[{"id":18,"attributeValue":null,"attributeName":"mobile","attributeType":"varchar(40)","entity":{"id":3,"attributes": ..... repeats for a while and then stops..
You're using XStream to serialize XML responses and Jackson JSON to serialize JSON responses. Looking at the JSON output you posted, it seems like there's a circular reference issue at hand. I'm guessing Entity has a list of attributes, each pointing to their respective entity. XStream handles circular references transparently by using XPath, this allows to preserve references when deserializing back to objects. Jackson is able to handle circular references since v1.6, but you need to help it by annotating your serialized entities with #JsonManagedReference and #JsonBackReference. I think Jackson is unique in allowing back references in JSON serialization.
See Jackson's documentation on handling bi-directional references using declarative methods for reference.

Categories