Iterating all Play Framework routes in Test - java

Is there any way to Iterate all described services in routes file? URL and HTTP methods are needed.
I need this feature for running some integration test.
I am using Play for Java.

Not easily. I managed to hack my way through it a while ago(no scala know-how). I'll post that code maybe it can be of use.
public static List<String[]> parseRoutes() {
scala.Option<play.core.Router.Routes> option = Play.application().getWrappedApplication().routes();
if (option.isDefined()) {
play.core.Router.Routes routes = option.get();
scala.collection.Seq<scala.Tuple3<String, String, String>> doc = routes.documentation();
scala.collection.Iterator<scala.Tuple3<String, String, String>> it = doc.iterator();
List<String[]> listOfRoutes = new ArrayList<String[]>();
while(it.hasNext()) {
scala.Tuple3<String, String, String> tuple = it.next();
//tuple._1() is the method and tuple._2() the url... tuple._3() is the controller name
String[] route = {tuple._1(), tuple._2()};
listOfRoutes.add(route);
Logger.debug("route -> " + Arrays.toString(route));
}
return listOfRoutes;
}
return null;
}
Don't worry about the .iterator() showing a The method iterator() is ambiguous for the type Seq<Tuple3<String,String,String>>. It compiles just fine in play.

Related

How to automate function according to Array list size

I'm sorry this question header is not 100% correct. Because of that, I'll explain my scenario here.
I created a function to merge 4 data sets into one return format. Because that's the format front-end side needed. So this is working fine now.
public ReturnFormat makeThribleLineChart(List<NameCountModel> totalCount, List<NameCountModel>,p1Count, List<NameCountModel> p2Count, List<NameCountModel> average) {
ReturnFormat returnFormat = new ReturnFormat(null,null);
try {
String[] totalData = new String[totalCount.size()];
String[] p1Data = new String[p1Count.size()];
String[] p2Data = new String[p2Count.size()];
String[] averageData = new String[p2Count.size()];
String[] lableList = new String[totalCount.size()];
for (int x = 0; x < totalCount.size(); x++) {
totalData[x] = totalCount.get(x).getCount();
p1Data[x] = p1Count.get(x).getCount();
p2Data[x] = p2Count.get(x).getCount();
averageData[x] = average.get(x).getCount();
lableList[x] = totalCount.get(x).getName();
}
FormatHelper<String[]> totalFormatHelper= new FormatHelper<String[]>();
totalFormatHelper.setData(totalData);
totalFormatHelper.setType("line");
totalFormatHelper.setLabel("Uudet");
totalFormatHelper.setyAxisID("y-axis-1");
FormatHelper<String[]> p1FormatHelper= new FormatHelper<String[]>();
p1FormatHelper.setData(p1Data);
p1FormatHelper.setType("line");
p1FormatHelper.setLabel("P1 päivystykseen heti");
FormatHelper<String[]> p2FormatHelper= new FormatHelper<String[]>();
p2FormatHelper.setData(p2Data);
p2FormatHelper.setType("line");
p2FormatHelper.setLabel("P2 päivystykseen muttei yöllä");
FormatHelper<String[]> averageFormatHelper= new FormatHelper<String[]>();
averageFormatHelper.setData(averageData);
averageFormatHelper.setType("line");
averageFormatHelper.setLabel("Jonotusaika keskiarvo");
averageFormatHelper.setyAxisID("y-axis-2");
List<FormatHelper<String[]>> formatHelpObj = new ArrayList<FormatHelper<String[]>>();
formatHelpObj.add(totalFormatHelper);
formatHelpObj.add(p1FormatHelper);
formatHelpObj.add(p2FormatHelper);
formatHelpObj.add(averageFormatHelper);
returnFormat.setData(formatHelpObj);
returnFormat.setLabels(lableList);
returnFormat.setMessage(Messages.Success);
returnFormat.setStatus(ReturnFormat.Status.SUCCESS);
} catch (Exception e) {
returnFormat.setData(null);
returnFormat.setMessage(Messages.InternalServerError);
returnFormat.setStatus(ReturnFormat.Status.ERROR);
}
return returnFormat;
}
so, as you can see here, all the formatting is hardcoded. So my question is how to automate this code for list count. Let's assume next time I have to create chart formatting for five datasets. So I have to create another function to it. That's the thing I want to reduce. So I hope you can understand my question.
Thank you.
You're trying to solve the more general problem of composing a result object (in this case ReturnFormat) based on dynamic information. In addition, there's some metadata being setup along with each dataset - the type, label, etc. In the example that you've posted, you've hardcoded the relationship between a dataset and this metadata, but you'd need some way to establish this relationship for data dynamically if you have a variable number of parameters here.
Therefore, you have a couple of options:
Make makeThribleLineChart a varargs method to accept a variable number of parameters representing your data. Now you have the problem of associating metadata with your parameters - best option is probably to wrap the data and metadata together in some new object that is provided as each param of makeThribleLineChart.
So you'll end up with a signature that looks a bit like ReturnFormat makeThribleLineChart(DataMetadataWrapper... allDatasets), where DataMetadataWrapper contains everything required to build one FormatHelper instance.
Use a builder pattern, similar to the collection builders in guava, for example something like so:
class ThribbleLineChartBuilder {
List<FormatHelper<String[]>> formatHelpObj = new ArrayList<>();
ThribbleLineChartBuilder addDataSet(String describeType, String label, String yAxisId, List<NameCountModel> data) {
String[] dataArray = ... ; // build your array of data
FormatHelper<String[]> formatHelper = new FormatHelper<String[]>();
formatHelper.setData(dataArray);
formatHelper.setType(describeType);
... // set any other parameters that the FormatHelper requires here
formatHelpObj.add(formatHelper);
return this;
}
ReturnFormat build() {
ReturnFormat returnFormat = new ReturnFormat(null, null);
returnFormat.setData(this.formatHelpObj);
... // setup any other fields you need in ReturnFormat
return returnFormat;
}
}
// usage:
new ThribbleLineChartBuilder()
.addDataSet("line", "Uudet", "y-axis-1", totalCount)
.addDataSet("line", "P1 päivystykseen heti", null, p1Count)
... // setup your other data sources
.build()

Mapping VCF file into POJO

I am trying to map .vcf to my DTO (Simple POJO) , here is what i have tried :
Code:
List<VCard> list = Ezvcard.parse(fr).all(); // fr is FileReader
SomeDto someDto = new SomeDto ();
List<SomeDto > someDtoList = new ArrayList<>();
for (Iterator<VCard> iterator = list.iterator(); iterator.hasNext();) {
VCard vCard = iterator.next();
c.setFirstName(vCard.getFormattedName().getValue());
c.setEmailAddress(vCard.getEmails().get(0).getValue());
c.setMobilePhone(vCard.getTelephoneNumbers().get(0).getText());
someDtoList .add(c);
}
return someDtoList ;
Is there a simplified way of handling this? Like in-built methods to take care if DTO has more properties, so we can avoid manual work?
I am using vCard JAR: https://github.com/mangstadt/ez-vcard
Maybe try this out https://github.com/mangstadt/ez-vcard it was originally a development by google and offers a lot of possibilities.
U may try to convert your vcards to json, to have more possibilities for further work.
String json = Ezvcard.writeJson(vcard).go();

Changing the format of list / array in URL [Retrofit 2]

As stated in the Retrofit documentation above the #Query annotation:
Passing a List or array will result in a query parameter for each
non-null item.
As of now my call looks something like this:
#GET("questions")
Call<List<QuestionHolder>> getQuestionsExcludingTheSpecified(
#Query("exclude_ids") long[] excludedQuestionIds
);
This works but results in fairly long URLs quite fast.
E.g. for excludedQuestionIds = new long[]{1L, 4L, 16L, 64L} the request URL already will be /questions?exclude_ids=1&exclude_ids=4&exclude_ids=16&exclude_ids=64.
Is there an easy way to exchange this behaviour resulting in arrays formatted as exclude_ids=[1,4,16,64] or something similar?
What came to my mind yet was, to:
use JsonArray as parameter, but then I need to convert every array / list before making the call
intercept every request and compress duplicated keys
override the built-in #Query decorator
Any ideas?
I decided to go with the Interceptor approach. I simply change any outgoing request that includes more than one value for a single query parameter.
public class QueryParameterCompressionInterceptor implements Interceptor {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
HttpUrl url = request.url();
for (String parameterName : url.queryParameterNames()) {
List<String> queryParameterValues = url.queryParameterValues(parameterName);
if (queryParameterValues.size() > 1) {
String formattedValues= "[" + TextUtils.join(",", queryParameterValues) + "]";
request = request.newBuilder()
.url(
url.newBuilder()
.removeAllQueryParameters(parameterName)
.addQueryParameter(parameterName, formattedValues)
.build()
).build();
}
}
return chain.proceed(request);
}
non android solution
TextUtils is part of the Android SDK, in case you're not developing for Android you might exchange TextUtils.join for a method like this:
public static String concatListOfStrings(String separator, Iterable<String> strings) {
StringBuilder sb = new StringBuilder();
for (String str : strings) {
sb.append(separator).append(str);
}
sb.delete(0, separator.length());
return sb.toString();
}
}
You may also have a look at this SO question for more solutions regarding the concatenation.

Get Data From Redis in batch RedisTemplate

I am using RedisTemplate in my spring boot application and I am able to read using singleKey.
String valueJson = (String) redisTemplate.opsForValue().get(setKey(someId));
I have now a List of "someId" like "List someIds" and I want to get the data of all Ids. Of course I can iterate on the list and hit redis with indivisual keys, but I dont want that, instead I want provide the whole list to get the response in one go.
Please help.
You need to use pipelining: https://redis.io/topics/pipelining
List<Object> results = redisTemplate.executePipelined(
new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
for(String id:someIds)
stringRedisConn.get(id);
return null;
}
});
Or in Java 8:
List<Object> results = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
StringRedisConnection stringRedisConn = (StringRedisConnection) connection;
someIds.forEach(id -> {
stringRedisConn.get(id);
});
return null;
});
The results List will contain all that you want.

Nodes returned from a RestCypherEngine execution produces just urls

When executing queries on a standalone Neo4J server using the RestCypherEngine, what is the best practice to retrieve a collection of nodes?
I have this code snippet running....
public DbService() {
gd = new RestGraphDatabase("http://neo4jbox:7474/db/data/");
engine = new RestCypherQueryEngine(gd.getRestAPI());
}
public String testData() {
try (Transaction tx = gd.beginTx()) {
QueryResult<Map<String, Object>> result;
result = engine.query(
"match (n:Person{username:'jomski2009'}) return n ",
null);
Iterator<Map<String, Object>> itr = result.iterator();
while (itr.hasNext()) {
Map<String, Object> item = itr.next();
log.info(item.get("n"));
}
tx.success();
return result.toString();
}
}
When I run the code, I get the following result...
services.DbService : http://neo4jbox:7474/db/data/node/177
which is a link to the node rather than the node itself. Now I know that if I return just a subset of the properties of the node in the same query that works well. What I'd like to know is how do I retrieve complete node object without necessarily specifying the properties in the query?
Thanks for your help guys.
It is just the to-string representation of a RestNode, it still has the properties. But not the relationships fetched those will be fetched on demand.
I would recommend to try to fetch primitive values over the wire with Cypher, works best as it minimizes the transferred data and you only get what you need.

Categories