From time to time I come across a class where a bigger part of code are logging calls.
e.g.
public init(Config config) {
logger.info("Configuring ...");
if (config.hasInitInterval()) {
initInterval = config.getInitInterval();
logger.info("Set initInterval to " + initInterval);
}
...
try {
logger.info("Updating access points " + config.getAccessPoints());
updateAccessPoints(config.getAccessPoints())
} catch (Throwable e) {
logger.warn("Init failed due to ", e);
}
...
if (logger.isDebugEnabled ()) {
for(int i = 0; i < config.getModifiers().size(); i++) {
try {
isValidModifier(config.getModifiers().get(i));
} catch (Exception e) {
throw new IllegalArgumentException ("Wrong modifier: " config.getModifiers().get(i));
}
}
}
}
When a class is not formatted well plus contains comments, it's hard to read the code.
I used proxy pattern to partially improve it but it's suitable only to log something before or after a call of method.
What are the best practices to separate functionality from logging?
Related
I have this variable in my Constants class:
public static final String EXCEPTION_STRING= "My Exceptions message";
I want to check for it in my catch and throw a particular message if it's found. This is what I came up with:
} catch (Exception e) {
if (e.getMessage().equals(Constants.EXCEPTION_STRING)) {
throw new ServiceException(MyClassName.class.toString(),
Constants.EXCEPTION_STRING);
} else {
LOGGER.info("Save failed: " + e);
}
}
The if never seems to get entered even though I can see the correct exception message. What am I doing wrong?
Does your own custom exception get wrapped in another exception? In that case you need to do something like:
e.getCause().getMessage()
This is what I did:
} catch (Exception e) {
if (e instanceof AxisFault) {
if (e.getMessage().equals(Constants.EXCEPTION_STRING)) {
throw new ServiceException(MyClassName.class.toString(),
Constants.EXCEPTION_STRING);
}
} else {
LOGGER.info("Save failed: " + e);
}
}
I do have method:
#TransactionTimeout(value = 1, unit = TimeUnit.SECONDS)
#Asynchronous
public void asyncMethod() {
System.out.println("start running asyncMethod in thread " + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finished running asyncMethod in thread " + Thread.currentThread().getName());
}
As you can see I running this in Transaction and timeout is set to 1 second and inside I have 3 second sleep. So as a result of running this method I am gettin:
javax.transaction.RollbackException
But let say I would like to implement service which will print information that transaction timeout has occured to the user. How could I achieve that?
#Glains gave me some advice in comment to use Interceptor.
I have added something like that:
#Interceptor
public class LoggingTimeoutInterceptor {
#AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
try {
System.out.println("Logger interceptor");
System.out.println("method " + ctx.getMethod().getName());
return ctx.proceed();
}catch (RollbackException e) {
System.out.println("Transaction RollbackException occured");
return null;
}
catch (Exception e) {
System.out.println("Exception occured");
return null;
}
}
}
This code is writing first two sysout correctly. But is not catching any exception and I dont know why. I was trying to change #AroundInvoke to #AroundTimeout but then it is not running at all.
I have multiple threads(runnables) in my program. On of theme is handling RS232 communication.
My problem is that code inside the loop is not executed in the order that is written:
while(!serialData.dataToSend.isEmpty())
{
try {
SerialMsgToSend msgObject = serialData.dataToSend.remove();
if(msgObject.type == msgObject.HOLDING_REGISTER)
{
Thread.sleep(COMMAND_WAIT_TIME);
Toolkit.getDefaultToolkit().beep();
modBusManager.singleRegisterWriteToMultipleRegisters(msgObject.unit, msgObject.startRegisterAdress, msgObject.data);
}
else if(msgObject.type == msgObject.COIL)
{
Thread.sleep(COMMAND_WAIT_TIME);
Toolkit.getDefaultToolkit().beep();
modBusManager.writeToCoil(msgObject.unit, msgObject.startRegisterAdress, msgObject.data[0] == 1);
}
Thread.sleep(5000);
readUnitsData(msgObject.unit);
Thread.sleep(5000);
if(msgObject.RESPONSE > 0)
{
serialData.listeners[msgObject.unit - 1].sendResponseToServer(msgObject.RESPONSE);
}
} catch (Exception ex) {
log.error("Exception on sending data: " + ex.toString());
}
}
First I write to ModBus register with calling:
modBusManager.singleRegisterWriteToMultipleRegisters(msgObject.unit, msgObject.startRegisterAdress, msgObject.data);
After that I want to wait 5 seconds that registers are updated, then read them and send information to server.
I read the data with calling method:
readUnitsData(msgObject.unit);
And then I am using listener to tell another thread to send data to server:
serialData.listeners[msgObject.unit - 1].sendResponseToServer(msgObject.RESPONSE);
My problem is that data is sent to server before it gets read/updated so I send old data. I am used that code is executed in the order that is written. Am I using threads in a wrong way or what could be the problem?
Here is method which I call to read data:
private void readUnitsData(int unitID)
{
if(mtxData.climatList[unitID] != null)
{
try
{
log.info("Serial reading data for: " + unitID);
int[] coils = modBusManager.readCoils(unitID + 1,0,87);
String[] holding = modBusManager.readHoldingRegisters(unitID + 1,0,64); //(int slaveAdress, int registerAdress, int registerQuntaity)
if(coils != null && holding != null)
{
System.out.println("send to listner: " + unitID);
serialData.listeners[unitID].newHoldingAndCoilData(holding, coils);
}
} catch (Exception ex)
{
log.error("Exception on run: " + ex.toString());
}
}
}
And method inside other runnable, which is connected to listener:
#Override
public void sendResponseToServer(int responseType)
{
try
{
log.info("listener for sendStatusToServer called: " + responseType);
Thread.sleep(15000);
switch(responseType)
{
case 1:
communicationManager.sendStatus();
break;
case 2:
communicationManager.sendSettings();
break;
}
}catch(Exception ex)
{
log.error("Exception on sendResponseToServer: " + ex);
}
}
I did like #Markus Mitterauer proposed and took apart the code. I found that that it was problem with one of the unitID's which was wrong. Because of that I didn't get any values when reading registers and listener wasn't triggered correctly.
I have a very curious situation.
I'm trying to execute EJB's method and returns the result with JAX-RS
public Service readSingle(...) {
try {
service.query(...);
} catch (final NoResultException nre) {
throw new NotFoundException(...);
} catch (final NonUniqueResultException nure) {
throw new BadRequstException(...);
}
}
The query method requires some values and a BiFuction and a Function.
The actual call looks like this.
try {
return serviceService.<Service>query(
id,
ofNullable(matrixParameters.getFirst("onid"))
.map(Integer::parseInt).orElse(null),
ofNullable(matrixParameters.getFirst("tsid"))
.map(Integer::parseInt).orElse(null),
ofNullable(matrixParameters.getFirst("sid"))
.map(Integer::parseInt).orElse(null),
ofNullable(matrixParameters.getFirst("number"))
.map(Integer::parseInt).orElse(null),
ofNullable(matrixParameters.getFirst("programId"))
.orElse(null),
operatorId,
(builder, root) -> emptyList(),
TypedQuery::getSingleResult);
} catch (final NoResultException nre) {
throw new NotFoundException(
"no entity idnetified by " + serviceIdSegment.getPath()
+ " with " + matrixParameters.toString());
} catch (final NonUniqueResultException nure) {
throw new BadRequestException("multiple entities identified");
}
Ok I passed TypedQuery::getSingleResult and I expect NonUniqueResultException should be caught when it has to be thrown.
But Payara keep responding with 500 and the log shows that the NonUniqueResultException has never caught by the code.
I disabled my ExceptionMappers the the results are same.
Ok. I figured it out. I had to do this.
try {
// execute EJB
} catch (final EJBTransactionRolledbackException ejbtre) {
Exception leaf = ejbtre;
try {
for (Exception c;
(c = ((EJBException) leaf).getCausedByException()) != null;
leaf = c);
} catch (final ClassCastException cce) {
}
logger.severe("causedByException: " + leaf);
if (leaf instanceof NoResultException) {
throw new NotFoundException(
"no entity idnetified by " + serviceIdSegment.getPath()
+ " with " + matrixParameters.toString());
} else if (leaf instanceof NonUniqueResultException) {
throw new BadRequestException(
"multiple entities identified by "
+ serviceIdSegment.getPath()
+ " with " + matrixParameters.toString());
}
throw new InternalServerErrorException(ejbtre);
}
This is far nasty beyond I've expected. The EJB's method design is not good.
Is there any way to do this more simply?
Let me introduce one of my utility class I used to justify myself.
public final class EJBExceptions {
private static final Logger logger
= getLogger(EJBExceptions.class.getName());
public static Stream<Exception> causedByExceptions(EJBException ejbe) {
final Stream.Builder<Exception> builder = Stream.builder();
while (ejbe != null) {
final Exception causedByException = ejbe.getCausedByException();
if (causedByException != null) {
builder.add(causedByException);
} else {
break;
}
if (causedByException instanceof EJBException) {
ejbe = (EJBException) causedByException;
} else {
break;
}
}
return builder.build();
}
public static Optional<Exception> lastCausedByException(
final EJBException ejbe) {
return causedByExceptions(ejbe).reduce((first, second) -> second);
}
private EJBExceptions() {
super();
}
}
I initially started programming in college and learnt vb.net. Now I have decided to make the move to Java and have some queries. In vb, the try catch statement is laid out as follows
try
Catch ex as exception
finally
End catch
but from the java website (https://docs.oracle.com/javase/tutorial/essential/exceptions/putItTogether.html)
i found that in java you use two catches like so:
try {
} catch (ExceptionType name) {
} catch (ExceptionType name) {
}
i was hoping someone could explain why you need two catches in java and what do the respective catches do/catch.
Thanks.
In Java, you can use multiple catch blocks.
It doesn't necessarily means you have to.
It depends on the code your have in the try block, and how many checked Exceptions it may potentially throw (or even unchecked Exceptions if you really want to catch that, typically you don't and you don't have to).
One bad practice is to use a single handler for general Exception (or worse, Throwable, which would also catch RuntimeExceptions and Errors):
try {
// stuff that throws multiple exceptions
}
// bad
catch (Exception e) {
// TODO
}
The good practice is to catch all potentially thrown checked Exceptions.
If some of them are related in terms of inheritance, always catch the child classes first (i.e. the more specific Exceptions), lest your code won't compile:
try {
// stuff that throws FileNotFoundException AND IOException
}
// good: FileNotFoundException is a child class of IOException - both checked
catch (FileNotFoundException fnfe) {
// TODO
}
catch (IOException ioe) {
// TODO
}
Also take a look at Java 7's multi-catch blocks, where unrelated Exceptions can be caught all at once with a | separator between each Exception type:
try (optionally with resources) {
// stuff that throws FileNotFoundException and MyOwnCheckedException
}
// below exceptions are unrelated
catch (FileNotFoundException | MyOwnCheckedException e) {
// TODO
}
Note
In this example you linked to, the first code snippet below Putting it all together may arguably be considered as sub-optimal: it does catch the potentially thrown Exceptions, but one of them is an IndexOutOfBoundsException, which is a RuntimeException (unchecked) and should not be handled in theory.
Instead, the SIZE variable (or likely constant) should be replaced by a reference to the size of the List being iterated, i.e. list.size(), in order to prevent IndexOutOfBoundsException from being thrown.
I guess in this case it's just to provide an example though.
The code that is on the page that is in link i have modified it with single exception. Problem here is that in this case you will not able to know that exception is where whether due to
IndexOutOfBoundsException or IOException
just you know that a exception occurs
import java.io.*;
import java.util.List;
import java.util.ArrayList;
public class ListOfNumbers {
public static void main(String... s) {
ListOfNumbers lon = new ListOfNumbers();
lon.writeList();
}
private List<Integer> list;
private static final int SIZE = 10;
public ListOfNumbers() {
list = new ArrayList<Integer>(SIZE);
for (int i = 0; i < SIZE; i++) {
list.add(new Integer(i));
}
}
public void writeList() {
PrintWriter out = null;
try {
System.out.println("Entering" + " try statement");
out = new PrintWriter(new FileWriter("e://OutFile.txt"));
for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = " + list.get(i));
}
} catch (Exception e) {
System.err.println("Caught Exception: " + e.getMessage());
} finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close();
} else {
System.out.println("PrintWriter not open");
}
}
}
}
Let us understand the concept it is better to know why the code fails due to which particular type of exception whether
IndexOutOfBoundsException or IOException
Now The Code with handling of different Exception
import java.io.*;
import java.util.List;
import java.util.ArrayList;
public class ListOfNumbers {
public static void main(String... s) {
ListOfNumbers lon = new ListOfNumbers();
lon.writeList();
}
private List<Integer> list;
private static final int SIZE = 10;
public ListOfNumbers() {
list = new ArrayList<Integer>(SIZE);
for (int i = 0; i < SIZE; i++) {
list.add(new Integer(i));
}
}
public void writeList() {
PrintWriter out = null;
try {
System.out.println("Entering" + " try statement");
out = new PrintWriter(new FileWriter("e://OutFile.txt"));
for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = " + list.get(i));
}
} catch (IndexOutOfBoundsException e) {
System.err.println("Caught IndexOutOfBoundsException: " +
e.getMessage());
} catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
} finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close();
} else {
System.out.println("PrintWriter not open");
}
}
}
}
Here we could come to know that whether it fails due to creation of file at location
e://OutFile.txt
drive Not on my system
error printed as
Caught Exception: e:\OutFile.txt (The system cannot find the path
specified) Entering try statement PrintWriter not open
Next Case
Now when i comment the line
list.add(new Integer(i));
import java.io.*;
import java.util.List;
import java.util.ArrayList;
public class ListOfNumbers {
public static void main(String... s) {
ListOfNumbers lon = new ListOfNumbers();
lon.writeList();
}
private List<Integer> list;
private static final int SIZE = 10;
public ListOfNumbers() {
list = new ArrayList<Integer>(SIZE);
for (int i = 0; i < SIZE; i++) {
// list.add(new Integer(i));
}
}
public void writeList() {
PrintWriter out = null;
try {
System.out.println("Entering" + " try statement");
out = new PrintWriter(new FileWriter("OutFile.txt"));
for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = " + list.get(i));
}
} catch (IndexOutOfBoundsException e) {
System.err.println("Caught IndexOutOfBoundsException: " +
e.getMessage());
} catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
} finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close();
} else {
System.out.println("PrintWriter not open");
}
}
}
}
then it clearly says that it fails for index out of bound exception
Entering try statement Caught IndexOutOfBoundsException: Index: 0,
Size: 0 Closing PrintWriter
So for the purpose of debugging the application properly and efficiently it is good.
I have created condition for the other type of exception
NoClassDefFoundError
java.lang.NoClassDefFoundError: ListOfNumbers
Caused by: java.lang.ClassNotFoundException: stackprac.ListOfNumbers
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Exception in thread "main" Process exited with exit code 1.