Web service response is MessageElement? - java

I am trying to figure out how to use this service, which should print out holidays in US: http://www.holidaywebservice.com/Holidays/HolidayService.asmx?WSDL
So, I generated Java classes for it, and tried to call its method, which should return list of available countries:
holidayServiceLocator.getHolidayServiceSoap().getCountriesAvailable().get_any()
getAny() method returns org.apache.axis.message.MessageElement[] type of object, and this is where I am lost.
As I can understand, MessageElement is used in order to store XML, am I correct? In that case, how should I handle it in order to get correct result (list of supported countries for this service)?

You can either use MessageElement.getElementsByTagName(String name) if you know the tag names in the response or you can use MessageElement.getChildElements() to iterate through all of them one by one.

Related

Pass list of objects to GET rest service

I would like to pass a list of objects to a java rest service. For example, list of cycles.
class Cycle {
private String id;
private LocalDate date;
}
#GetMapping("results")
public Result results(List<Cycle> cycles)
Or have a CyclesWrapper class that contains the list. Instead of passing a List cycleDates and a List cycleIds.
How would I pass the parameters to the rest service using say POSTMAN or curl?
So, for passing in a List<String> says cycleIds, the request would be:
http://localhost:8080/application/results?cycleIds=xx,yy
For passing in a Cycle says cycle, the request would be:
http://localhost:8080/application/results?date=2020-10-17&id=xx
Thanks
As it currently stands, your endpoint would interpret cycles as a query parameter, meaning that it would expect the following kind of request:
GET /results?cycles=...
With a list of complex objects, this is not the standard approach. You could possibly pass the objects as /results?cycle1Id=abc&cycle1Date=22-10&cycle2Id=def&cycle2Date=10-10&..., but this would be extremely cumbersome, error-prone, and would require custom mapping on your end to make it work. Additionally, as far as I am aware, there is no standard for sending query array parameters.
Note also, in case you might have misconstrued: you cannot send a request body on a GET request - while the standard does not explicitly disallow this, almost every server's handling of GET does not accept (or just flatly ignores) a request body.
Instead, what you could do, is either:
Change the endpoint to a POST endpoint, passing the list of cycles (i.e. filters) as standard #RequestBody JSON. This would look as follows:
#PostMapping("results")
public Result results(#RequestBody List<Cycle> cycles)
Now your request would expect:
POST /results
{
[
{"abc", "22-10"},
{"def", "10-10"}
]
}
Since POST is allowed to pretty much do anything, it could also return a filtered response on this endpoint. This would however, not be very RESTful.
Change your GET to accept two lists of of simple (i.e. non-nested) objects, e.g. String and LocalDate.
#GetMapping("results")
public Result results(#RequestParam List<String> ids, #RequestParam List<LocalDate> dates)
Which would then expect a request as follows:
GET /results?ids=abc,def&dates=22-10,10-10
as a comma-separated list. This is more in tune with RESTful endpoints, although it's also kind of cumbersome.
In the end, it seems like your endpoint is trying to do two things at once: filter on id and date. Since I am not sure what kind of logical work represents a cycle, perhaps these should be split up into two different endpoints, e.g.:
===>
GET /results?dateFrom=22-10&dateUntil=23-10
<===
[abc, def]
==>
GET /results/abc?dateFrom=22-10&dateUntil=23-10
<==
abc detailed view
Where the /abc represents a singular object. Whether this represents a result or a cycle in your specific case, I cannot say. You'd have to evaluate that for yourself.

Sorting rest get request results by field passed as a parameter

I am currently working on a Rest API, in a get method which suppose to return an Array of objects in json format I now have the requirement to sort the result by a field passed as a parameter to the method. Consider for example the object to be
public class ExampleType {
int firstField ;
String secondField ;
}
Now according to the requirements the Rest API user should be able to pass as a parameter among other things either "firstField" or "secondField" and I should be sorting the array containing the result objects using this field.
Apparently my model is not so simplistic as the example, I do have more than 15 fields which could potentially be the one that I need to sort by, so an else if statement is not a choice at this point. My question is does anybody had a similar requirement for a rest api and if so how did you tackle it ? Or any recommendation on what could potentially by an elegant solution to my problem would be greatly appreciated.
You should create a Comparator and then use this to sort your data.
The comparators could be stored in a static map to avoid a switch/case if/else:
map.put("fieldName", Comparator.comparing(ExampleType::getFirstField));
You can combine two or more comparators using the thenComparing method.
The only other option is to create the appropriate comparators using reflection.
Note: requirements of API consumers often are not requirements that should be implemented in the API itself. You may also consider that sorting output is in fact a display problem and not something that an API needs to be concerned with.
It depends on the situation though, if data needs to be paginated then you may have no option other than to sort at the API level.

4 Key Value HashMap? Array? Best Approach?

I've got loads of the following to implement.
validateParameter(field_name, field_type, field_validationMessage, visibleBoolean);
Instead of having 50-60 of these in a row, is there some form of nested hashmap/4d array I can use to build it up and loop through them?
Whats the best approach for doing something like that?
Thanks!
EDIT: Was 4 items.
What you could do is create a new Class that holds three values. (The type, the boolean, and name, or the fourth value (you didn't list it)). Then, when creating the HashMap, all you have to do is call the method to get your three values. It may seem like more work, but all you would have to do is create a simple loop to go through all of the values you need. Since I don't know exactly what it is that you're trying to do, all I can do is provide an example of what I'm trying to do. Hope it applies to your problem.
Anyways, creating the Class to hold the three(or four) values you need.
For example,
Class Fields{
String field_name;
Integer field_type;
Boolean validationMessageVisible;
Fields(String name, Integer type, Boolean mv) {
// this.field_name = name;
this.field_type = type;
this.validationMessageVisible = mv;
}
Then put them in a HashMap somewhat like this:
HashMap map = new HashMap<String, Triple>();
map.put(LOCAL STRING FOR NAME OF FIELD, new Field(new Integer(YOUR INTEGER),new Boolean(YOUR BOOLEAN)));
NOTE: This is only going to work as long as these three or four values can all be stored together. For example if you need all of the values to be stored separately for whatever reason it may be, then this won't work. Only if they can be grouped together without it affecting the function of the program, that this will work.
This was a quick brainstorm. Not sure if it will work, but think along these lines and I believe it should work out for you.
You may have to make a few edits, but this should get you in the right direction
P.S. Sorry for it being so wordy, just tried to get as many details out as possible.
The other answer is close but you don't need a key in this case.
Just define a class to contain your three fields. Create a List or array of that class. Loop over the list or array calling the method for each combination.
The approach I'd use is to create a POJO (or some POJOs) to store the values as attributes and validate attribute by attribute.
Since many times you're going to have the same validation per attribute type (e.g. dates and numbers can be validated by range, strings can be validated to ensure they´re not null or empty, etc), you could just iterate on these attributes using reflection (or even better, using annotations).
If you need to validate on the POJO level, you can still reuse these attribute-level validators via composition, while you add more specific validations are you´re going up in the abstraction level (going up means basic attributes -> pojos -> pojos that contain other pojos -> etc).
Passing several basic types as parameters of the same method is not good because the parameters themselves don't tell much and you can easily exchange two parameters of the same type by accident in the method call.

Can I use varargs in a retrofit method declaration?

I've got an API endpoint that is defined as:
GET https://api-server.com/something/{id_or_ids}
where ids can be a single object id or a comma separated list of ids.
e.g.
https://api-server.com/something/abcd1234
https://api-server.com/something/abcd1234,abcd4567,gdht64332
if a single id is given (and a matching object is found) I get back a json object:
{ "blah" : "blah" }
If multiple ids are given, I get the response in a json array:
[{"blah1":"bleh"}, {"blah2":"meh"}, {"blah3":"blah"}]
I'm currently thinking that I should implement this as two methods (can it be done in one?):
one that takes a single id and returns a single object:
#GET("/something/{id}")
void getObject (#Path("id") String objectId, Callback<MyObject> callback)
and
one that takes multiple ids and returns an array of objects.
#GET("/something/{ids}")
void getObject (Callback<MyObject[]> callback,#Path("ids") String ... objectIds)
Is there a way to feed the 2nd method varargs and concatenate them in the id field?
Thanks
Retrofit can't know how you want to join the strings in the path. While commas seem obvious, there's no reason why someone might want pipes (|) or colons (:) or whatever.
Because of this fact, we don't do anything and rely on you to choose.
There's two solutions to this:
Use String as the argument type and join at the call site. For example:
foo.getObject(Joiner.on(',').join(things));
Use a custom object whose toString() method deals with returning the correct format for one or many objects.

How can I convert from java ArrayList object to real value

I'm trying to get a value from the databae.
My Database query:
String GroupID1="select idCompanies from companies where Company_Name='ACME';";
here I'm calling to a javabeans which give back an ArrayLIst with one element
ArrayList<?> IdGroup1=oper.getList(GroupID1);
then, I print the result:
System.out.println(IdGroup1);
The query works fine, however I'm getting as a result:
[javabeans.ListOneElement#609f6e68]
Instead of the real value. How can I convert the java object to the real value?
you are printing the ArrayList object IdGroup1,You need to iterate to get the alues
This code will retrieve the first (and only) item from the list:
System.out.println(IdGroup1.get(0).toString());
Adding the following will prevent a nullPointerException:
if (!IdGroup1.isEmpty())
System.out.println(IdGroup1.get(0).toString());
-Added .toString() to get the value of the object
Consider what type of Object oper.getList(GroupID1) will return.
You need to accommodate for whatever object that is and then convert it to String.
You need to:
Unpackage your list (that is a list contains, and is expected by java to possibly contain multiple objects, so it doesn't automatically 'unpack' it for you if you have a list of 1 object)
Extract your string. Here java might cleverly convert a number (int, float, etc. ) to a string for you.
For part two, look at what you expect the object to be by finding the JavaDocs for whatever package is handling your database queries. Then see how to extract your string.
It might be as simple as System.out.println(IdGroup1.get(0).toString());
Where get(0) unpackages the object from the list, and toString() extracts the string.
If you still get back javabeans.ListOneElement#41ccdc4d try other methods to extract your string....toValue() perhaps? It depends on the packages you're using.

Categories

Resources