JSON Formatting in Data Logging File - java

I am trying to convert a file that contains data logging parameters to be json format.
Currently it retains the format:
{ X }
{ X }
I know this is not a valid JSON format, so I am trying to make it like this:
[
{ X },
{ X }
]
This is the code I have right know that logs data as this function is called:
public void write(String _rec) {
writeLock.writeLock().lock();
timestamp = System.currentTimeMillis();
String jsonstr = "{ \"timestamp\":" + timestamp + ", \"record\" : " + _rec + " },\n";
// Log.d(LOG_TAG, jsonstr);
try {
fileWriter.write(jsonstr);
fileWriter.flush();
} catch(IOException e) {
e.printStackTrace();
}
writeLock.writeLock().unlock();
} // END write
I added the comma in after the closing }, but I am not sure what to do about the []. Is there a way when I make the file I can insert the [] and then start writing information between them? Is there another solution to automatically insert these brackets?

Related

Wrap the key-value pairs with double quotes in Json String in java

To make it into a valid JSON
"{containerId:81,params:[{parameterName:vinay,valueInDesignMode:where actor_id<50,valueInRunMode:where actor_id<100},{parameterName:name,valueInDesignMode:where actor < =10,valueInRunMode:},{parameterName:nameID,valueInDesignMode:,valueInRunMode:}]}"
Expected output
{"containerId":81,"params":[{"parameterName":"vinay","valueInDesignMode":"where actor_id<50","valueInRunMode":"where actor_id<100","containerId":81},{"parameterName":"name","valueInDesignMode":"where actor < =10","valueInRunMode":""},{"parameterName":"nameID","valueInDesignMode":"","valueInRunMode":""}]}
Please check this:
public static void main(String[] args) {
String inputJson = "{containerId:81,params:[{parameterName:vinay,valueInDesignMode:where actor_id<50,valueInRunMode:where actor_id<100},{parameterName:name,valueInDesignMode:where actor < =10,valueInRunMode:},{parameterName:nameID,valueInDesignMode:,valueInRunMode:}]}";
String outputJson =
inputJson
.replace(" ", "")
.replaceAll("([\\w]+):", "\"$1\":")
.replaceAll(":([\\w|<|=]+)", ": \"$1\"")
.replaceAll("\"([\\d]+)\"", "$1")
.replace(":}", ": \"\"}")
.replace(":]", ": \"\"]")
.replace(":,", ": \"\",");
System.out.println(outputJson);
}
Although this code gives your desired result but you can find better solutions.
To convert the above Object to JSON you need to make the key and value as a string like the below and later you can parse the JSON to evaluate the conditional statements.
{
"containerId":81,
"params":[
{
"parameterName":"vinay",
"valueInDesignMode":"where actor_id<50",
"valueInRunMode":"where actor_id<100"
},
{
"parameterName":"name",
"valueInDesignMode":"where actor < =10",
"valueInRunMode":null
},
{
"parameterName":"nameID",
"valueInDesignMode": null,
"valueInRunMode":null
}
]}

Return substring of analyzed, non-stored text field in elasticsearch java api

I work on a project that has a string field (the name is urlOrContent) and it can be small (less than 50 character) or very long (more than 50 character), and I just want to return the first 50 characters every time based on a specific query. My database is elasticsearch and my problem is raised in this link and the questioner’s response seems to be correct (urlOrContent field is analyzed and non stored text field). It uses following script:
{
"script_fields": {
"substring": {
"script": {
"lang": "painless",
"inline": "params._source.text.substring(0, 100)"
}
}
}
}
But my main problem is that I can not find the equivalent of elasticsearch java api code. In fact, what should be added to the code below, which only returns the first 50 characters of the urlOrContent field? Note that this field may not even have 50 characters in some cases, and then the entire string should be returned.
String queryString =
EnumLinkFields.CREATE_TIME.getFieldName() + ":(>=" + dateFrom + " AND <=" + dateTo + ")";
QueryBuilder query = QueryBuilders.queryStringQuery(queryString);
SearchResponse response = TRANSPORT_CLIENT.prepareSearch(MY_INDEX)
.setTypes(MY_TYPE)
.setSearchType(SEARCH_TYPE)
.setQuery(query)
.setFetchSource(null, new String[]{EnumLinkFields.USER_ID.getFieldName()})
.setFrom(offset)
.setSize(count)
.addSort(orderByField, sortOrder)
.execute().actionGet();
I found the best answer.
String queryString =
EnumLinkFields.CREATE_TIME.getFieldName() + ":(>=" + dateFrom + " AND <=" + dateTo + ")";
QueryBuilder query = QueryBuilders.queryStringQuery(queryString);
String codeUrlOrContent = "if (" + EnumElasticScriptField.URL_OR_CONTENT.getFieldName() + ".length() > 50) {" +
"return " + EnumElasticScriptField.URL_OR_CONTENT.getFieldName() + ".substring(0, 50);" +
"} else { " +
"return " + EnumElasticScriptField.URL_OR_CONTENT.getFieldName() + "; }";
Script scriptUrlOrContent = new Script(ScriptType.INLINE, "painless",
codeUrlOrContent, Collections.emptyMap());
Script scriptIsUrl = new Script(ScriptType.INLINE, "painless",
EnumElasticScriptField.IS_URL.getFieldName(), Collections.emptyMap());
SearchResponse response = TRANSPORT_CLIENT.prepareSearch(MY_INDEX)
.setTypes(MY_TYPE)
.setSearchType(SEARCH_TYPE)
.setQuery(query)
.addScriptField(EnumLinkFields.URL_OR_CONTENT.getFieldName(),
scriptUrlOrContent)
.addScriptField(EnumLinkFields.IS_URL.getFieldName(), scriptIsUrl)
.setFrom(offset)
.setSize(count)
.addSort(orderByField, sortOrder)
.execute().actionGet();
Note that the call to the setFetchSource function must be removed and all returned fields must be returned through the script.
You can put your script_fields query in the query object, i.e. in setQuery(query).
Your query object should be looking like this right now.
"query" : {
"term" : { "user" : "kimchy" }
}
After you add the script_fields in the object, it should become:
"query" : {
"term" : { "user" : "kimchy" }
},
"script_fields": {
"urlOrContent": {
"script": {
"lang": "painless",
"inline": "if(params._source.urlOrContent.length() > 50){
params._source.urlOrContent.substring(0, 50)
}
else {
params._source.urlOrContent
}"
}
}
}
The resulting hits will have a fields array with the substring you required.
You have to enable scripting by changing the elasticsearch.yml file like so and restart the elasticsearch:
script.engine.painless.inline.aggs: on
script.engine.painless.inline.update: on
script.inline: on
script.indexed: on

No file BLOB, through JSON from ORACLE to SQL Server

i am a student and right now I'm doing an internship working with a local library, and in this case i have the following problem:
In the project i´m making, i need to retrieve image data from a temporal table, constructed in ORACLE that receives its data from some triggers in an INFORMIX DB and parse it through a monitor made in JAVA, in a JSON format to a web service published in C# and insert that image in a SQL Server DB.
I looked around and i found that it was possible to parse images through JSON using Base64 encoding and whatnot but when they talk about it they say that you must have the image path file and encode it. as you may have realized by now, i cant use that route because i don't have those images, best case scenario, the triggers are able to feed some BLOB data (by what I've been told). but i have to insert them in the SQL Server DB as Varbinary(MAX).
To summarize:
-->Informix DB has images -->triggers feed an ORACLE Temp_table (images sent probably as BLOB or CLOB at most)-->monitor made in JAVA must read those BLOBS or CLOBS and send them through JSON
-->Web Service made in C# must receive that JSON, and insert the images in a SQL Server DB (where they need to be visible, without having the physical file to refer to).
the schema i´m using (it has been IMPOSED to me, i didn't had a saying in this) is something similar to this: (it´s really long and tedious code so i´ll try to make it as neat and clean as possible)
This is the part of the java monitor that specifies which fields from the temp_table are feeding what fields in the JSON structure
public static BookRecordList viewBookRecordTable(Connection connection) throws ExceptionToOracleConcurrent
{
BookRecordList bookRecordList = new BookRecordList();
BookRecord bookRecord = new BookRecord();
Statement stmt = null;
String query = "SELECT operacion,"
+ "UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(img_logo,32670,1))"
+ "x_logo,"
+ "UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(img_logoGris,32760,1))"
+ "UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(r_firma,32670,1)),"
+ " FROM "
+ dataBaseConnectionData.getDB_SHCHEMA() + "."+ dataBaseConnectionData.getDB_TABLE_COLA()
+ " WHERE (some condition)";
try
{
stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
while(rs.next())
{
try
{
bookRecord = new BookRecord();
bookRecord.setOperacion(rs.getInt("operacion"));
bookRecord.setImg_logo(rs.getString("img_logo"));
bookRecord.setImg_logoGris(rs.getString("img_logoGris"))
bookRecord.setR_firma(rs.getString("r_firma"));
bookRecord.print();
bookRecordList.getBookRecordList().add(bookRecord);
}
catch (Exception e)
{
logger.error("Some exception " + dataBaseConnectionData.getDB_TABLE_COLA() + ": " + e.toString());
e.printStackTrace();
//Process next order
continue;
}
}
}
catch (SQLException e )
{
logger.fatal("Some exception " + dataBaseConnectionData.getDB_TABLE_COLA() + ": " + e.toString());
throw new ExceptionToOracleConcurrent("exception definition " + dataBaseConnectionData.getDB_TABLE_COLA() + ": " + e.toString());
}
finally
{
if (stmt != null)
{
try
{
stmt.close();
}
catch (SQLException e)
{
logger.fatal("another exception " + e.toString());
}
}
}
return bookRecordList;
}
This is the part of the java monitor that generates the JSON (the empty cases contain another stuff that goes into the JSON but i sorted that out)
private static String GenerateJSON(SomeClass someClass) throws IOException
{
int operation = someClass.getOperation();
JSONObject obj = new JSONObject();
String jsonText = "";
switch (operation)
{
case 0:
//obligatory fields
obj.put("img_logo",someClass.getImg_logo());
break;
case 1:
break;
case 2:
//Obligatory fields
obj.put("img_foto",someClass.getC_empleado());
obj.put("img_firma",someClass.getC_empleado());
break;
case 3:
obj.put("r_firma",someClass.getR_firma());
break;
case 4:
break;
case 5:
break;
}
StringWriter out = new StringWriter();
obj.writeJSONString(out);
jsonText = out.toString();
String newJson = jsonText.replace("\\/", "/");
logger.info("JSON a enviar: " + newJson);
return newJson;
}
The web service is made in C#, it´s another case based program, structured accordingly to the operation number received in the JSON, it calls a number of function and, in the end, it comes down to these two:
this part of the WS receive the parameters of the parsed JSON
public int ActualizarFichaLibro( String img_foto, String r_firma)
{
try
{
//Define query to insert
Cmd.CommandText = QueryCFA.ActualizarFicha();
//Define parameters types to insert
Cmd.Parameters.Add("#img_foto", SqlDbType.VarBinary, -1);
Cmd.Parameters.Add("#r_firma", SqlDbType.VarBinary, -1);
//Define parameters values to insert
Cmd.Parameters["#img_foto"].Value = img_foto;
Cmd.Parameters["#r_firma"].Value = r_firma;
int rowCount = Cmd.ExecuteNonQuery();
CerrarConexionBd();
return rowCount;
}
catch (Exception)
{
return 0;
}
}
and finally that invokes a simple query, in this particular case, to this one:
public string ActualizarFicha()
{
Query = "UPDATE dbo.fichaEmpleado SET( CASE WHEN #img_foto = '' THEN NULL ELSE img_foto = CONVERT(VARBINARY(MAX), #img_foto, 2) END,"
+ "CASE WHEN #r_firma = '' THEN NULL ELSE img_firma = CONVERT(VARBINARY(MAX), #r_firma, 2) END,"
+"WHERE (some conditions)";
return Query;
}
my questions are:
is there a way to do this (sending images from one DB to anther) through JSON, specifically with this massive schema this people got going on? if not is there a way to do it?
the querys for reading a BLOB (possible BLOB) and inserting a Varbinary are well implemented?
I´m sorry for the extremely long explanation, I've been working on this for a week and i cant seem to find a proper way to do it (at least not with this schema, but the bosses don't want to change it)

Using enumeration to represent error messages legibily - is it good practice?

I'd like to consolidate my error messages and stuff into one file, and make my code more readable if possible.
Here's an example of what I have in my enum file:
public enum ZipErrorType {
// START: define exception messages (alphabetical order)
EMPTY_FILE_NAME_IN_LIST {
public String toString() {
return "One or more null/empty filename(s) found";
}
},
FILE_DOESNT_EXIST {
public String who(String sThisFile) {
return "[" + sThisFile + "] does not exist";
}
},
FILE_LIST_IS_NULL {
public String toString() {
return "File list is null/empty";
}
},
FILENAME_NOT_ABSOLUTE {
public String who(String sThisFile) {
return "[" + sThisFile + "] is not absolute";
}
},
MUST_BE_DIR {
public String who(String sThisFile) {
return "[" + sThisFile + "] must be a directory";
}
},
MUST_BE_FILE {
public String who(String sThisFile) {
return "[" + sThisFile + "] must be a file";
}
},
NULL_OR_EMPTY {
public String who(String sThisFile) {
return "[" + sThisFile + "] is null/empty";
}
},
OUTPUT_FILE_ALREADY_EXISTS {
public String who(String sThisFile) {
return "[" + sThisFile + "] already exists";
}
},
OUTPUT_FILENAME_EMPTY {
public String toString() {
return "Output filename is null/empty";
}
},
OUTPUT_PATH_EMPTY {
public String toString() {
return "Output path is null/empty";
}
},
// END: define exception messages
NONE {};
public String who(String sThisFile) { return ""; }
}
Then in my program I have code like:
private static ZipErrorType getFileErrorsIfAny(String sFilename, boolean shouldBeFile) {
// check if given filename is absolute
File file = new File(sFilename);
if (!file.isAbsolute()) {
return ZipErrorType.FILENAME_NOT_ABSOLUTE;
}
// check if file exists
if (!file.exists()) {
return ZipErrorType.FILE_DOESNT_EXIST;
}
// check if corresponding file is a file when it shouldn't be...
if (file.isFile() && !shouldBeFile) {
return ZipErrorType.MUST_BE_DIR;
}
// ...or a directory when it should be a file
else if (file.isDirectory() && shouldBeFile) {
return ZipErrorType.MUST_BE_FILE;
}
return ZipErrorType.NONE;
}
...and an example of how I make use of my enum:
// check input files
for (String sFile : files) {
if (sFile == null || sFile.trim().length() == 0) {
throw new NullPointerException("One or more filename is null/empty");
}
errorIfAny = getFileErrorsIfAny(sFile.trim(), true);
if (!errorIfAny.equals(ZipErrorType.NONE)) {
throw new ZipInputException(errorIfAny.who(sFile.trim()));
}
}
Now I know it's hard to judge just by these code snippets alone, but is this alright, from a general perspective? Is what I'm doing not worth the trouble, and is there a way to improve this?
I would suggest using simple string templates instead of enums for building error messages.
Something like this:
String EMPTY_FILE_NAME_IN_LIST_TEMPLATE = "One or more null/empty filename(s) found";
String FILE_DOESNT_EXIST_TEMPLATE = "[ %s ] does not exist";
String FILE_LIST_IS_NULL_TEMPLATE = "File list is null/empty";
String FILENAME_NOT_ABSOLUTE_TEMPLATE = "[ %s ] is not absolute";
String MUST_BE_DIR_TEMPLATE = "[ %s ] must be a directory";
String MUST_BE_FILE_TEMPLATE = "[ %s ] must be a file";
String NULL_OR_EMPTY_TEMPLATE = "[ %s ] is null/empty";
String OUTPUT_FILE_ALREADY_EXISTS_TEMPLATE = "[ %s ] already exists";
String OUTPUT_FILENAME_EMPTY_TEMPLATE = "Output filename is null/empty";
String OUTPUT_PATH_EMPTY_TEMPLATE = "Output path is null/empty";
And then, use String.format(template, sFilename) for building actual message.
You may also consider throwing an exception right out of getFileErrorsIfAny() method:
File file = new File(sFilename);
if (!file.isAbsolute()) {
throw new ZipInputException(String.format(FILENAME_NOT_ABSOLUTE_TEMPLATE, sFilename));
}
Looks cleaner and more compact to me.
This seems to have the potential to result in many many massive enums dotted around the code.
This isn't the first time someone has wanted to separate of the log message from the log statement.
In fact java.util.logging already has a framework for this that is designed for localisation.
It uses a .properties file which contains the messages.
You get the logger with the path to the file in the classpath : -
Logger logger = Logger.getLogger("com.example", "path/to/messages.properties");
Logging statements are then done using the property keys
logger.log(level, "messageKey");
And you can parameterise the logging because it uses MessageFormat syntax
zip.fileDoesNotExist={0} does not exist
logger.log(level, "zip.fileDoesNotExist", file);
These parameters are extremely flexible as you can specify formatting information in them and even use ChoiceFormat if needed.
The main advantage of all this is that your messages are in a separate file, rather than a class. And you can turn logging on and off at will with the logging.properties file. You can even turn logging on and off for single classes. And you can log to multiple files, to the console, you can send emails on errors etc etc
So, in conclusion. Use an existing logging framework. Don't roll your own.
Disclaimer: I only talk about JUL because then is built into Java - you don't need any 3rd party libs, there are many, many other frameworks out there.

Whats the best pratice to show multiple placemarks with photos inside of the ballons?

I have a project as follows: Several photos are taken from a mobile, the photos are saved in a web system, which in turn displays the photos on google earth that is inside it. I've read many articles but all of them were using fetchKml, one good article that i've read was using php, but using fetchKml. I dont know if its possible using parseKml instead. Anyway, I'm not sure how to do this with the kml, so it looks tike this:
My Class KMLGenerator()
public static String getKMLFromObra (List<Obra> obraFotos) {
StringBuffer sb = new StringBuffer();
sb.append("<?xml version='1.0' encoding='UTF-8'?>");
sb.append("<kml xmlns='http://www.opengis.net/kml/2.2' " +
"xmlns:gx='http://www.google.com/kml/ext/2.2' " +
"xmlns:kml='http://www.opengis.net/kml/2.2' " +
"xmlns:atom='http://www.w3.org/2005/Atom'> ");
if (obraFotos != null && obraFotos.size() > 0) {
for (Obra o : obraFotos) {
for (Local local : o.getLocais()) {
sb.append("<Document>");
sb.append("<name>" + local.getName() + "</name>");
sb.append("<Style id='defaultStyles'>");
sb.append("<IconStyle>");
sb.append("<scale>1.1</scale>");
sb.append("<Icon>");
sb.append("<href>" + "http://localhost:8080/ConstruMobilFoto/lib/img/fotoIcon.png" + "</href>");
sb.append("</Icon>");
sb.append("</IconStyle>");
sb.append("</Style>");
sb.append("<Placemark>");
sb.append("<name>" + "Foto" + "</name>");
sb.append("<styleUrl>" + "#defaultStyles"+ "</styleUrl>");
sb.append("<altitudeMode>" + "relativeToGround" + "</altitudeMode>");
sb.append("<Point>");
sb.append("<altitudeMode>relativeToGround</altitudeMode>");
sb.append("<coordinates>" + local.getLongitude() + "," + local.getLatitude() + "," + 50</coordinates>");
sb.append("</Point>");
sb.append("<Link>");
sb.append("<href>" + local.getFotos() + "</href>");
sb.append("</Link>");
sb.append("</Placemark>");
sb.append("</Document>");
sb.append("</kml>");
return sb.toString();
}
}
}
return null;
}
I have a dwr function in my jsp that invokes this method, got its String results and make the parse like this:
Class PainelEarth()
#SuppressWarnings("static-access")
public String geraFotosObra (int idObra) throws Exception {
try {
List<Obra> obraFotos = obraBusiness.getObraLatLong(new Obra(idObra));
return new KMLGenerator().getKMLFromObra(obraFotos);
} catch (Exception e) {
log.error(e.getLocalizedMessage(), e);
return null;
}
}
and in my jsp page
function initCB(instance) {
// other codes
showPics(ge);
}
function showPics(ge) {
PainelEarthAjax.geraFotosObra({
callback : function(kmlString) {
var kmlObject = ge.parseKml(kmlString);
ge.getFeatures().appendChild(kmlObject);
}
});
return null;
}
Any help will be welcome!!
In your code if you look at the signature of the method geraFotosObra you can see it takes a single int parameter idObra.
public String geraFotosObra (int idObra) throws Exception { ...
Yet when you call the method in your jsp you are passing an an object literal containing a callback function.
PainelEarthAjax.geraFotosObra({
callback : function(kmlString) { ...
As it is I don't see how the kml is generated, unless perhaps geraFotosObra is an overloaded method? Also even if it was generated, as is, I don't see how the callback function that you pass in place of an id is ever called - why for example would kmlString be the result of the call to geraFotosObra?
// How is this called, what sets kmlString!?
callback : function(kmlString) {
var kmlObject = ge.parseKml(kmlString);
ge.getFeatures().appendChild(kmlObject);
}
All in all the code you posted is a wee bit confusing, so sorry if I have missed something...I think you have possibly copy and pasted some code from a fetchKml example and the asynchronous callbacks used with that method have confused you slightly.
Anyhow, based on what you have posted, you should be passing an int id to the geraFotosObra method, getting the string result and then parsing it in the plug-in.
Something like the following makes sense. Replace the showPics function with the following.
function showPics(ge) {
var kmlString = PainelEarthAjax.geraFotosObra(1); // or something?
var kmlObject = ge.parseKml(kmlString);
ge.getFeatures().appendChild(kmlObject);
}

Categories

Resources