I try to implement a restful webservice in Java together with Jersey.
To communicate between the client- and server-side i´m watching out for XML.
I already tried JSON.
When using JSON, the encapsulation is in the POJO-Object like:
#XmlRootElement
public class MyPojo {
public int a;
public int[] b;
}
Then I just got a header in the Rest-Class like
public String classname(MyPojo p)
But I need a header like
public String classname(int a, int [] b)
to create Form-Elements automatically by reading the Rest-Headers.
An example showed me that:
#Consumes("application/xml")
public classname methodname(#QueryParam("a") Integer a, #QueryParam("b") IntArray b)
should work.
Question: How can I create a XML-Request (like JSON.stringify() in XML) for this method? Is there maybe a better way doing this?
Not sure if I understand the question, but will try to provide some hints - hopefully at least some of it will be relevant. If not, please share more about your app (i.e. is this for GET or POST requests? why is it important to have 2 separate parameters, etc.)
If you need to send XML or JSON in the request entity (e.g. in a POST request), then it is not possible to retrieve these in multiple parameters - you have to live with the single object parameter as you have above. What you could do is the following:
#POST
#Consumes("application/xml")
public ClassName postMethod(MyPojo p) {
return postMethod(p.a, p.b);
}
public ClassName postMethod(int a, int[] b) {
// do something
}
Or, if you don't really need XML/JSON, if you are POSTing using HTML forms, typically you do the following:
#POST
#Consumes("application/x-www-form-urlencoded")
public ClassName postMethod(#FormParam("a") Integer a, #FormParam("b") String b /*I think arrays are not supported - will have to parse it yourself*/) {
// do something
}
Related
I was having some problem when trying to execute POST request with multiple parameters. Here is my service.ts class written in typescript:
retrieve(packageId: any[], date: any) {
console.log(packageId);
console.log(date);
let packgeIdStr: string = JSON.stringify(packageId);
const data = { stringArrDo: packgeIdStr, date: date };
const url = this.serviceAPI + '/...../retrieve';
return this.http.post<SRFDO[]>(
url,
{ params: data }
);
}
When I print out in my console, I managed to get the data here.
However, when I pass the data to my controller written in Java, the parameters became null:
#PostMapping("/retrieve")
public DO[] retrieve(#RequestBody String stringArrDo, java.sql.Date date)
throws RemoteException, JaMClientRemoteException, JaMException {
System.out.println(stringArrDo);
System.out.println("date :"+ date);
// removed code
}
I not sure why the data is printed out at service.ts but when passing it to the controller then became null. Any ideas?
Thanks!
You can open up your Chrome dev tools, go to the Network tab, and inspect your POST to see if angular is actually passing the right stuff to the right endpoint. That will tell you if your problem is client-side vs server-side.
Edit:
It looks like your server may be expecting an array of strings, but you're sending an object. In javascript, when you do {var1, var2}, that's just shorthand for {var1: var1Value, var2: var2Value}
Edit 2: I looked up spring, and it looks like you're using #RequestBody incorrectly. It looks like you're supposed to pass it a class that it can deserialize the JSON into, like
public class RequestData {
private String[] packageIds;
private Date date;
// ...
}
You've also put your data under the top-level variable params, so you'd want to remove that and put all your stuff at the top level of your object.
Try reading through this tutorial for more info: https://www.baeldung.com/spring-request-response-body
The attributes name on two classes may be different.
class A{
// class in springboot
private String name;
}
class A {
//class in angular
data: String;
}
In this case, attribute name is main cause for null pointer exception in server side.
I have this post api:
#PostMapping
public void connect(#RequestBody String data)
{
int result = service.connect(data);
}
I want to send back the result to whomever called this REST api. How can I do it? Can I send a int or a whole Object in Json format? I would like both if possible.
Change the method return type to int, and simply return result. Spring Boot handles JSON serialization for you. You can return anything, as long as it's serializable: https://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
I have a web project with 2 Java Entities(Lets Say E1,E2) like how mybatis and VO works.
Object structure:
class E1{
String a;
.... n other data members
E2 e2;
}
class E2{
String b;
.... n other data members
}
Is it possible to make a single class in Android project, i.e.
class E1 {
String a;
String b; //This Data member belongs to class E2
}
and parse it with the help of a framework (like Jackson) or I have to write a custom class for that?
My JSON Data will look like this:
{
"E1": {
"a": "some data",
.
.
.
"E2": {
"b": "some data",
.
.
other data
}
}
}
Is there any API which can do this?
I asked this because with my web Application its not just 2 Class but atleast 10 interconnected class and I am not Using them in my android app. So don't wanna replicate the same classes in android app.
Also if you can suggest any other possible way.
It would be a very bad design practice/approach, making things very difficult to debug, error prone and not future proof (think about it, what if you add to one of the 10 classes a field that conflict with another class' field?).
Anyway, if you still want to trick your way out of the correct approach that would be to have 10 classes, I am not aware of any lib that provides you with this feature. You could parse json ==> 10 Java Map, then merge the 10 Map through the Map::putAll method and finally pass the obtained Map that contains all the objects to Jackson.
Your best bet is to use #JsonAnySetter annotation from Jackson library on the receiver POJO.
public class E1{
public String a;
private Map<String, Object> paramMap = new HashMap<>();
#JsonAnyGetter
public Map<String, Object> getParamMap() {
return paramMap;
}
#JsonAnySetter
public void setParamMap(String s, Object o) {
paramMap.put(s, o);
}
}
This will put every unimplemented attributes in a HashMap.
In combination with #JsonAnyGetter, the serialization of the receiver POJO will give the same result as the JSON input.
I have 2 different URLs :
GET /stuff/{id} (where id is an Integer)
GET /stuff/foo?bar={someValue} (foo is not an Integer, it is a hard coded String)
When calling /stuff/foo&bar=someValue, I have the following error:
Failed executing GET /stuff/foo&bar=someValue
...
Caused by: java.lang.NumberFormatException: For input string: "foo&bar=someValue"
The code is :
#GET
#Path("/stuff/{id}")
public Response getById(#PathParam("id") int id) {
// code
}
#GET
#Path("/stuff/foo")
public Response foo(#QueryParam("bar") String bar) {
// code
}
I am using RESTEasy and I would like to keep my URLs that way if possible. Obviously RESTEasy just tries the getById method where it should use the foo method.
How can I do to make this work in RESTEasy ? ("change your URLs" is not an answer without detailed explanations about RESTEasy limitations). I tried (to be sure) putting foo code before getById but I had the same error (of course).
Is there any priority notion between declared URLs ?
As a note : I already implemented that kind of URLs in another framework (python-flask) and it worked just fine : you just have to be careful to declare /stuff/foo before /stuff/{id} (specific case before a more generic one).
EDIT: I just made a stupid mistake ! I was calling /stuff/foo&bar=someValue where I should be calling /stuff/foo?bar=someValue. Thanks #Scobal for pointing it out !
You are calling GET /stuff/foo&bar=someValue
You should be calling GET /stuff/foo?bar=someValue
RESTEasy is trying to parse foo&bar=someValue as the {id} field.
I can't give you an answer about RESTEasy URL priorities but you could do this:
#GET
#Path("/stuff/{id}")
public Response getById(#PathParam("id") String id, #QueryParam("bar") String bar) {
try {
int intId = Integer.parseInt(id);
// do int id things
} catch(NumberFormatException e) {
// do foo + bar things
}
}
I'm using XmlRpcClient to connect to a XML-RPC server
In the response to my request in the XML response I will get:
int cpuLoad,
String fanStatus,
String fanStatusWorst,
String temperatureStatus,
String temperatureStatusWorst,
String rtcBatteryStatus,
String rtcBatteryStatusWorst,
String voltagesStatus,
String voltagesStatusWorst,
String operationalStatus
I'm using
HashMap result = (HashMap) xmlRpcClient.execute(METHOD_DEVICE_HEALTH, params );
to retrieve results, but not sure how can I iterate over each value to
find operationalStatus value.
Is there a more elegant solution to parse results using xmlRpcClient? So I just retrieve the fields I'm interested?
Thanks
Actually there are more than one answer to your question depending on your cenario.
1) If you are communicating with Java based system using XML-RPC
Apache XML-RPC library comes with handy class called ClientFactory. This class allows you to bind your service interface (in your case the interface of the object you are invoking METHOD_DEVICE_HEALTH) to an object in the JVM of your consumer (the object that invokes xmlRpcClient.execute(METHOD_DEVICE_HEALTH, params)). For more details about the implementation, take a look at this link.
In this cenario, you can even have an transfert object like
public class DeviceHealth {
int cpuLoad,
String fanStatus,
String fanStatusWorst,
String temperatureStatus,
String temperatureStatusWorst,
String rtcBatteryStatus,
String rtcBatteryStatusWorst,
String voltagesStatus,
String voltagesStatusWorst,
String operationalStatus
// getters and setters
}
and a method in your service class returning directly its type
public interface HealthService {
DeviceHealth checkDeviceHealth(int id);
}
public class DefaultHealthService implements HealthService {
public DeviceHealth checkDeviceHealth(int id) {}
}
The framework will serialize and deserialize this object automatically for you.
2) If you are communicating with other systems
Well, in this case your gona have to handle the serialization and deserialization process your own. You can use for that JAXB, which has a reference implementation built-in JDK 1.6 and 1.7. This post gives you an idea on how to do this.