I am trying to build a Jenkins Post build plugin where I have to process JSON file (contains test results) and show it in tabular format in Jenkins once build is executed.
Following are the steps done till now:
Created Jenkins plugin
Able to retrieve JSON file content and read it as Google gson JSONElement.
Built BuildAction (extends Action) to show the results.
In index.jelly (view for BuildAction) corresponding to BuildAction, trying to show each record in JSON file, as a row.
JSON File sample:
{
"records": [{
"objectProps": {
"OTYPE": "TEST",
"NAME": "testMethodError",
}
},
{
"objectProps": {
"OTYPE": "TEST",
"NAME": "testMethodFail",
}
}]
}
BuildAction class:
public class BuildAction implements Action {
private JsonElement results;
private Run<?, ?> build;
TaskListener listener;
// this value referred as `it.results` in `index.jelly`
public JsonArray getResults(){
return results.getAsJsonObject().get("records").getAsJsonArray();
}
}
current index.jelly for above BuildAction class
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:l="/lib/layout">
<l:layout>
<st:include it="${it.build}" page="sidepanel.jelly"/>
<l:main-panel>
<table> Test - Wise Results
<j:forEach items="${it.results}" var="i">
<tr><td>Test case name: ${i}</td></tr>
</j:forEach>
</table>
</l:main-panel>
</l:layout>
</j:jelly>
Actual behaviour:
As of now, ${results} value is of JSONArray type. forEach in jelly, I am able iterate over and get the record using var i (syntax ${i}). i refers to each record in records JSONArray. Now, I want to access objectProps.NAME field using i, I don't know the syntax in Jelly to achieve the same.
Expected behaviour:
I wan to iterate through records array in JSON file and each child/jsonObject as one table row (and its values as corresponding columns).
something similar to this (to access NAME value):
<j:forEach items="${it.results}" var="i">
<tr><td>Test case name: ${i}."objectProps"."NAME"</td></tr>
</j:forEach>
Need help in building the table out of a JSON using Jelly. Any other way of achieving the same also welcome (please post code samples when suggesting the same).
Note: Groovy related answer also welcome as Jenkins support both Jelly and Groovy for View.
I am interested in solving you problem, but might not have a 100% certain answer as I can't test locally.
Have you tried to use ${i.objectProps.NAME}or ${i."objectProps"."NAME"} instead of ${i}."objectProps"."NAME"in your example?
You could also see if g:evaluate is available, as jelly might not evaluate your variable without explicitly telling it to do so. You can find some documentation on g:evaluate here.
Related
Sorry for this stupid question, but I cannot understand how to extract tag-specific information from Micrometer.
We are using Spring Boot 2.7.6. When using multiple counters with tags like this:
private Map<String, Counter> errorCounters = new HashMap<>();
...
tenantList.forEach(tenant ->
{
final Counter counter = Counter.builder("company.publishing_errors")
.description("Total number of failed tries to publish an object.")
.tag("tenant", tenant)
.register(registry);
errorCounters.put(tenant, counter);
});
...
errorCounters.get(tenant).increment();
which results in one counter per tenant. In the debugger I can clearly see that they are counted independently.
Under http://127.0.0.1:8080/actuator/metrics/company.publishing_errors I see the following JSON:
{
"name":"company.publishing_errors",
"description":"Total number of failed tries to publish an object.",
"baseUnit":null,
"measurements":[{
"statistic":"COUNT",
"value":6.0
}],
"availableTags":[{
"tag":"tenant",
"values":[
"tenant1",
"tenant2"
]}
]}
I tried multiple variations to extract the tag specific data, but failed. All tutorials and guides I found either stop at this point, or just import the data into e.g. Grafana which extracts the data itself. Do I have to specify the version, e.g. Micrometer-Prometheus? We are only using the Spring Boot standard, which includes the micrometer-core-library. Do I need to set commonTags?
Thanks to input from a colleague, I found the answer.
According to the Spring documentation, you can view tag specific data with tag=KEY:VALUE query parameters. So in my case the URL would be
http://127.0.0.1:8080/actuator/metrics/company.publishing_errors?tag=tenant:tenant1
I want to match json data based on scenario name. i.e using scenario name particular json node need to be selected. any can one help on how can i setup this approach. i am using Cucumber with Java.
Json will look like this.
{
"scenario1":
{
"coffeestore": "CCD",
"Area": "Hyderabad"
},
"scenario2":
{
"coffeestore": "starbucks",
"Area: "Banglore"
}
}
Feature will look like this.
Scenario: senario1
Given user enters coffeshop details
And user saved the coffeshop details
Scenario: senario2
Given user enters coffeshop details
And user saved the coffeshop details
I was trying to write a data model to send a JSON to the API and delete some fields
the JSON should contain the id of some words and it should look exactly like this :
{
"words":[3,4,5]
}
as I know and also as the https://jsonformatter.org/ said the data class should be something like the following piece of code:
data class words(var id: List<Int>)
but the problem is when I pass the data to it and toast it to see if it's a valid JSON request for the server the output will be this :
words(id=[1,2,4,5])
and it's not what it should be.
as I said I need this :
{
"words":[3,4,5]
}
I think the following should work.
data class AnyNameYouWant(val words: List<Int>)
I think the name of the data class really doesn't matter as it would finally represent the { } object syntax of json.
Looking in the comments, I think it's better to use some logging library like Timber. If you are using Retrofit then use can also use HttpLoggingInterceptor and set the level to Body that will print the body of the response in the logcat.
My mobile app has quite a lot of hard-coded data, that I want to share between the native Android and iOS versions of the app.
I don't want to create two settings files for each app: I would like to have a single place where the information is stored.
My first thought was using a JSON file embedded with my app and decode it at runtime.
Instead my goal here is to deserialize the app's data at compile time, in order to:
track potential errors within the JSON file or the decoding code before shipping the app: the build will fail instead
avoid being slowed down by some deserialization at startup time
avoid leaving unencrypted app data lying around as JSON files (.ipa/.apk are zip files where resources can be easily extracted), I'd rather have it obfuscated in code
I'm looking for a command line tool that I could add to my build scripts that given a JSON file infer a schema and thus classes AND instantiates an object with all the app settings.
For instance given the following settings.json file:
{
"gravity": 9.81,
"scientists": ["Kepler", "Einstein", "Newton"],
"planets": [
{
"name": "Mars",
"radius": 3390
},
{
"name": "Venus",
"radius": 6052
}
]
}
I would like to generate automatically a Settings.swift file that could look like:
struct Settings {
struct Planet {
var name: String
var radius: Int
}
var gravity: Double
var scientists: [String]
var planets: [Planet]
static func content() -> Settings {
return Settings(gravity: 9.81, scientists: ["Kepler", "Einstein", "Newton"], planets: [Planet(name: "Mars", radius: 3390), Planet(name: "Venus", radius: 6052)])
}
}
I could then include the generated file into my project and call Settings.content() once, keep it in a global variable and use it throughout my project.
I want to achieve the same with Android as well.
Tools like quicktype or json2swift do half the job and don't generate the object instantiation bit, that still needs to be done at runtime.
Any idea?
I have created an open source NodeJS mobile_app_data tool to achieve what I wanted.
A possible solution will be as follows:
Save the .json file in the project directory
In AppDelegate applicationDidFinishLauncing() read the above file into a Data object (Read JSON file with Swift 3)
Make your Settings class implement Decodable (your inner class Planet will need to implement Decodable as well)
Call JsonDecoder().decode() and provide the data you obtained in 2)
You can then save this value anywhere you want
I just noticed that you needed the generation to happed when Settings.content() is called. Follow the above steps just move step 2) into the content() function
First I know my title is bad as I didn't come up with better, I'm opened to suggestion.
I'm using retrofit to get data from an api of this kind : #GET("users/{userid}")
It works fine and I'm happy with it, the problem is when I call the same api with #POST("users/widget") with a list of ids. I have the following answer :
{
"long_hash_id": {
"_id": "long_hash_id"
.......
},
"long_hash_id": {
"_id": "long_hash_id",
.....
},
........
}
the "long_hash_id" is typicaly "525558cf8ecd651095af7954"
it correspond to the id of the user attached to it.
When I didn't use retrofit, I used Gson in stream mode to get each user one by one. But I don't know how to tell retrofit.
Hope I'm clear and
Thank you in advance.
----------- Solution :
I made my interface this way :
#FormUrlEncoded
#POST(AppConstants.ROUTE_USER_GROUP)
Call<Map<String,User>> getUsers( #Field("ids") List<String> param, #QueryMap Map<String,String> options);
and I simply gave my ArrayList of ids. Thank you very much
Gson is able to deal with JSON objects with variable keys like the one you posted. What you have to do, in this case, is to declare a Map<String, ModelClass>, where ModelClass is the content of the JSONObject you want to represent