I'm using android.util.Log
class Foo
{
private void boo()
{
// This is the basic log of android.
Log.i("tag", "Start");
}
}
I want the log should be printed [Foo::boo] Start.
Can I get the class and function name in Java? Then how do I wrap the code?
here
UPDATED
String tag = "[";
tag += this.getClass().toString();
tag += " :: ";
tag += Thread.currentThread().getStackTrace()[1].getMethodName().toString();
tag += "]";
Log.i(tag, "Message");
this.getClass().toString() will return class name as String
UPDATE
if function is static then use following code
String tag = "[";
tag += Thread.currentThread().getStackTrace()[1].getClassName().toString();
tag += " :: ";
tag += Thread.currentThread().getStackTrace()[1].getMethodName().toString();
tag += "]";
Log.i(tag, "Message");
Get The Current Class Name and Function Name :
Log.i(getFunctionName(), "Start");
private String getFunctionName()
{
StackTraceElement[] sts = Thread.currentThread().getStackTrace();
if(sts == null)
{
return null;
}
for(StackTraceElement st : sts)
{
if(st.isNativeMethod())
{
continue;
}
if(st.getClassName().equals(Thread.class.getName()))
{
continue;
}
if(st.getClassName().equals(this.getClass().getName()))
{
continue;
}
return mClassName + "[ " + Thread.currentThread().getName() + ": "
+ " " + st.getMethodName() + " ]";
}
return null;
}
You can use these methods of java.lang.Class class
getClass().getname() - to get the name of the class
getClass().getMethods() - to get the methods declared in that class.
Related
How can I check for an empty Optional array of strings in Java?
In the case is empty I would like to return a message.
#PostMapping("/users")
#ResponseBody
public String saveUsers(#RequestParam Optional<String>[] paramArray) {
System.out.println("param " + paramArray);
String msg = "";
int i = 0;
if (paramArray is empty) {
msg = "paramArray is empty";
} else {
for (Optional<String> paramArrayItem : paramArray) {
msg += "param[" + i + "]" + paramArrayItem + "\n";
i++;
}
}
return msg;
}
Optional<String>[] is an array of Optional<String> elements.
You'd rather want to have optional array of strings, so you need to change paramArray type to Optional<String[]>.
#PostMapping("/users")
#ResponseBody
public String saveUsers(#RequestParam Optional<String[]> paramArray) {
System.out.println("param " + paramArray);
String msg = "";
int i = 0;
if (paramArray.isEmpty()) {
msg = "paramArray is empty";
} else {
for (String paramArrayItem : paramArray.get()) {
msg += "param[" + i + "]" + paramArrayItem + "\n";
i++;
}
}
return msg;
}
I want to write into a file/print the constants of an enum, as well as the values of their variables.
For example, here is what I thought of doing:
id, field_name_1, field_name_2, ...
enum_id, field_value_1, field_value_2, ...
...
However, I am not fully sure on how to do such a thing, as I only recently began working with reflection.
This is the code that I currently have.
public static void writeEnum(String filename, Enum e, SnelPlugin plugin){
SnelTextFile file = new SnelTextFile(plugin, new File(plugin.getDataFolder() + "/" + filename + ".txt"));
Logger.debug("Starting an EnumWriter for " + filename + ".txt for plugin " + plugin.getPluginName());
try {
file.openWriter(true);
Field[] fields = e.getClass().getFields();
// HEADER
String info = "";
for(Field f: fields) {
info += ", " + f.getName();
Logger.debug("Detected value: " + f.getName());
}
info = info.replaceFirst(", ", "");
file.addLine(info);
// CONTENT
for(Object current: e.getDeclaringClass().getEnumConstants()){
Logger.debug(current.toString());
String result = "";
for(Field f: fields){
result += ", " + f.get(current);
}
result = result.replaceFirst(", ", "");
file.addLine(result);
Logger.debug("Added row: " + result);
}
}catch (Exception ex){
ex.printStackTrace();
}finally {
try {
file.closeWriter();
} catch (IOException e1) {
}
}
Logger.log(LColor.GREEN + "Finished an EnumWriter action on " + filename + ".txt from " + plugin.getPluginName());
}
Here is the Enum (APIPerm), which I setup for a simple test:
COMMANDS_SNELAPI,
COMMANDS_SNELAPI_INFO;
private String id;
APIPerm(){
id = getID();
}
#Override
public String getPrefix() {
return "snelapi";
}
#Override
public String getID(){
return getPrefix() + "." + this.toString().toLowerCase().replaceAll("_", ".");
}
However, I get an NPE in for(Object current: e.getDeclaringClass().getEnumConstants())
Thanks for your help,
Sneling.
Thanks to #Pshemo and #MarkusFisher, I've come to a solution.
Note that this method DOES include other classes and methods, but they don't affect the way this method works.
If you want to test for yourself:
Logger.debug can be replaced with System.out.println, LColor should
be deleted
SnelPlugin is only needed for the Logger.debug and locating a directory.
SnelTextFile is just a class to make creating text files easier. Remove if you're only printing.
Method Code:
public static <E extends Enum<E>> void writeEnum(String fileName, Class<E> c, SnelPlugin plugin){
SnelTextFile file = new SnelTextFile(plugin, new File(plugin.getDataFolder() + "/" + fileName + ".txt"));
Logger.debug("Starting EnumWriter for " + file.getFile().getName(), plugin);
try {
file.openWriter(true);
Logger.debug("Opened FileWriter", plugin);
Field[] classFields = c.getDeclaredFields();
String header = "Value";
for(Field f: classFields){
if(!Modifier.isStatic(f.getModifiers())) {
header += ", " + f.getName();
Logger.debug("Discovered variable '" + f.getName() + "'", plugin);
}
}
file.addLine(header);
file.addLine("");
for(E en: c.getEnumConstants()){
Logger.debug("Reading Enum Constant: " + en.toString(), plugin);
Field[] fields = en.getDeclaringClass().getDeclaredFields();
String current = en.toString();
for(Field f: fields){
if(!Modifier.isStatic(f.getModifiers())){
f.setAccessible(true);
current += ", " + f.get(en);
Logger.debug("Value for '" +f.getName() + "' = '" + f.get(en) + "'" , plugin);
}
}
file.addLine(current);
}
}catch (Exception ex){
ex.printStackTrace();
}finally {
try {
file.closeWriter();
Logger.debug("Closer FileWriter");
} catch (IOException ex) {
}
}
Logger.log(LColor.GREEN + "Finished EnumWriter for " + file.getFile().getName() + ". It can be found at " + file.getFile().getPath(), plugin);
}
If you want to get the values of the Enum, normally you would just call the values() method on the Enum class. But since you are starting with an instance you need to get the class and call it. I don't see any way to just cast the class to Enum, so I used reflection to get the public static Enum[] values() method like this.
/**
* Get the Enum values for this Enum instance.
* #param e the enum value
* #return all the values for this type of enum
*/
private Enum[] getValues(Enum e) {
Enum[] values = new Enum[0];
try {
Class<? extends Enum> enumClass = e.getDeclaringClass();
Method mtd = enumClass.getMethod("values");
values = (Enum[])mtd.invoke(null);
}
catch (Exception ex) {
ex.printStackTrace();
}
return values;
}
Obviously you should do better error handling. I am not sure what else you wanted from the Enum class in regards to fields.
I have a simple class named A which has two private fields.
public class A {
private String a;
private String b;
} // A
When I get all declared fields from class instance, I get one extra field named $change of type com.android.tools.fd.runtime.IncrementalChange. Where is it coming from ? I am totally not getting this.
Field[] fields = cls.getDeclaredFields();
for (int i = 0, len = fields.length; i < len; i++) {
Field field = fields[i];
field.setAccessible(true);
Log.d("TAG", field.getName());
if (field.isAnnotationPresent(Primary.class)) {
query += getFromalName(field.getName()).toUpperCase() + " " + getSchemaType(field.getType().getSimpleName()) + " PRIMARY KEY, ";
continue;
}
if (field.isAnnotationPresent(NotNull.class)) {
query += getFromalName(field.getName()) + " " + getSchemaType(field.getType().getSimpleName()) + " NOT NULL, ";
continue;
}
query += getFromalName(field.getName()) + " " + getSchemaType(field.getType().getSimpleName()) + ", ";
} // end for
query = query.substring(0, query.lastIndexOf(","));
query += " )";
It was added to support instant run. Disabling instant run solved the problem. here
is the link to android issue tracker
I am trying to get response text from Java server using getJSON() jQuery method. Although, I can get response data when the Java class is simple format (String, List and Map), I could not get success data when using other Java object.
The following is Java class which is using a simple type and I get the success result with data that works:
package com.awitd.framework.action;
import com.opensymphony.xwork2.Action;
public class getAllJson implements Action{
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String execute() {
System.out.println(" this is from action");
data = "[";
data += "{";
data += "\"objid\":\"" + "1" + "\",";
data += "\"id\":\"" + "1" + "\",\"name\":\"" + "name" + "\"";
data += "}"; System.out.println("data " + data);
data += "]";
return SUCCESS;
}
}
The following is Java class which is using other Java object and it doesn't return a success data:
package com.awitd.framework.action;
import java.util.List;
import com.opensymphony.xwork2.Action;
import com.awitd.framework.entity.Employee;
import com.awitd.framework.entity.Profile;
import com.awitd.framework.service.EmployeeService;
public class getAllJson implements Action{
private String data;
private EmployeeService employeeService;
private List<Employee> employeeList;
private Employee employee;
private Profile profile;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public EmployeeService getEmployeeService() {
return employeeService;
}
public void setEmployeeService(EmployeeService employeeService) {
this.employeeService = employeeService;
}
public String execute() {
System.out.println(" this is from action");
data = "[";
/*data += "{";
data += "\"objid\":\"" + "1" + "\",";
data += "\"id\":\"" + "1" + "\",\"name\":\"" + "name" + "\"";
data += "}"; System.out.println("data " + data);*/
employeeList = employeeService.getAll();
System.out.println("size........"+employeeList.size());
if (!employeeList.isEmpty()) {
for (int i=0; i<employeeList.size(); i++) {
employee = employeeList.get(i);
profile = employee.getProfile();
data += "{";
data += "\"objid\":\"" + employee.getEmployeeId() + "\",";
data += "\"id\":\"" + employee.getId() + "\",\"name\":\"" + employee.getName() + "\"";
data += ",\"dob\":\"" + profile.getDob() + "\",\"sex\":\"" + profile.getSex() + "\"";
data += ",\"email\":\"" + profile.getEmail() + "\",\"workstart\":\"" + profile.getWorkstart() + "\"";
data += ",\"study\":\"" + profile.getStudySub() + "\",\"jplevel\":\"" + profile.getJpLevel() + "\"";
data += ",\"jpgroup\":\"" + profile.getJpGroup() + "\",\"remark\":\"" + profile.getRemark() + "\"";
data += "}";
if (!(i==employeeList.size()-1))
data += ",";
}
}
data += "]";
return SUCCESS;
}
}
Got this error:
No existing transaction found for transaction marked with propagation 'mandatory'
java.lang.reflect.InvocationTargetException
org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException:
org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException
org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:246)
org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:178)
org.apache.struts2.json.JSONWriter.process(JSONWriter.java:168)
org.apache.struts2.json.JSONWriter.value(JSONWriter.java:134)
org.apache.struts2.json.JSONWriter.write(JSONWriter.java:102)
org.apache.struts2.json.JSONUtil.serialize(JSONUtil.java:116)
org.apache.struts2.json.JSONResult.createJSONString(JSONResult.java:196)
org.apache.struts2.json.JSONResult.execute(JSONResult.java:170)
com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:367)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:271)
Try the following code, it should fix the error
data += "{";
data += "\"objid\":\"" + employee.getEmployeeId() + "\",";
data += "\"id\":\"" + employee.getId() + "\",\"name\":\"" + employee.getName() + "\",";
data += ",\"dob\":\"" + profile.getDob() + "\",\"sex\":\"" + profile.getSex() + "\",";
data += ",\"email\":\"" + profile.getEmail() + "\",\"workstart\":\"" + profile.getWorkstart() + "\",";
data += ",\"study\":\"" + profile.getStudySub() + "\",\"jplevel\":\"" + profile.getJpLevel() + "\",";
data += ",\"jpgroup\":\"" + profile.getJpGroup() + "\",\"remark\":\"" + profile.getRemark() + "\"";
data += "}";
We are doing some integration towards a quite inconsistent (Zurmo-)REST API. The API only accepts urlencoded strings as its payload in the http posts, but it answers with JSON.
So as the documentation was very unclear on this we naturally thought we could post JSON to it, but this was not the case.
So now we have all our code generating JSON when we need to send it as x-www-form-urlencoded, is there any java library that can do a conversion from JSON to an urlencoded string?
We are currently using the org.json lib, but we can change it if there would be a need for it.
Example:
This JSON string:
{"data":{"description":"test","occurredOnDateTime":"2013-10-24 01:44:50"}}
Should be converted into this:
data%5Bdescription%5D=test&data%5BoccurredOnDateTime%5D=2013-10-24+01%3A44%3A50
Java code:
We translated rasmushaglunds javascript code to java and wrapped it, here is the result if anybody else stumbles upon this problem.
public static String jsonToURLEncoding(JSONObject json) {
String output = "";
String[] keys = JSONObject.getNames(json);
for (String currKey : keys)
output += jsonToURLEncodingAux(json.get(currKey), currKey);
return output.substring(0, output.length()-1);
}
private static String jsonToURLEncodingAux(Object json, String prefix) {
String output = "";
if (json instanceof JSONObject) {
JSONObject obj = (JSONObject)json;
String[] keys = JSONObject.getNames(obj);
for (String currKey : keys) {
String subPrefix = prefix + "[" + currKey + "]";
output += jsonToURLEncodingAux(obj.get(currKey), subPrefix);
}
} else if (json instanceof JSONArray) {
JSONArray jsonArr = (JSONArray) json;
int arrLen = jsonArr.length();
for (int i = 0; i < arrLen; i++) {
String subPrefix = prefix + "[" + i + "]";
Object child = jsonArr.get(i);
output += jsonToURLEncodingAux(child, subPrefix);
}
} else {
output = prefix + "=" + json.toString() + "&";
}
return output;
}
public static String objectToUrlEncodedString(Object object, Gson gson) {
return jsonToUrlEncodedString((JsonObject) new JsonParser().parse(gson.toJson(object)));
}
private static String jsonToUrlEncodedString(JsonObject jsonObject) {
return jsonToUrlEncodedString(jsonObject, "");
}
private static String jsonToUrlEncodedString(JsonObject jsonObject, String prefix) {
String urlString = "";
for (Map.Entry<String, JsonElement> item : jsonObject.entrySet()) {
if (item.getValue() != null && item.getValue().isJsonObject()) {
urlString += jsonToUrlEncodedString(
item.getValue().getAsJsonObject(),
prefix.isEmpty() ? item.getKey() : prefix + "[" + item.getKey() + "]"
);
} else {
urlString += prefix.isEmpty() ?
item.getKey() + "=" + item.getValue().getAsString() + "&" :
prefix + "[" + item.getKey() + "]=" + item.getValue().getAsString() + "&";
}
}
return urlString;
}
There is an easier way now, and that is to use the URLEncoder.encode method.
Import the URLEncoder package:
import java.net.URLEncoder;
and then:
URLEncoder.encode(objectMapper.writeValueAsString(<yourClass>), StandardCharsets.UTF_8.toString());
You can test your result here:
https://onlinejsontools.com/url-decode-json
As noted below, it's not a Java library but you should be able to translate it :)
Here's how you could do it in javascript:
var jsonArrayToUrl = function (obj, prefix) {
var urlString = "";
for (var key in obj) {
if (obj[key] !== null && typeof obj[key] == "object") {
prefix += "[" + key + "]";
urlString += jsonArrayToUrl(obj[key], prefix);
}else{
urlString += prefix + "[" + key + "]=" + obj[key] + "&";
}
}
return encodeURIComponent(urlString);
};
Then call it with
jsonArrayToUrl(test["data"], "data");
By the example string you gave above it returns
"data%5Bdescription%5D%3Dtest%26data%5BoccurredOnDateTime%5D%3D2013-10-24%2001%3A44%3A50%26"
It should work recursively on nested arrays. You might also consider writing a wrapper for the function so that you only need one argument.