I am having a response class which looks like :
Class Response{
private String key;
private int value;
}
and I am expecting two response objects from two different data sources:
Response response1 = getResponsefromDataSource1();
Response response2 = getResponsefromDataSource2();
I am trying to validate the differences between these objects and build a difference object like this:
Class difference{
private String key;
private int valueFromResponse1;
private int valueFromResponse2;
private int difference;
}
Now I amde my research on using Java refelections to loop through the fields of an object and I am trying to build a 'difference' object from the field. My code looks like this:
Field[] fields = response1 .getClass().getDeclaredFields();
Arrays.stream(fields).forEach(field ->{
try {
field.setAccessible(true);
//need code here
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
is there a way for me to build the difference object from this code? Is there a better way to compare and build a difference object like I have mentioned?
Comapre two obejccts andwrite the differences onto another object, with reflections
Related
i try to use some web api, so i do this
public static void main(String[] args) {
// Create Jersey client
Client client = Client.create();
// GET request to findBook resource with a query parameter
String getSoccersSeasonsUrl = "http://api.football-data.org/v1/soccerseasons";
WebResource webResourceGet = client.resource(getSoccersSeasonsUrl);
webResourceGet.header("X-Auth-Token", myToken);
ClientResponse response = webResourceGet.get(ClientResponse.class);
String output = response.getEntity(String.class);
System.out.println(output);
}
output
[{"_links":{"self":{"href":"http://api.football-data.org/v1/soccerseasons/394"},"teams":{"href":"http://api.football-data.org/v1/soccerseasons/394/teams"},"fixtures":{"href":"http://api.football-data.org/v1/soccerseasons/394/fixtures"},
"leagueTable":{"href":"http://api.football-data.org/v1/soccerseasons/394/leagueTable"}},
"id":394,
"caption":"1. Bundesliga 2015/16",
"league":"BL1",
"year":"2015",
"currentMatchday":24,
"numberOfMatchdays":34,
"numberOfTeams":18,
"numberOfGames":306,
"lastUpdated":"2016-03-01T20:50:44Z ยป}
how can i fill from this output directly in a java ArrayList of object like:
public class SoccerSeason {
public SoccerSeason() {
}
private long id;
private String caption;
private String league;
private String year;
private long currentMatchday;
private long numberOfMatchdays;
private long numberOfTeams;
private long numberOfGames;
private String lastUpdated;
}
when i try to get directly SoccerSeason output = response.getEntity(SoccerSeason.class); i have a classic com.sun.jersey.api.client.ClientHandlerException
what's missing in my code please? do you have any idea how to do this simply?
What you want is Google's GSON. It can be found with a quick google search, and it has a ton of easy to read documentation.
Add GSON to your projects dependencies/source code, add getters and setters for all of your class members to the class you've created and it should work beautifully.
It is used like this:
Gson gson = new Gson();
SoccerSeason newSoccerSeason = gson.fromJson(webApiResponse, SoccerSeason.class);
String lastUpdated = newSoccerSeason.getLastUpdated();
Where webApiResponse is a String representation of the JSON received as your web API's response. You can also define a class SoccerSeasonList which looks like this:
public class SoccerSeasonList {
ArrayList<SoccerSeason> seasonList;
// getters/setters
}
Of course, your incoming JSON would have to have an object called seasonList containing all of your SoccerSeason objects to match up with this definition.
But then, you could grab your list like so:
SoccerSeasonList seasonList = gson.fromJson(webApiResponse, SoccerSeasonList.class);
ArrayList<SoccerSeason> seasonArr = seasonList.getSeasonList();
And perform operations like so:
for(SoccerSeason ss : seasonArr)
System.out.println(ss.getNumberOfMatchdays());
To recap: You simply match up your JSON object names and literals to their equivalent java types in a class, and call fromJSON on a String containing the JSON received from your web API that you'd like to parse, passing in the class you want the object parsed to.
I am trying to post a form to a Restlet ServerResource and read it into an object using Gson Restlet Extension.
There's no documentation on how to use it and nothing on StackOverflow.
What is the correct way of using gson restlet extension?
Following is what I have tried so far:
public class CustomerSegment {
private int visitsMin;
private int visitsMax;
// Getters, Setters and constructors
}
public class CampaignsResource extends ServerResource {
#Post
public Representation createCampaign(Representation entity) {
Form form = new Form(entity);
// Using form is the usual way, which works fine
// form: [[visitsMin=3], [visitsMax=6]]
CustomerSegment segment = null;
// Following hasn't worked
GsonConverter converter = new GsonConverter();
try {
segment = converter.toObject(entity, CustomerSegment.class, this);
//segment = null
} catch (IOException e1) {
e1.printStackTrace();
}
GsonRepresentation<CustomerSegment> gson
= new GsonRepresentation<CustomerSegment>(entity, CustomerSegment.class);
try {
segment = gson.getObject();
//NullPointerException
} catch (IOException e) {
e.printStackTrace();
}
return new EmptyRepresentation();
}
}
Form data that is being posted:
In fact, you can leverage the built-in converter support of Restlet without explicitly use the gson converter.
In fact, when you put the GSON extension within the classpath, the converter it contains is automatically registered within the Restlet engine itself. To check that you can simply use these lines when starting your application:
List<ConverterHelper> converters
= Engine.getInstance().getRegisteredConverters();
for (ConverterHelper converterHelper : converters) {
System.out.println("- " + converterHelper);
}
/* This will print this in your case:
- org.restlet.ext.gson.GsonConverter#2085ce5a
- org.restlet.engine.converter.DefaultConverter#30ae8764
- org.restlet.engine.converter.StatusInfoHtmlConverter#123acf34
*/
Then you can rely on beans within signatures of methods in your server resources instead of class Representation, as described below:
public class MyServerResource extends ServerResource {
#Post
public SomeOutputBean handleBean(SomeInputBean input) {
(...)
SomeOutputBean bean = new SomeOutputBean();
bean.setId(10);
bean.setName("some name");
return bean;
}
}
This works in both sides:
Deserialization of the request content into a bean that is provided as parameter of the handling method in the server resource.
Serialization into the response content of the returned bean.
You don't have anything more to do here.
For the client side, you can leverage the same mechanism. It's based on the annotated interfaces. For this, you need to create an interface defining what can be called on the resource. For our previous sample, it would be something like that:
public interface MyResource {
#Post
SomeOutputBean handleBean(SomeInputBean input);
}
Then you can use it with a client resource, as described below:
String url = "http://localhost:8182/test";
ClientResource cr = new ClientResource(url);
MyResource resource = cr.wrap(MyResource.class);
SomeInputBean input = new SomeInputBean();
SomeOutputBean output = resource.handleBean(input);
So in your case, I would refactor your code as described below:
public class CampaignsResource extends ServerResource {
private String getUri() {
Reference resourceRef = getRequest().getResourceRef();
return resourceRef.toString();
}
#Post
public void createCampaign(CustomerSegment segment) {
// Handle segment
(...)
// You can return something if the client expects
// to have something returned
// For creation on POST method, returning a 204 status
// code with a Location header is enough...
getResponse().setLocationRef(getUri() + addedSegmentId);
}
}
You can leverage for example the content type application/json to send data as JSON:
{
visitsMin: 2,
visitsMax: 11
}
If you want to use Gson, you should use this content type instead of the urlencoded one since the tool targets JSON conversion:
Gson is a Java library that can be used to convert Java Objects into
their JSON representation. It can also be used to convert a JSON string
to an equivalent Java object. Gson can work with arbitrary Java objects
including pre-existing objects that you do not have source-code of.
Hope it helps you,
Thierry
this is my situation:
I have a method which has a String as parameter. This method has to receive an object from a class called Urls. The object it has to recieve, has the same name as the value of the String. Here is my code:
private Object getObject(String objectName){
try
{
Field field = Urls.class.getField(objectName);
}
catch (NoSuchFieldException e)
{}
catch (IllegalAccessException e)
{}
}
And here is my Urls class:
public class Urls{
public static final String[] ASTUN = new String[]{
"http://www.astun.com/camara/truchas.jpg",
"https://www.todonieve.com/photowebcam.asp?fotografia=astun/astun.jpg",
"http://www.astun.com/camara/caba%C3%B1a%20sarrios.jpg",
"http://www.astun.com/camara/sector%20sarrios.jpg",
"http://www.astun.com/camara/sector%20raca%20prad.jpg",
"http://www.astun.com/camara/sector%20aguila%20cr.jpg",
"http://www.astun.com/camara/sector%20truchas.jpg",
"http://www.astun.com/camara/sector%20llanos%20.jpg",
"http://www.astun.com/camara/llegada.jpg",
"http://www.astun.com/camara/terraza.jpg",
"http://www.astun.com/camara/panoramica.jpg",
"http://www.astun.com/camara/snow.jpg"
};
private static final String[] CANDANCHU = new String[]{
"https://www.todonieve.com/photowebcam.asp?fotografia=candanchu/candanchu.jpg",
"https://www.todonieve.com/photowebcam.asp?fotografia=CandanchuNew/CandanchuNew.jpg",
"https://www.todonieve.com/photowebcam.asp?fotografia=candanchu_rinconada/candanchu_rinco.jpg",
"https://www.todonieve.com/photowebcam.asp?fotografia=candanchu_tobazo/candanchu_tobazo.jpg"
};
}
So, that way I have a Field object, but how can I get the String[] of that field? I have read about the get(Object object) method of Field class but it seems that i doesnt do what I want to do...
EDIT: I WANT TO GET ASTUN OR CANDACHU STRING ARRAYS
Avoid reflection whenever possible. It often does more harm than good.
Put them into a map:
public class Urls {
//put your arrays here
private static final Map<String,String[]> urlsLists = new HashMap<>();
static {
urlLists.put("ASTUN", ASTUN);
urlLists.put("CANDANCHU", CANDANCHU);
}
public static String[] getUrlList(String name) {
return urlLists.get(name);
}
}
And then call it like this:
private Object getObject(String objectName){
return Urls.getUrlList(objectName);
}
Update
You loose a lot of nice stuff Java help you with, including type-safety, encapsulation and compile-time checks. Because of this it is a lot more error prone. There is a much increased risk of run-time errors and you need a bunch of extra code to handle this. Your brief example already have two catch clauses. Trust me - that will just get worse.
You can even improve type-safety more by creating an Enum to define url-types. Then you will get compile time checks that you have spelled the name right and even auto-completion all through-out your code. :)
public class Urls {
public enum UrlTypes {ASTUN; CANDANCHU;}
// ..
private static final Map<UrlTypes,String[]> urlsLists = new HashMap<>();
static {
urlLists.put(UrlTypes.ASTUN, ASTUN);
urlLists.put(UrlTypes.CANDANCHU, CANDANCHU);
}
..
public static String[] getUrlList(UrlTypes name) {
return urlLists.get(name);
}
}
Every error you can catch at compile-time instead of at run-time can save you between half an hour or half a week of work, when things get complex.
You will need something like this:
private Object getObject(String objectName){
try
{
Field field = Urls.class.getField(objectName);
Object o = field.get(null); // null works as well.
return o;
}
catch (NoSuchFieldException e)
{ e.printStackTrace(); }
catch (IllegalAccessException e)
{ e.printStackTrace(); }
}
private String[] getStringArray(String arrayName)
{
return (String[]) getObject(arrayName);
}
Usage:
Object o = getObject("ASTUN");
// or:
String[] arr = getStringArray("ASTUN");
getField will return the (reflexive) representation of the field concept in the Urls class. You then need to bind it with an actual object of that class to have access to the contents of the field in that object.
Field field = Urls.class.getFiled(objectName);
String[] values = (String[]) field.get(o);
where o is a variable of type Urls.
Note the cast to String[] as Field.get() will return an Object as it does not know the actual type. You should make sure that the type is indeed correct by using the Field.getType() method and compare that to Urls.class.
Since objects dont have names, you will need to create ypur own class, put the field variable in there, then use that instead of Object. Or use a Map for better key/value logging.
My basic question: is there anything built that already does this automatically (doesn't have to be part of a popular library/package)? The main things I'm working with are Spring (MVC) and Jackson2.
I understand there are a few manual ways to do this:
Create a method in each class that serializes its specific properties into property=value& form (kind of stinks because it's a bunch of logic duplication, I feel).
Create a function that accepts an object, and uses reflection to dynamically read all the properties (I guess the getters), and build the string by getting each. I'm assuming this is how Jackson works for serialization/deserialization in general, but I really don't know.
Use some feature of Jackson to customly serialize the object. I've researched custom serializers, but it seems they are specific to a class (so I'd have to create one for each Class I'm trying to serialize), while I was hoping for a generic way. I'm just having trouble understanding how to apply one universally to objects. A few of the links:
http://techtraits.com/Programming/2011/11/20/using-custom-serializers-with-jackson/
http://wiki.fasterxml.com/JacksonHowToCustomSerializers
Use ObjectMapper.convertValue(object, HashMap.class);, iterate over the HashMap's key/value pairs, and build the string (which is what I'm using now, but I feel the conversions are excessive?).
I'm guessing there's others I'm not thinking of.
The main post I've looked into is Java: Getting the properties of a class to construct a string representation
My point is that I have several classes that I want to be able to serialize without having to specify something specific for each. That's why I'm thinking a function using reflection (#2 above) is the only way to handle this (if I have to do it manually).
If it helps, an example of what I mean is with, say, these two classes:
public class C1 {
private String C1prop1;
private String C1prop2;
private String C1prop3;
// Getters and setters for the 3 properties
}
public class C2 {
private String C2prop1;
private String C2prop2;
private String C2prop3;
// Getters and setters for the 3 properties
}
(no, the properties names and conventions are not what my actual app is using, it's just an example)
The results of serializing would be C1prop1=value&C1prop2=value&C1prop3=value and C2prop1=value&C2prop2=value&C2prop3=value, but there's only one place that defines how the serialization happens (already defined somewhere, or created manually by me).
So my idea is that I will have to end up using a form of the following (taken from the post I linked above):
public String toString() {
StringBuilder sb = new StringBuilder();
try {
Class c = Class.forName(this.getClass().getName());
Method m[] = c.getDeclaredMethods();
Object oo;
for (int i = 0; i < m.length; i++)
if (m[i].getName().startsWith("get")) {
oo = m[i].invoke(this, null);
sb.append(m[i].getName().substring(3) + ":"
+ String.valueOf(oo) + "\n");
}
} catch (Throwable e) {
System.err.println(e);
}
return sb.toString();
}
And modify it to accept an object, and change the format of the items appended to the StringBuilder. That works for me, I don't need help modifying this now.
So again, my main question is if there's something that already handles this (potentially simple) serialization instead of me having to (quickly) modify the function above, even if I have to specify how to deal with each property and value and how to combine each?
If it helps, the background of this is that I'm using a RestTemplate (Spring) to make a GET request to a different server, and I want to pass a specific object's properties/values in the URL. I understand I can use something like:
restTemplate.getForObject("URL?C1prop1={C1Prop1}&...", String.class, C1Object);
I believe the properties will be automatically mapped. But like I said, I don't want to have to make a different URL template and method for each object type. I'm hoping to have something like the following:
public String getRequest(String url, Object obj) {
String serializedUri = SERIALIZE_URI(obj);
String response = restTemplate.getForObject("URL?" + serializedUri, String.class);
return response;
}
where SERIALIZE_URI is where I'd handle it. And I could call it like getRequest("whatever", C1Object); and getRequest("whateverElse", C2Object);.
I think, solution number 4 is OK. It is simple to understand and clear.
I propose similar solution in which we can use #JsonAnySetter annotation. Please, see below example:
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonProgram {
public static void main(String[] args) throws Exception {
C1 c1 = new C1();
c1.setProp1("a");
c1.setProp3("c");
User user = new User();
user.setName("Tom");
user.setSurname("Irg");
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.convertValue(c1, UriFormat.class));
System.out.println(mapper.convertValue(user, UriFormat.class));
}
}
class UriFormat {
private StringBuilder builder = new StringBuilder();
#JsonAnySetter
public void addToUri(String name, Object property) {
if (builder.length() > 0) {
builder.append("&");
}
builder.append(name).append("=").append(property);
}
#Override
public String toString() {
return builder.toString();
}
}
Above program prints:
prop1=a&prop2=null&prop3=c
name=Tom&surname=Irg
And your getRequest method could look like this:
public String getRequest(String url, Object obj) {
String serializedUri = mapper.convertValue(obj, UriFormat.class).toString();
String response = restTemplate.getForObject(url + "?" + serializedUri, String.class);
return response;
}
Lets we have c1.
c1.setC1prop1("C1prop1");
c1.setC1prop2("C1prop2");
c1.setC1prop3("C1prop3");
Converts c1 into URI
UriComponentsBuilder.fromHttpUrl("http://test.com")
.queryParams(new ObjectMapper().convertValue(c1, LinkedMultiValueMap.class))
.build()
.toUri());
After we will have
http://test.com?c1prop1=C1prop1&c1prop2=C1prop2&c1prop3=C1prop3
Is there a way to Parse/Unmarshall query strings which passing arrays as parameters in Java into Map or custom class?
URL example:
localhost:8080/app/ws/categories?take=10&skip=10&page=2&pageSize=10&filter[logic]=and&filter[filters][0][field]=company_id&filter[filters][0][operator]=eq&filter[filters][0][value]=1513
I need to parse filter parameter in something like this:
public class Filter {
private String logic;
private List<Filters> filters;
public class Filters {
private String field;
private String operator;
private String value;
}
}
One more point - I'm using Jersey here, maybe it has possibility to Parse/Unmarshall #QueryParam using Jersey's tools?
Anyway any other Java solutions will be OK too.
I would suggest 2 things :
Either you want to perform a GET, then to keep a RESTful approach, I would have an Url like :
localhost:8080/app/ws/categories?take/10/skip/10/page/2/pageSize/10/filter/logic/and/ ...etc
Or POST is acceptable, and I would send JSON payload
We can do it utilizing #BeanParam from JAXRS 2.0 spec
public PageableResponse<PatientBundleType> getPatientBundles(#BeanParam final PageableBeanParam paging)
{
...
}
public class PageableBeanParam
{
public PageableBeanParam(#Context final UriInfo uriInfo)
{
for (Entry<String, List<String>> param : params.entrySet())
{
String key = param.getKey();
String value = param.getValue().iterator().next();
if ("pageSize".equals(key))
{
setPageSize(Integer.valueOf(value));
}
...
}
}
}