I have a Main() class where I serialize an object of a class called Names. I am using Apache HttpClient's HttpPost() to call a servlet.
public static void main(String[] args) {
Names names = new Names();
names.setName("ABC");
names.setPlace("Bangalore");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("Name.txt"));
out.writeObject(names);
out.close();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost:6080/HttpClientGson/FirstHttpPostServlet");
Now, how do I send the ObjectOutputStream object? I wrote the following line
httppost.setEntity(out)
But setEntity() can only take objects of HttpEntity type. Is there any other method of HttpClient that I can use to send serialized object?
You could SerializableEntity class shipped with HttpClient
httpost.setEntity(new SerializableEntity(mySerializableObj, false));
Please note, though, that binary object serialization should be used only when absolutely required. Other serialization formats such as XML or JSON should generally be preferred.
You can use XStream to serialize an object to XML/JSON.
http://x-stream.github.io/
and then to pass it.
Related
I am trying to access httpServletRequest inside a component class. I tried it in several ways.
#Component
public class MyService{
#Resource
WebServiceContext wsCtxt;
public void myWebMethod(){
MessageContext msgCtxt = wsCtxt.getMessageContext();
HttpServletRequest req = (
(HttpServletRequest)msgCtxt.get(MessageContext.SERVLET_REQUEST);
String clientIP = req.getRemoteAddr();
}
This didn't work for me. because WebServiceContext is always null. Then I tried same code inside Web service class. Then that code is working. My Requirement it to get HttpServletRequest inside component class. (ultimately What i am trying to do it get client host from request header).
It this possible to do ?. Are there any alternatives for this ?
Method #1
Have you tried passing the request object into your component by passing it in as an argument to your service method, and from your service to your component method?
// in your controller... Spring provides the request object
public String myController(HttpServletRequest request, ...) {
//...
myService.myServiceMethod(request,...);
}
// in your service...
public void myServiceMethod(HttpServletRequest request, ...) {
//...
myComponent.myWebMethod(request,...);
}
// in your component
public String myWebMethod(HttpServletRequest request, ...) {
// use the raw request object
}
Method #2
Also, DispatcherServlet exposes the request object by wrapping it in a ServletRequestAttributes object, which in turn is stored in a ThreadLocal variable. The actual storing takes place in RequestContextHolder and its static methods. You can access it as follows:
public void myWebMethod(){
//...
RequestAttributes reqAttr = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servlReqAttr = (ServletRequestAttributes)reqAttr;
HttpServletRequest req = servlReqAttr.getRequest();
//...
}
Although a little verbose, you can see what's going on.
You could also condense it:
((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
I hope this helps!
I am returning a string object from spring controller like
#RequestMapping(value = "/persons.html", method = RequestMethod.GET)
public #ResponseBody String listPersonHtml(Model model) {
return "{\"abc\":\"test\"}";
}
I am getting response on ui like "{\"abc\":\"test\"}",i want this response as
{"abc":"test"}
i.e pure json object.
what type of configuration I need?
On UI side,if I set Accept */* then I face this issue,if I set Accept text/html or Accept text/plain then no issue is there,but I can't change accept header.
I found the way.Its all about spring message-converters.I added MappingJackson2HttpMessageConverter in this list and this converter tries to convert string to json and produces this result.
Just add org.springframework.http.converter.StringHttpMessageConverter before MappingJackson2HttpMessageConverter so that StringHttpMessageConverter can come into action and string can be returned as it is.
Old question, but I just had to solve the same issue and most of the answers I found resulted misleading, so here's mine:
It all starts with the Controller, and Spring trying to answer a mapped request in the format that the invoking client is expecting. The client can inform this using different HTTP features, and there is where the different HttpMessageConverter implementations are involved. Spring pick's the format to answer based on different strategies, applied by the ContentNegotiationManager.
By prioritizing StringHttpMessageConverter over MappingJackson2XmlHttpMessageConverter you are only telling Spring to answer in "text/plain" format over "application/json", and it will work until a client specifies that is expecting a json response (this is mostly done by setting the Accept header in the request, although there are other ways to do it). The important thing is that if a client sets that header to "application/json", Spring will use MappingJackson2XmlHttpMessageConverter that will translate the Java String to a Json String, ending up with something like "{\"abc\":\"test\"}" instead of {"abc":"test"}
So, the real issue that every developer faces in this case is that MappingJackson2XmlHttpMessageConverter translates a Java String to a Json String, and in some cases, you might not need that, because the string contains valid json that needs to be returned without modifications. There are some configuration classes for this MessageConverter but I did'n went that road, because I need to return Strings like "raw" Json only in some specific endpoints (performance is the key driver). Here's an expample that resumes my "approach":
#RestController
#RequestMapping(value = "test", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class TestController {
#RequestMapping(method = RequestMethod.GET, value = "endpoint")
public JsonObject getSomeJson() {
return new JsonObject("{\"abc\":\"test\"}");
}
private static class JsonObject {
private String rawJsonValue;
JsonObject(String rawJsonValue) {
this.rawJsonValue = rawJsonValue;
}
#JsonValue #JsonRawValue
public String getRawJsonValue() {
return rawJsonValue;
}
}
}
#JsonValue and #JsonRawValue are Jackson annotations that tell MappingJackson2XmlHttpMessageConverter to treat the getRawJsonValue method result as the Json representation of JsonObject, without making any modification. The response of the endpoint will be {"abc":"test"}
Spring web application configuration contains Jackson ObjectMapper configured like this
objectMapper.disable(ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
objectMapper.registerModule(new JavaTimeModule())
JavaTimeModule is added to handle deserialisation of ZonedDateTime. There are two endpoint which handle a POJO which contains ZonedDateTime. The POJO is like this:
class MyRequest {
ZonedDateTime from
ZonedDateTime to
}
and controller with endpoints is:
#Slf4j
#RestController
class MyController {
#GetMapping('/pojo')
void getPojo(MyRequest myRequest) {
log.debug("Request received: $myRequest")
}
#PostMapping('/pojo')
void postPojo(#RequestBody MyRequest myRequest) {
log.debug("Request received: $myRequest")
}
}
When I send POST /pojo with body
{"from": "2017-03-15T00:00:00Z", "to": "2017-03-16T00:00:00Z"}
The response is 200 and deserialisation is successful.
Contrary, when I send
GET /pojo?from=2017-03-15T00:00:00Z&to=2017-03-15T00:00:00Z
The 400 Bad Request is received with error
Failed to convert from type [java.lang.String] to type [java.time.ZonedDateTime] for value '2017-03-15T00:00:00Z'
This make sense, since in GET request, I'm not sending JSON and therefore JSON object mapper is not called.
Is there a way to use objectMapper for GET requests also, so query parameters are converted into POJO object?
By the way, I know that it can be deserialised for GET endpoint like below, but I want to use same converter for GET and POST endpoint
#DateTimeFormat(iso = ISO.DATE_TIME)
ZonedDateTime from
#DateTimeFormat(iso = ISO.DATE_TIME)
ZonedDateTime to
Injecting objectMapper and converting query parameters map into object solves the problem
#Slf4j
#RestController
class MyController {
#Autowired
private ObjectMapper objectMapper
#GetMapping('/pojo')
void getPojo(#RequestParam Map<String, String> allRequestParams) {
MyRequest request = objectMapper.convertValue(allRequestParams, MyRequest)
log.debug("Request received: $myRequest")
}
...
I am using SignalR 1.1 with .NET clients.
I have a single method in my hub that accepts an object of BaseMessage class and broadcasts it to all clients:
public void SendMessage(BaseMessage message)
{
Clients.All.BroadCastMessage(message);
}
Clients will pass derived messages into this method:
_hub.Invoke("SendMessage", new ErrorMessage("Some Error")).Wait();
The client has a single message handler:
_hub.On<BaseMessage>("BroadCastMessage", OnMessageReceived);
I've specified TypeNameHandling.All serializer settings at application startup:
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All};
var serializer = new JsonNetSerializer(settings);
GlobalHost.DependencyResolver.Register(typeof(IJsonSerializer), () => serializer);
But when the client sends a derived message, the server receives a base message.
How should I configure serializer to be able to receive derived messages?
Note: I can do serialization/deserialization manually and pass strings to the server, but this causes double serialization.
SignalR is not supporting this scenario as it would require your JSON payload to contain information about the derived type and assembly. See this sample.
Adding type information in your payload would not play well with browsers. I suggest you create individual hub methods to handle each of your derived types.
I'm trying to deserialize an object which was generated by LinqToSql. The user is allowed to edit the data of the object in the view and then it gets posted back to the controller. The edited Data comes in JSON. How does this action have to look like?
Something like...
public ActionResult(JsonObject json)
{
MyClass c = Jsonify(json) as MyClass;
}
Is there a nice helpful static class in the framework I'm missing? Or do I have to create a DataContract?
Many thanks
System.Web.Script.Serialization.JavaScriptSerializer
public ActionResult Blah(JsonObject json)
{
JavaScriptSerializer js = new JavaScriptSerializer();
var c = js.Deserialize<MyClass>(json);
return View(c);
}
EDIT: Oops...just noticed you are passing an object instead of string....so you will need to use System.Runtime.Serialization.Json.DataContractJsonSerializer:
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(MyClass));
MyClass c = (MyClass)serializer.ReadObject(json);