So I am running the debugger and came across a variable 'e' which I think is error. But within that variable e is a variable "detailMessage". What is the code to get that string displayed?
I would like something along these lines
System.out.println("The error is " + e.detailMessage );
e is e MySQLSyntaxErrorException (id=67)
Where e.detailMessage is the string.
Thanks
The method is
e.getMessage();
http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html#getMessage()
From the Java 7 API (http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html) the method you want is getMessage().
System.out.println("The error is " + e.getMessage());
The correct way to show exceptions is by using a Logger, but for simplicity's sake, you should probably use e.printStackTrace(), this shows you the error as well as the stack where it occured. If you really want just the message (which in itself is not usually very useful) use getMessage()
try{
// ... do something ...
} catch (Exception e){
e.printStackTrace();
}
The method you are looking for is getMessage.
In code:
System.out.println("The error is " + e.getMessage());
Related
There are a lot of if-else statements in my code what is the best way that I can avoid so many if-else statements. Below is the code snippet. Now again I need to check if WWW-Authenticate header returns value
signature_invalid
then I need to log and return a different error message and if WWW-Authenticate header returns value
token_exppured
then I need to log a different error message which will again add 2 more ifs. Can anyone Help me how can I avoid this??
if (e.getRawStatusCode() == NOT_FOUND) {
logger.log(
log,
LogLevel.ERROR,
MISSING_VALID_ID_ERROR_MSG + " : " + e.toString(),
viewRequest);
String errorDetails = createNotFoundDetails(appl, transactionId);
updateIdentifier(rcvLog, true, request, identifier);
return createErrorViewResponseReply(MISSING_VALID_ID_ERROR_MSG, errorDetails);
} else if (e.getRawStatusCode() == UNAUTHORIZED) {
logger.log(
log,
LogLevel.ERROR,
UNABLE_TO_REACH_ERROR_MSG + " : " + e.toString(),
viewRequest);
if (e.getResponseHeaders() != null && e.getResponseHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE != null)) {
logger.log(
log,
LogLevel.ERROR,
INVALID_TOKEN_ERROR_MSG + " : " + e.getResponseHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE),
viewRequest);
}
updateIdentifier(rcvLog, false, request, identifier);
return createErrorViewResponseReply(
UNABLE_TO_REACH_ERROR_MSG,
INVALID_TOKEN_ERROR_DETAILS);
}
The basic approaches one can take with this is:
Create a class hierarchy with a factory to instantiate the right instance to respond to the action
Do the same but in short hand with Enums
Use a map of this::method() and call your methods that do the work for you
For your case, since you can't really control the types of code an API sends you, and a factory method may be overkill, a map approach may be best:
map.put(NOT_FOUND, this::methodA);
map.put(UNAUTHORIZED, this::methodB);
map.put(OTHER, this::methodC);
map.computeIfAbsent(
e.getRawStatusCode(),
(e, rc, req, id) -> {/** NOTHING */}
).apply(e, rcvLog, request, identifier);
computeIfAbsent() allows you to handle the unhandled case with basically a no-op.
I am making database of my school's building and classroom with Realm. But, 'for-loop' in try-catch doesn't work:
public void startCheckRealm() {
// Writing DataBase with Realm
try {
Log.d("Realm", "Init");
InitializeAPI.init_BuildingRoom(getActivity().getApplicationContext());
Log.d("Realm", "Complete");
} catch(Exception e) {
e.printStackTrace();
}
// Trying to check the Database whether it is right or wrong
try {
Log.d("Realm Test", "2nd Try Catch");
Realm.init(getActivity().getApplicationContext());
Realm realm = Realm.getDefaultInstance();
RealmResults<BuildingList> buildingLists = realm.where(BuildingList.class).findAllSorted("buildingCode");
int totalNumber = 0;
for(int i = 0; i < buildingLists.size(); i++) {
Log.d("For", "index = " + i);
RealmResults<RoomList> rooms = buildingLists.get(i).getRoomList().sort("roomCode");
String BuildingName = buildingLists.get(i).getBuildingName();
String BuildingCode = buildingLists.get(i).getBuildingCode();
for(int idx = 0; idx < rooms.size(); idx++) {
totalNumber++;
String RoomCode = rooms.get(idx).getRoomCode();
String RoomName = rooms.get(idx).getRoomName();
Log.d("Realm Test", "Number :: " + String.valueOf(totalNumber) + " BuildingCode :: " + BuildingCode + "\t\t BuildingName :: " + BuildingName + "\t\t RoomCode :: " + RoomCode + "\t\t RoomName :: " + RoomName);
}
}
Log.d("Realm Test", "2nd Try Catch Complete + " + String.valueOf(totalNumber));
} catch(RealmException e) {
e.printStackTrace();
}
}
In the first try-catch, the method, which does making database, is complete without Exception. I was curious whether this database is right or wrong.
So, in 2nd try-catch, I was trying to check realm files with queries.
The problem is "for-loop" doesn't work in 2nd try-catch. Below snippet is my logcat.
D/Realm: Init
I/System.out: bdList getLength :: 52
I/System.out: roomList getLength :: 2376
D/Realm: Complete
D/Realm Test: 2nd Try Catch
D/Realm Test: 2nd Try Catch Complete + 0
I want to check my realm data with Log but, doesn't work as you can see.
If there is no problem, the logcat shows lots of my building and room lists and ends with "D/Realm Test: 2nd Try Catch Complete + 2376".
Could you explain the reason why it doesn't work? I cannot understand the reason why it doesn't work even though there is no Exception.
While in your use-case this doesn't pose a problem, when you're iterating a RealmResults inside a transaction, the results are live in every version <= 0.88.3 and >= 3.0.0.
So in that case,
RealmResults<BuildingList> buildingLists = realm.where(BuildingList.class).findAllSorted("buildingCode");
for(int i = 0; i < buildingLists.size(); i++) {
BuildingList buildingList = buildingLists.get(i); // <-- !!!
will fail (it will skip every second item!)
So you should use iterators instead (3.0.0+! on <= 0.88.3 you'd do reverse iteration)
RealmResults<BuildingList> buildingLists = realm.where(BuildingList.class).findAllSorted("buildingCode");
for(BuildingList buildingList : buildingLists) { // <-- !!!
The reason why this works is because iterators by default create a new snapshot collection (3.0.0+), and iterating by index on a snapshot also works
OrderedRealmCollection<BuildingList> snapshot = buildingLists.createSnapshot();
for(int i = 0; i < ...
Simple: there is no exception thrown; and you only have your print statements inside the loop.
Thus the one and only conclusion: at that point in time when your for loops are executed, the corresponding list is empty. Therefore the loop body is not entered; nothing gets printed. And that has nothing to do with the fact that this loop is within a try-catch block.
That is all there is to this. So, the direct answer is: print the list size directly in front of the loop to avoid such surprises.
(of course, the interesting part is to understand what happens to the list which seems to be non-empty earlier on - but in order to debug that, you would have to add more of your code).
Two inputs:
1.Haven't used realm but looks like the syntax for getting sorted entriesis a bit different Official documentation
2.If the above point is wrong than from your code it looks like buildingList size is zero. Have you tried checking the size?
Let me know the results.
Try logging your catch block. Chances are the rest of the code including the loop didn't complete because your app was caught with the Exception.
You should debug buildingLists.size(); before for loop
Log.d("Building List Size ", buildingLists.size()+"");
In that case you can find the value of buildingLists.size();
In case of bulkWrite(), I want array of _ids of successfully processed documents OR failed documents, along with reason for failure.
Following is the attempt I made. Suggest more easy approach if possible.
try {
collection.insertMany(documents, new InsertManyOptions().ordered(false));
} catch (DuplicateKeyException dke) {
LOGGER.error("{}", dke);
} catch (MongoBulkWriteException mbwe) {
List<BulkWriteError> errors = mbwe.getWriteErrors();
for (BulkWriteError error : errors) {
LOGGER.error("{}", error.getMessage());
}
} catch (Exception ex) {
LOGGER.error("{}", ex.getCause());
}
When I insert document with duplicate _ids, I supposed to get DuplicateKeyException as per javadoc, but I am getting MongoBulkWriteException.
I am using java 8 and mongodb 3.2.1 drivers
insertMany throws only the following exceptions:
MongoBulkWriteException - if there's an exception in the bulk write operation
MongoException - if the write failed due some other failure
However the exception carries the cause of it and in the case of a duplicated id will be something like:
insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.restaurants.$_id_ dup key: { : ObjectId('56c8ac3146235e4898bb696c') }
So since you have the information in the message you can extract with a regular expression the ids of the documents that failed in an array.
The code would be something like that (I am giving it inline in your code):
List<String>duplicateIds = new ArrayList<String>();
List<BulkWriteError> errors = mbwe.getWriteErrors();
for (BulkWriteError error : errors) {
LOGGER.error("{}", error.getMessage());
// extract from error.message the id of the duplicated document, (11000 is the duplicate id code)
if (error.getCode() == 11000) {
Matcher m = Pattern.compile("[0-9a-f]{24}")
.matcher(error.getMessage());
m.find();
duplicateIds.add(m.group());
}
}
// here the duplicateIds will hold all the found ids, you can print them in console for example:
System.out.println(duplicateIds.toString());
// and do whatever else you like with them
The above code will catch the duplicated Ids - if you want to make it to catch other errors it is easy to adapt it accordingly.
UPDATE:
If you want to use bulkWrite() you can use exactly the same code since it throws the same exceptions (MongoBulkWrite, MongoException) as insertMany(), see BulkWrite()
If you want to update the code to catch other exceptions it is easily expandable:
see what the specific message and error code is for the exception you want to catch from the logs.
add an if block as the one I gave for that particular error code to extract the ids with a regular expression and add them to the array you have initialized for that kind of error
do your handling in the end
I am having trouble fixing a Log Forging issue in Fortify. The issue, "writes unvalidated user input to the log", is being raised from both of the logging calls in the getLongFromTimestamp() method.
public long getLongFromTimestamp(final String value) {
LOGGER.info("getLongFromTimestamp(" + cleanLogString(value) + ")");
long longVal = 0;
Date tempDate = null;
try {
tempDate = new SimpleDateFormat(FORMAT_YYYYMMDDHHMMSS, Locale.US).parse(value);
} catch (ParseException e) {
LOGGER.warn("Failed to convert to Date: " + cleanLogString(value) + " Exception: " + cleanLogString(e.getMessage()));
throw new Exception(e);
}
if (tempDate != null) {
longVal = tempDate.getTime();
}
return longVal;
}
private cleanLogString(String logString) {
String clean = logString.replaceAll("[^A-Za-z0-9]", "");
if(!logString.equals(clean)) {
clean += " (CLEANED)";
}
return clean;
}
The cleanLogString() method has fixed other Log Forging Fortify issues in my project, however it has no effect on the 2 above.
Any help would be appreciated!
It is possible to use fortify Java annotations to tell Fortify that the data returned from a sanitizing function is now safe.
When looking at my log forging problems I had strings coming in through a web API and thus had the flags XSS and WEB on my strings. I tried to find annotations that would only remove these flags, but couldn't find any way to remove the WEB flag. The only documentation I've found is the Samples/advanced/javaAnnotation directory.
Since my sanitation method does sanitize strings, I choose to remove all flags. This could be a problem though, as it could hide privacy violations.
#FortifyValidate("return")
private String sanitizeString(String taintedString) {
return doSomethingWithTheString(taintedString);
}
Originally when this question was written our team was using log4j v1.2.8, however we noticed that all the log forging issues disappeared after upgrading to log4j v2.6.2.
Once the log4j version is upgraded the Fortify log forging issues should go away. The cleanLogString() method form the question above is also unnecessary. For example:
LOGGER.info("getLongFromTimestamp(" + value + ")");
I know I have run into situations where the complexity of my application would stop any malicious input from working as intended; Fortify does not consider this to be secure. I bet you are running into the same thing.
You are stripping any really useful characters out of the log message, but see what happens if you do some encoding on the output prior to writing to the log.
http://www.jtmelton.com/2010/09/21/preventing-log-forging-in-java/
// ensure no CRLF injection into logs for forging records
String clean = message.replace( '\n', '_' ).replace( '\r', '_' );
if ( ESAPI.securityConfiguration().getLogEncodingRequired() ) {
clean = ESAPI.encoder().encodeForHTML(message);
if (!message.equals(clean)) {
clean += " (Encoded)";
}
}
Use reflect or try-catch.
Its easy to cheat fortify.
while looking for a simple way to display errors I've found SwingX
Currently I'm using
JXErrorPane.showDialog(null, new ErrorInfo("Error", e.getMessage(), null, null, exception, ErrorLevel.SEVERE, null));
which results in the following : http://i.imgur.com/JKeF4.png
I really like the way this looks but I don't want to show the stack trace. I've tried passing null instead of the exception but that way I don't get the details.
Is there any way to just omit the stack trace?
(Like this : http://i.imgur.com/kObaH.png)
If you don't like the auto-built details message (which is built by the BasicErrorPaneUI, have a look at its getDetailsAsHtml), you can pass-in a custom one like:
Exception e = new NullPointerException("something ...");
// copied from BasicErrorPaneUI
StringBuffer html = new StringBuffer("<html>");
html.append("<h2>" + "Error" + "</h2>");
html.append("<HR size='1' noshade>");
html.append("<div></div>");
html.append("<b>Message:</b>");
html.append("<pre>");
html.append(" " + e.toString());
html.append("</pre>");
html.append("<b>Level:</b>");
html.append("<pre>");
html.append(" " + ErrorLevel.SEVERE);
html.append("</pre>");
html.append("</html>");
ErrorInfo errorInfo = new ErrorInfo("Error", e.getMessage(),
html.toString(), null, e, ErrorLevel.SEVERE, null);
JXErrorPane.showDialog(null, errorInfo);
If you want to do that more often, I would suggest a custom ErrorInfo subclass