I want to retrieve the TraceId of Zipkin, is there any method to get it ?
If service 2 is getting traceId from service 1, you can take the traceId from requestHeader in your java code. Otherwise sleuth generate a new traceId in service 2.
To get the trace Id In java
#Autowired
private Tracer tracer;
Just do
tracer.getCurrentSpan().traceIdString();
Hello you can also get the x-b3-traceid header information from the request, I created a Util class for that -> https://gist.github.com/walterwhites/067dd635986e564aafdb5ac559073b0f
public final class DebugUtils {
private static String PURPLE = "\033[0;35m"; // PURPLE
private static String RED = "\u001B[31m"; // RED
private static String RESET = "\u001B[0m";
public static class ZipkinDebug {
private static String url = "http://localhost:9411/zipkin/traces/";
public static void displayTraceUrl(HttpServletRequest request) {
String traceId = request.getHeader("x-b3-traceid");
System.out.println(PURPLE + "DebugUtils:ZipkinDebug -> " + url + traceId + RESET);
}
}
public static class RequestInfo {
public static void displayAllRequestHeaders(HttpServletRequest request) {
Enumeration<String> headerNames = request.getHeaderNames();
System.out.println(RED + "DebugUtils:RequestInfo -> " + RESET);
headerNames.asIterator().forEachRemaining(header -> {
System.out.println("Header Name:" + header + " " + "Header Value:" + request.getHeader(header));
});
}
public static void displayRequestHeader(HttpServletRequest request, String headerName) {
System.out.println(RED + "DebugUtils:RequestInfo -> Header Name:" + headerName + " " + "Header Value:" + request.getHeader(headerName) + RESET);
}
}
}
Then in your main class you just need to call
ZipkinDebug.displayTraceUrl(request);
Related
I am working on restassured and here is my 2 methods. I want to use the albumId returned from the AlbumList method in the other method
public void AlbumList() {
Response response1 = given().spec(url).queryParam("page", 0).queryParam("size", 100)
.queryParam("sortBy", "createdDate").queryParam("contentType", "album/photo")
.queryParam("sortOrder", "ASC")
.header("Content-type", "application/json")
.header("Accept", "application/json")
.header("X-Auth-Token", payload.userAuth())
.when().get("/album")
.then().assertThat().statusCode(200).extract().response();
Assert.assertEquals(response1.jsonPath().get("[4].label"), "TLOTR");
JsonPath js = new JsonPath(response1.asString());
int count = js.getInt("size()");
// Response check part
for (int i = 0; i < count; i++) {
assertEqual(js, i, "createdDate", AlbumAttributes.actual_createdDate());
assertEqual(js, i, "lastModifiedDate", AlbumAttributes.actual_modifiedDate());
assertEqual(js, i, "uuid", AlbumAttributes.actual_uuid());
if (js.get("[" + i + "].coverPhoto") != null) {
String d = response1.jsonPath().get("[" + i + "].coverPhoto.tempDownloadURL").toString();
Assert.assertTrue(d.matches(AlbumAttributes.actual_temp_url()));
System.out.println(js.get("[" + i + "].coverPhoto.tempDownloadURL").toString() + " is equalent to : " + AlbumAttributes.actual_temp_url());
}
if (js.get("[" + i + "].coverPhoto.metadata['Thumbnail-Large']") != null) {
String e = response1.jsonPath().get("[" + i + "].coverPhoto.metadata['Thumbnail-Large']").toString();
Assert.assertTrue(e.matches(AlbumAttributes.actual_metaData_url()));
System.out.println(js.get("[" + i + "].coverPhoto.metadata['Thumbnail-Large']").toString() + " is equalent to : " + AlbumAttributes.actual_metaData_url());
}
}
String albumId = response1.jsonPath().get("[0].uuid").toString();
String albumId2 = response1.jsonPath().get("[1].uuid").toString();
}
I know these are void and doesnt return anything but idk how to use it. Bye the these methods are in the same class. Thanks in advance
public void AlbumDetails() {
Response response = given().queryParam("page", 0).queryParam("size", 100)
.queryParam("sortBy", "createdDate").queryParam("sortOrder", "DESC")
.header("Content-type", "application/json")
.header("Accept", "application/json")
.header("X-Auth-Token", payload.userAuth())
.when().get("/album/" + albumId)
.then().assertThat().statusCode(200).extract().response();
// Response check part
Assert.assertEquals("[]", response.jsonPath().get("fileList").toString());
Assert.assertEquals("album/photo", response.jsonPath().get("contentType").toString());
Assert.assertEquals("false", response.jsonPath().get("readOnly").toString());
Assert.assertTrue(response.jsonPath().get("createdDate").toString().matches(AlbumAttributes.actual_createdDate()));
Assert.assertTrue(response.jsonPath().get("lastModifiedDate").toString().matches(AlbumAttributes.actual_modifiedDate()));
Assert.assertTrue(response.jsonPath().get("uuid").toString().matches(AlbumAttributes.actual_uuid()));
System.out.println("Album Details Response Test PASS");
long albumDetails_time = response.getTime();
System.out.println("\tAlbum Detail's Api response time is : " + albumDetails_time);
}
The easiest way is to change the return type of the AlbumList() method from void to String:
public String AlbumList() {
And in AlbumDetails() method we should change:
.when().get("/album/" + AlbumList())
Another option is to create instance variable albumId, not locally in AlbumList() method, and use it:
public class SomeClass {
public String albumId;
public void AlbumList() {
...
albumId = response1.jsonPath().get("[0].uuid").toString();
}
public void AlbumDetails() {
...
.when().get("/album/" + albumId)
...
}
}
P.S. Here are some more tips:
due to clean code more correct name describes what these methods do, e.g. getAlbumList() or storeAlbumList() and smth similar for another method;
for extracting jsonPath from response we can use: JsonPath js = given()....extract().jsonPath();
I found this code in Java 6.
String mensajeExcluido = ArqSpringContext.getPropiedad("MENSAJE.EXCLUIDO");
LOG.warn("ERROR: Servicio: " + mensajeExcluido + ":" + someDTO.getProperty() +
",\tsomeValue:" + someDTO.getValue() + "'.");
throw new Exception(mensajeExcluido);
this code
String mensajeExcluido = ArqSpringContext.getPropiedad("REGLA.MENSAJE");
String mensajeWarn = "ALERTA: Otro Servicio: " + mensajeExcluido + ":" +
someDTO.getProperty() + ",\tsomeValue:" + someDTO.getValue() + "'.";
LOG.warn(mensajeWarn);
boolean exclusionVisible = Boolean.valueOf(ArqSpringContext.getPropiedad("EXCLUSION.VISIBLE"));
if (exclusionVisible) {
mensajeWarn = "<br></br>" + mensajeWarn;
} else {
mensajeWarn = "";
}
throw new Exception(mensajeExcluido + mensajeWarn);
an this code
LOG.warn("No se pudo validar Client Service. Code: " +
someDTO.getStatusCode() + ".");
return "No se pudo validar Client Service. Code: " +
someDTO.getStatusCode() + ".";
In order to follow best practices...
What recommendations are applicable?
What changes would they make to the code?
How should texts be handled?
First, try to avoid message creation processing before checking if the log statement should be printed (I.e.: don't concatenate the messages strings before checking the log level.
// Better this
if (LOG.isDebugEnabled())
LOG.debug("This is a message with " + variable + " inside");
// Than this
final String message = "This is a message with " + variable + " inside";
if (LOG.isDebugEnabled())
LOG.debug(message);
Most Java logging frameworks allow a check to know in advance if a log statement is going to be printed based on the given settings.
If you want to save you the burden of writting those checks for each log statement, you can take advantage of Java 8 lambdas and code an utility like this:
import java.util.function.Supplier;
import java.util.logging.Logger;
import static java.util.logging.Level.FINE;
class MyLogger {
public static MyLogger of(final Class<?> loggerClass) {
return new MyLogger(loggerClass);
}
private final Logger logger;
private MyLogger(final Class<?> loggerClass) {
logger = Logger.getLogger(loggerClass.getName());
}
// Supplier will be evaluated AFTER checking if log statement must be executed
public void fine(final Supplier<?> message) {
if (logger.isLoggable(FINE))
logger.log(FINE, message.get().toString());
}
}
static final LOG = MyLogger.of(String.class);
public void example() {
LOG.fine(() -> "This is a message with a system property: " + System.getProperty("property"));
}
And finally, you can take advantage of Java string formatting to format log messages using String.format. I.e.:
final String message = String.format("Print %s string and %d digit", "str", 42);
Those good practices applied to the examples you provided would be:
/*
* Using java.util.logging in JDK8+
*/
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.lang.String.format;
class Dto {
String getProperty() { return "property"; }
String getValue() { return "property"; }
String getStatusCode() { return "statusCode"; }
}
final Logger LOG = Logger.getGlobal();
final Dto someDTO = new Dto();
void example1() throws Exception {
String mensajeExcluido = System.getProperty("MENSAJE.EXCLUIDO");
// Check if log will be printed before composing the log message
if (LOG.isLoggable(Level.WARNING)) {
// Using String.format usually is clearer and gives you more formatting options
final String messageFormat = "ERROR: Servicio: %s:%s,\tsomeValue:%s'.";
LOG.warning(format(messageFormat, mensajeExcluido, someDTO.getProperty(), someDTO.getValue()));
}
// Or using lambdas
LOG.warning(() -> {
final String message = "ERROR: Servicio: %s:%s,\tsomeValue:%s'.";
return format(message, mensajeExcluido, someDTO.getProperty(), someDTO.getValue());
});
throw new Exception(mensajeExcluido);
}
void example2() throws Exception {
String mensajeExcluido = System.getProperty("REGLA.MENSAJE");
String mensajeWarn = format(
// The concatenated message is probably missing a single quote at 'someValue'
"ALERTA: Otro Servicio: %s:%s,\tsomeValue:%s'.",
mensajeExcluido,
someDTO.getProperty(),
someDTO.getValue()
);
LOG.warning(mensajeWarn);
boolean exclusionVisible = Boolean.parseBoolean(System.getProperty("EXCLUSION.VISIBLE"));
String exceptionMessage = exclusionVisible ?
mensajeExcluido + "<br></br>" + mensajeWarn : mensajeExcluido;
throw new Exception(exceptionMessage);
}
String example3() {
// You can compose the message only once and use it for the log and the result
String message =
format("No se pudo validar Client Service. Code: %s.", someDTO.getStatusCode());
LOG.warning(message);
return message;
}
I need to read JSON from file and replace few objects.
For example, I have class User.java
public class User {
String username;
String email;
String city;
String code;
}
and JSON:
{
"variables":
{
"user":
{
"value":
{
"username": "$USERNAME",
"email": "$EMAIL",
"city": "$CITY"
}
}
}
}
I have two questions:
How can I read JSON from file? Read JSON will be send by WebClient POST API.
How can I replace $USERNAME, $EMAIL and $CITY? I won't hardcode it.
I have register form. When someone complete form, it will be replaced for $...
Firsty, I got hardcode JSON to string but I need read it from file
class JSONClass {
static String toFormat(User user) {
String jsonUserRegister = "{\n" +
" \"variables\":\n" +
" {\n" +
" \"user\": \n" +
" {\n" +
" \"value\":\n" +
" {\n" +
" \"username\": \"" + user.getUsername() + "\",\n" +
" \"email\": \"" + user.getEmail() + "\",\n" +
" \"city\": \"" + user.getCity() + "\",\n" +
" \"code\": \"" + user.getCode() + "\"\n" +
" } }\n" +
" }\n" +
"}";
return jsonUserRegister;
This can be achieved using Spring Boot to set up the backend to receive client calls. So to get Task 1a working, we need below
#RestController
public class JsonReaderController {
#Autowired
private ResourceLoader resourceLoader;
#PostMapping(value = "/read-json")
public String fileContent() throws IOException {
return new String(Files.readAllBytes(
resourceLoader.getResource("classpath:data/json- sample.json").getFile().toPath()));
}
}
Above code simply reads file content and returns as String. Note default response is Json.
Now that we have the backend done, we need Task 1b - Sending the POST request.
private String readJsonFile() throws IOException {
final OkHttpClient client = new OkHttpClient();
final String requestUrl = "http://localhost:8080/read-json";
Request request = new Request.Builder()
.url(requestUrl)
.post(RequestBody.create(JSON, ""))
.build();
try (Response response = client.newCall(request).execute()) {
//we know its not empty given scenario
return response.body().string();
}
}
readJsonFile method makes a POST request - using OkHttp to our backend bit (done in Task 1a) and returns the content of the file as json.
And for Task 2 - replacing $USERNAME, $EMAIL and $CITY with appropriate values. For this, we will use the Apache commons-text library.
public static void main(String[] args) throws IOException {
String fileContent = new ReadJsonFromFile().readJsonFile();
User user = new User("alpha", "alpha#tesrt.com", "Bristol", "alpha");
Map<String, String> substitutes = new HashMap<>();
substitutes.put("$USERNAME", user.getUsername());
substitutes.put("$EMAIL", user.getEmail());
substitutes.put("$CITY", user.getCity());
substitutes.put("$CODE", user.getCode());
StringSubstitutor stringSubstitutor = new StringSubstitutor(substitutes);
//include double quote prefix and suffix as its json wrapped
stringSubstitutor.setVariablePrefix("\"");
stringSubstitutor.setVariableSuffix("\"");
String updatedContent = stringSubstitutor.replace(fileContent);
System.out.println(updatedContent);
}
Hope this helps.
My code is 100% working. I dont understand when i store the receiving output from Volley onresponse, i cant seem to store them correctly into my object. The raw output is correct. When i store it into my object, and then try to read the object, it showing wrong information.
For example, there is no data for contact and data for position is output at wrong place.
Log.d("TAG", "onResponse : "+ response.toString());
myProfile.set_firstname(response.optString("firstname", ""));
myProfile.set_lastname(response.optString("lastname", ""));
myProfile.set_contact(response.optString("contact", ""));
myProfile.set_email(response.optString("email", ""));
myProfile.set_position(response.optString("position", ""));
myProfile.set_areaname(response.optString("area", ""));
myProfile.set_deptname(response.optString("department", ""));
Log.d("TAG", "myProfile SET : " +
"firstname: "+myProfile.get_firstname() + " " +
"lastname: "+myProfile.get_lastname() + " " +
"contact: "+myProfile.get_contact() + " " +
"email: "+myProfile.get_email() + " " +
"position: "+myProfile.get_position() + " " +
"area: "+myProfile.get_areaname() + " " +
"dept: "+myProfile.get_deptname()
);
Raw JSON response from Volley and Log.d
onResponse : {"firstname":"kirpal","lastname":"SINGH","contact":"0164028083","email":"kirpal#gmail.com","position":"Technician","area":"Nextrack","department":"nexpro"}
myProfile SET : firstname: kirpal lastname: SINGH contact: Technician email: kirpal#gmail.com position: area: Nextrack dept: nexpro
MyProfile.java
public class MyProfile {
private String id="";
private String firstname="";
private String lastname="";
private String areaname ="";
private String deptname ="";
private String contact ="";
private String email ="";
private String position ="";
//SET
public void set_id(String id){this.id = id;}
public void set_firstname(String firstname){this.firstname = firstname;}
public void set_lastname(String lastname){this.lastname = lastname;}
public void set_areaname(String areaname){this.areaname = areaname;}
public void set_deptname(String deptname){this.deptname = deptname;}
public void set_contact(String contact){this.contact = contact;}
public void set_email(String email){this.email = email;}
public void set_position(String position){this.contact = position;}
//GET
public String get_id(){return this.id;}
public String get_firstname(){return this.firstname;}
public String get_lastname(){return this.lastname;}
public String get_areaname(){return this.areaname;}
public String get_deptname(){return this.deptname;}
public String get_contact(){return this.contact;}
public String get_email(){return this.email;}
public String get_position(){return this.position;}
}
Wrong info shows because you set position on contact and also set position on position.
public void set_position(String position){this.contact = position;}
change to
public void set_position(String position){this.position = position;}
How would JestResult.getSourceAsObjectList be used to map the field "#timestamp"? Actually, I cannot figure out how to map any field with a name starting with "#". It keeps getting set to "null".
For example if the Elasticsearch query returns
{
"_id": "Vhv2OE1SNSeSg285UYQRQ",
"#version": "1",
"#timestamp": "2014-12-19T01:18:06.454Z"
"type": "hdfs"
}
and there is a matching POJO Java class
import io.searchbox.annotations.JestId;
public class ElasticsearchLog {
#JestId
private String _id;
private String version;
private String timestamp;
private String type;
#Override
public String toString() {
return "ElasticsearchLog{" +
"_id='" + _id + '\'' +
", version='" + version + '\'' +
", timestamp='" + timestamp + '\'' +
", type='" + type + '\''
' }';
}
Then doing
import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.JestResult;
import io.searchbox.client.config.HttpClientConfig;
import io.searchbox.core.Search;
import java.util.List;
public class JESTClient {
public static void main(String[] args) throws Exception {
String clusterIP = "localhost";
String port = "9200";
//setup client
JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(new HttpClientConfig
.Builder("http://" + clusterIP + ":" + port)
.multiThreaded(true)
.build());
JestClient client = factory.getObject();
Search search = new Search.Builder("{ \"query\": { \"match_all\": {} } }")
.addIndex("_all")
.build();
JestResult result = client.execute(search);
List<ElasticsearchLog> resultLogs = result.getSourceAsObjectList(ElasticsearchLog.class);
for(ElasticsearchLog log: resultLogs){
System.out.println(log);
}
Prints out
ElasticsearchLog{_id='Vhv2OE1SNSeSg285UYQRQ', version='null', timestamp='null', type='hdfs'}
So the "#version" and "#timestamp" are not getting mapped properly.
JsonObject itself seems to be just fine with "#" symbols:
import com.google.gson.JsonObject;
public static void main(String[] args){
JsonObject testy = new JsonObject();
testy.addProperty("#timestamp", "zzz");
System.out.println(testy.get("#timestamp"));
}
Outputs: "zzz"
What is the proper usage of JestResult.
getSourceAsObjectList to map a json field with a name starting with "#"?
Note: This is for
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>0.1.4</version>
</dependency>
Searchly support to the rescue!
Email response from support#searchly.com
Ferhat Sobay replied:
Problem in here is #version requires a Java field as '#version' which is not possible with Java lang. #SerializedName annotation comes to rescue, had to dig a little but works!
So try below;
public class ElasticsearchLog {
#JestId
private String _id;
#SerializedName("#version")
private String version;
#SerializedName("#timestamp")
private String timestamp;
private String type;
#Override
public String toString() {
return "ElasticsearchLog{" +
"_id='" + _id + '\'' +
", version='" + version + '\'' +
", timestamp='" + timestamp + '\'' +
", type='" + type + '\''
' }';
}
Best,
#Ferhat