How to extract try catch outside method? - java

I have this method sendParameterValueAsMQTTMessage() which I use to publish message via MQTT on a specific topic. I am using try catch two times after another (not nested) but it still seems somewhat ugly and overcrowding the method. I read an article on clean code where Uncle Bob talks about extracting the body of try catch but I seem to not grasp it quite well or at least not in my case.
How could I get rid of the try catch in my method by extracting it outside?
public void sendParameterValueAsMQTTMessage() {
String payload = null;
try {
payload = convertToJSONString("range", String.valueOf(range));
} catch (JSONException e) {
this.logger.log(Level.ERROR, e);
}
MQTTMessage message = new MQTTMessage(MQTTTopics.RANGE_TOPIC,payload,0);
try {
this.client.publish(message);
Thread.sleep(3000);
} catch (Exception e) {
this.logger.log(Level.ERROR, e);
}
}

there are multiple different problems with provided code, here is how I'd refactor it:
public void sendParameterValueAsMQTTMessage() {
final String payload = tryGetPayloadAsJson();
if (payload != null) {
trySendPayloadViaMQTT(payload);
}
}
private String tryGetPayloadAsJson() {
try {
return convertToJSONString("range", String.valueOf(range));
} catch (JSONException e) {
this.logger.log(Level.ERROR, e);
}
return null;
}
private void trySendPayloadViaMQTT(final String payload) {
try {
final MQTTMessage message = new MQTTMessage(MQTTTopics.RANGE_TOPIC, payload, 0);
this.client.publish(message);
Thread.sleep(3000);
} catch (Exception e) {
this.logger.log(Level.ERROR, e);
}
}
one thing which might be improved here based on Uncle Bob's advice is to actually move try/catch outside of trySendPayloadViaMQTT, like this:
public void sendParameterValueAsMQTTMessage() {
final String payload = tryGetPayloadAsJson();
if (payload != null) {
trySendPayloadViaMQTT(payload);
}
}
private String tryGetPayloadAsJson() {
try {
return convertToJSONString("range", String.valueOf(range));
} catch (JSONException e) {
this.logger.log(Level.ERROR, e);
}
return null;
}
private void trySendPayloadViaMQTT(final String payload) {
try {
sendPayloadViaMQTT(payload);
} catch (Exception e) {
this.logger.log(Level.ERROR, e);
}
}
private void sendPayloadViaMQTT(final String payload) {
final MQTTMessage message = new MQTTMessage(MQTTTopics.RANGE_TOPIC, payload, 0);
this.client.publish(message);
Thread.sleep(3000);
}

you can put all of your code in just one try block and set multiple catches, when ever an exception be happened, the catch that is revelated to it will be execute, like:
try{
int a[]=new int[5];
a[5]=30/0;
}
catch(ArithmeticException e)
{
System.out.println("Arithmetic Exception occurs");
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("ArrayIndexOutOfBounds Exception occurs");
}

You can use single general catch for both possible exceptions inside the method as following:
public void sendParameterValueAsMQTTMessage() {
String payload = null;
try {
payload = convertToJSONString("range", String.valueOf(range));
MQTTMessage message = new MQTTMessage(MQTTTopics.RANGE_TOPIC,payload,0);
this.client.publish(message);
Thread.sleep(3000);
} catch (Exception e) {
this.logger.log(Level.ERROR, e);
}
}

public void sendParameterValueAsMQTTMessage() {
String payload = null;
try {
payload = convertToJSONString("range", String.valueOf(range));
} catch (JSONException e) {
this.logger.log(Level.ERROR, e);
}
MQTTMessage message = new MQTTMessage(MQTTTopics.RANGE_TOPIC,payload,0);
publishMessage(message); //extracted in a new method
}
public void publishMessage(MQTTMessage message){
try {
this.client.publish(message);
Thread.sleep(3000);
} catch (Exception e) {
this.logger.log(Level.ERROR, e);
}
}

Related

How do I save the id from chatid with the telegram api

Hello. I'm trying to solve this problem for a while now. For some
reason I keep getting null pointer exception when I try to save a
object in my repository. Below you can see what happens and my
functions.
java.lang.NullPointerException at com.br.einstein.api.service.ApiTelegram.sendMsg(ApiTelegram.java:104)
at
com.br.einstein.api.service.ApiTelegram.onUpdateReceived(ApiTelegram.java:81)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at
org.telegram.telegrambots.meta.generics.LongPollingBot.onUpdatesReceived(LongPollingBot.java:27)
at
org.telegram.telegrambots.updatesreceivers.DefaultBotSession$HandlerThread.run(DefaultBotSession.java:317)
public void onUpdateReceived(Update update) {
ApiEinstein api = new ApiEinstein();
try {
JsonObject objSession = api.getSessionDetails();
String message = update.getMessage().getText();
api.sendChatRequest(objSession);
List < String > list = new ApiEinstein().ReadChatDetails(objSession);
sendMsg(update.getMessage().getChatId().toString(), list.toString());
new ApiEinstein().SendChatMessage(objSession, message);
api.syncChatSession(objSession);
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void sendMsg(String chatId, String s) {
SendMessage sendMessage = new SendMessage();
// sendMessage.enableMarkdown(true);
sendMessage.setChatId(chatId);
sendMessage.setText(s);
long id = Long.valueOf(chatId);
Telegram telegram = new Telegram();
telegram.setChatId(id);
repository.save(telegram);
try {
execute(sendMessage);
} catch (TelegramApiException e) {
e.printStackTrace();
}
} ```

try implement SQLGrammarException into method Java

im trying to implement SQLGrammarException into my method.
This method show me column error, but i need to show what procedure the column with error from.
public static PersistenceMicrodataException dealHibernateException(Throwable e) {
e.printStackTrace();
Throwable t = ExceptionUtil.getCause(e);
return new PersistenceMicrodataException(t.getMessage(), t);
}
I try this:
public static PersistenceMicrodataException dealHibernateException(Throwable e) {
try {
Throwable t = ExceptionUtil.getCause(e);
} catch (Exception e) {
System.out.println(t.getMessage());
System.out.println(((SQLGrammarException) t).getSQLState());
System.out.println(((SQLGrammarException) t).getErrorCode());
System.out.println(t.getCause());
}
return new PersistenceMicrodataException(e.getMessage(), e);
}
Someone can help me with this?
I found solution!
public static PersistenceMicrodataException dealHibernateException(Throwable e) {
String concatError = ((SQLGrammarException) e).getSQL() + ((SQLGrammarException) e).getClass() + ((SQLGrammarException) e).getCause();
while (e != null) {
java.lang.System.out.println(concatError);
break;
}
Throwable t = ExceptionUtil.getCause(e);
return new PersistenceMicrodataException(concatError,t);
}

Non-Static Generic function that invokes a method passed in as a parameter

I'm trying to consolidate 2 methods into 1, because they handle exceptions the same way. I know in C# you can pass functions/actions as parameters into other functions. I tried creating a generic method to invoke a function, but can't seem to figure it out.
public String getTheStuff(String client) {
try {
return extService.getProduct(client);
} catch (UIException e) {
notHealthy();
} catch (HostException e) {
notHealthy();
} catch (Exception e) {
Throwables.propagate(e);
}
}
public CustomType getsomeMoreStuff(String source, int offset) {
try {
return extService.getMetrics(source, offset);
} catch (UIException e) {
notHealthy();
} catch (HostException e) {
notHealthy();
} catch (Exception e) {
Throwables.propagate(e);
}
}
What I'm looking for is something like
public T invokeExtService(Function functionToInvoke, Parameters[] params){
try {
return functionToInvoke.Invoke(params);
} catch (UIException e) {
notHealthy();
} catch (HostException e) {
notHealthy();
} catch (Exception e) {
Throwables.propagate(e);
}
}
As #LouisWasserman said, this would be much nicer in Java 8, but how about something like this (untested):
public <T> T invoke(Callable<T> function) {
try {
return function.call();
} catch (UIException e) {
notHealthy();
} catch (HostException e) {
notHealthy();
} catch (Exception e) {
Throwables.propagate(e);
}
}
public String getTheStuff(final String client) {
return invoke(new Callable<String>() {
#Override
public String call() {
return extService.getProduct(client);
}
});
}
public CustomType getsomeMoreStuff(final String source, final int offset) {
return invoke(new Callable<CustomType>() {
#Override
public CustomType call() {
return extService.getMetrics(source, offset);
}
});
}
To be honest, I'm not sure how worthwhile this is considering how short your methods are (and they could be even shorter with multi-catch).

Copy (over a web API) is complete; I get a broken pipe anyway. How to solve it?

For one of my projects, I implement a Java 7 FileSystem over the Box API Java SDK (the new one).
However, for downloading files, when you want to have a stream to the content, it only provides methods taking OutputStream as an argument; specifically, I am using this one at the moment.
But this doesn't sit well with the JDK API; I need to be able to implement FileSystemProvider#newInputStream()... Therefore I elected to use Pipe{Input,Output}Stream.
Moreover, since the Box SDK API methods are synchronous (not that it matters here), I wrap them in a Future. My code is as follows (imports ommitted for brevity):
#ParametersAreNonnullByDefault
public final class BoxFileInputStream
extends InputStream
{
private final Future<Void> future;
private final PipedInputStream in;
public BoxFileInputStream(final ExecutorService executor,
final BoxFile file)
{
in = new PipedInputStream(16384);
future = executor.submit(new Callable<Void>()
{
#Override
public Void call()
throws IOException
{
try {
file.download(new PipedOutputStream(in));
return null;
} catch (BoxAPIException e) {
throw BoxIOException.wrap(e);
}
}
});
}
#Override
public int read()
throws IOException
{
try {
return in.read();
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public int read(final byte[] b)
throws IOException
{
try {
return in.read(b);
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public int read(final byte[] b, final int off, final int len)
throws IOException
{
try {
return in.read(b, off, len);
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public long skip(final long n)
throws IOException
{
try {
return in.skip(n);
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public int available()
throws IOException
{
try {
return in.available();
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public void close()
throws IOException
{
IOException streamException = null;
IOException futureException = null;
try {
in.close();
} catch (IOException e) {
streamException = e;
}
try {
future.get(5L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
futureException = new BoxIOException("donwload interrupted", e);
} catch (ExecutionException e) {
futureException = new BoxIOException("download failure",
e.getCause());
} catch (CancellationException e) {
futureException = new BoxIOException("download cancelled", e);
} catch (TimeoutException e) {
futureException = new BoxIOException("download timeout", e);
}
if (futureException != null) {
if (streamException != null)
futureException.addSuppressed(streamException);
throw futureException;
}
if (streamException != null)
throw streamException;
}
#Override
public synchronized void mark(final int readlimit)
{
in.mark(readlimit);
}
#Override
public synchronized void reset()
throws IOException
{
try {
in.reset();
} catch (IOException e) {
future.cancel(true);
throw new BoxIOException("download failure", e);
}
}
#Override
public boolean markSupported()
{
return in.markSupported();
}
}
The code consistenly fails with the following stack trace (that is in int read(byte[]):
Exception in thread "main" com.github.fge.filesystem.box.exceptions.BoxIOException: download failure
at com.github.fge.filesystem.box.io.BoxFileInputStream.read(BoxFileInputStream.java:81)
at java.nio.file.Files.copy(Files.java:2735)
at java.nio.file.Files.copy(Files.java:2854)
at java.nio.file.CopyMoveHelper.copyToForeignTarget(CopyMoveHelper.java:126)
at java.nio.file.Files.copy(Files.java:1230)
at Main.main(Main.java:37)
[ IDEA specific stack trace elements follow -- irrelevant]
Caused by: java.io.IOException: Pipe broken
at java.io.PipedInputStream.read(PipedInputStream.java:322)
at java.io.PipedInputStream.read(PipedInputStream.java:378)
at java.io.InputStream.read(InputStream.java:101)
at com.github.fge.filesystem.box.io.BoxFileInputStream.read(BoxFileInputStream.java:78)
... 10 more
But when it fails, the download is already complete...
OK, the thing is, I can grab the file size and hack around it but I'd prefer not to if at all possible; how can I modify this code so as to avoid EPIPE?
The SDK also provides BoxAPIRequest and BoxAPIResponse classes that let you make manual requests for advanced use-cases. These classes still automatically handle authentication, errors, back-off, etc. but give you more granular control over the request.
In your case, you could do make a download request manually by doing:
// Note: this example assumes you already have a BoxAPIConnection.
URL url = new URL("files/" + file.getID() + "/content")
BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
BoxAPIResponse response = request.send();
InputStream bodyStream = response.getBody();
// Use the stream.
response.disconnect();
Well, I found the solution, although I am not very satisfied with it...
Since I can know the file size which I try to open an inputstream on, I just pick the size and decrease it by the amount of bytes read -- unless the size reaches 0, in this case all read methods return -1.

Get detail messages of chained exceptions Java

I'd like to know how I could throw a "final" Exception, containing a detailed message with all the detailed messages of a number of chained exceptions.
For example suppose a code like this:
try {
try {
try {
try {
//Some error here
} catch (Exception e) {
throw new Exception("FIRST EXCEPTION", e);
}
} catch (Exception e) {
throw new Exception("SECOND EXCEPTION", e);
}
} catch (Exception e) {
throw new Exception("THIRD EXCEPTION", e);
}
} catch (Exception e) {
String allMessages = //all the messages
throw new Exception(allMessages, e);
}
I'm not interested in the full stackTrace, but only in the messages, I wrote. I mean, I'd like to have a result like this:
java.lang.Exception: THIRD EXCEPTION + SECOND EXCEPTION + FIRST EXCEPTION
I think what you need is:
public static List<String> getExceptionMessageChain(Throwable throwable) {
List<String> result = new ArrayList<String>();
while (throwable != null) {
result.add(throwable.getMessage());
throwable = throwable.getCause();
}
return result; //["THIRD EXCEPTION", "SECOND EXCEPTION", "FIRST EXCEPTION"]
}
you can better use it this way, merge the message() of previous Exception with the message() of new Exception you are throwing:
} catch (Exception e) {
throw new Exception("FIRST EXCEPTION" + e.getMessage(), e);
}
Cycle through the exception cause and append the message in each exception.
try
{
try
{
try
{
try
{
throw new RuntimeException("Message");
}
catch (Exception e)
{
throw new Exception("FIRST EXCEPTION", e);
}
}
catch (Exception e)
{
throw new Exception("SECOND EXCEPTION", e);
}
}
catch (Exception e)
{
throw new Exception("THIRD EXCEPTION", e);
}
}
catch (Exception e)
{
String message = e.getMessage();
Throwable inner = null;
Throwable root = e;
while ((inner = root.getCause()) != null)
{
message += " " + inner.getMessage();
root = inner;
}
System.out.println(message);
}
Which prints
THIRD EXCEPTION SECOND EXCEPTION FIRST EXCEPTION Message
You can just add the previous exception message on each exception
This is an example :
public static void main(String[] args) {
try {
try {
try {
try {
throw new Exception();
// Some error here
} catch (Exception e) {
throw new Exception("FIRST EXCEPTION", e);
}
} catch (Exception e) {
Exception e2 = new Exception("SECOND EXCEPTION + " + e.getMessage());
throw e2;
}
} catch (Exception e) {
Exception e3 = new Exception("THIRD EXCEPTION + " + e.getMessage());
throw e3;
}
} catch (Exception e) {
System.out.println(e);
}
}
The result is : java.lang.Exception: THIRD EXCEPTION + SECOND EXCEPTION + FIRST EXCEPTION
Here is a nice utility for converting chained exceptions to string:
public final class ThrowableUtil {
private ThrowableUtil() {}
public static String chainedString(#NonNull Throwable throwable) {
StringBuilder SB = new StringBuilder(throwable.toString());
while((throwable = throwable.getCause()) != null)
SB.append("\ncaused by ").append(throwable);
return SB.toString();
}
public static String chainedString(#NonNull String msg, #NonNull Throwable throwable) {
StringBuilder SB = new StringBuilder(msg);
do {
SB.append("\ncaused by ").append(throwable);
} while((throwable = throwable.getCause()) != null);
return SB.toString();
}
}
Example output:
ThrowableUtil.chainedString(e);
produces
java.io.IOException: Failed to create required video encoder
caused by java.lang.RuntimeException: Invalid mime type
Another example output:
ThrowableUtil.chainedString("Writing of media file failed", e);
produces
Writing of media file failed
caused by java.io.IOException: Failed to create required video encoder
caused by java.lang.RuntimeException: Invalid mime type
I had saved all attributes in a class object with the following example:
public List<ErrorMessage> getMessageList(Throwable throwable) {
List<ErrorMessage> errorMessageList = new ArrayList<ErrorMessage>();
while (throwable != null) {
ErrorMessage message = new ErrorMessage();
message.set_message( throwable.getMessage());
message.set_line(throwable.getStackTrace()[0].getLineNumber());
message.set_methodName(throwable.getStackTrace()[0].getMethodName());
message.set_fileName(throwable.getStackTrace()[0].getFileName() );
message.set_className(throwable.getStackTrace()[0].getClassName());
errorMessageList.add(message);
throwable = throwable.getCause();
}
return errorMessageList;
}
Maybe simpler
try {
// code that throws exception
} catch(Throwable e ) {
var messages = new ArrayList<String>();
do {
messages.add(e.getMessage());
e = e.getCause();
} while( e!= null );
var message = String.join(" -> ", messages);
System.out.println(message);
}

Categories

Resources