I want to send a message to notify the user when there is an exception occur in your application. I am wondering what is the best way to do it in Java?
In my program, I have a properties files call mail.properties. I declared some of the properties in this file. I successfully read the properties from my properties file. Now I need to detect an error in my program and send an error message to my email account
mail.properties
smtpServer = smtp.gmail.com
smtpUsername = myemail#gmail.com
smtpPassword = 123456
smtpPort = 465
In my main method, I have declared my properties file. I call this main.java
public class main{
private static String smtpServer;
private static String smtpUsername;
private static String smtpPassword;
private static String smtpPort;
public static void main (String[] args){
//Method for initialize the properties
initialize();
//Code go here (Sending message and stuff)
try{
}
catch(Exception ex)
{
}
}
private static void initialize() throws Exception{
//loadProperties is where I check and get the properties file (no need to worry about it
Properties props = PropertiesUtil.loadProperties("mail.properties");
smtpServer = props.getProperty("smtpServer")
smtpUsername = props.getProperty("smtpUsername")
smtpPassword = props.getProperty("smtpPassword")
smtpPort = props.getProperty("smtpPort")
}
}
The Best Practice is create a RuntimeException, throw that exception upto top of the layer. at the top of the layer pass exception to the utility and send the exception message as email body.
Maybe you want notify error only when they are RuntimeException subclases because they indicate an unexpected error that you are not controlling.
Exception is too spread and you will notify to the user with anything error condition. I suggest you catch RuntimeException and only some checked exceptions.
public class Main {
public static void main(String[] args) {
try {
Job job = new Job();
job.doSomething();
} catch (RuntimeException | MustNotifyException re) {
sendMessage();
}
}
public static void sendMessage() {
}
}
class Job {
void doSomething() throws MustNotifyException {
}
}
class MustNotifyException extends Exception {
}
Related
From a single method trowing two different custom exceptions based on the condition. While creating a custom exception passing two things one is an error message and another one is error code as a string. But I'm unable to get the error based on the error code. getting an error while calling processErrorCodes() method. Could anyone please help me in fixing this.
// BackgroundException is a custom EXCEPTION
public class BackgroundException extends Exception {
private static final long serialVersionUID = 4664456874499611218L;
private String errorCode="Unknown_Exception";
public BackgroundException(String message, String errorCode){
super(message);
this.errorCode=errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
// Similarly I have InvalidException custom exception
public class MyExceptionTest {
public void methodTest(){
String policyId =null;
String policyNotification = null;
String policyStatus = null;
try {
if(policyNotification !=null) {
if(policyStatus!=null) {
if(policyId!=null) {
}
else{
throw new InvalidException("Policy ID Is Null","POLICY_ID");
}
}else{
throw new BackgroundException("Policy Status Is Null","POLICY_STATUS");
}
}
else{
throw new BackgroundException("Policy Notification Is Null","POLICY_NOTIFICATION");
}
} catch (BackgroundException | InvalidException e ) {
// TODO Auto-generated catch block
try {
processErrorCodes(e);
} catch (MyExcep e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.getMessage();
}
}
private static void processErrorCodes(Exception e) throws BackgroundException,InvalidException {
switch(e.getErrorCode()){
case "POLICY_NOTIFICATION":
System.out.println(e.getMessage());
throw e;
case "POLICY_ID":
System.out.println(e.getMessage());
throw e;
case "POLICY_STATUS":
System.out.println(e.getMessage());
throw e;
default:
System.out.println("Unknown exception occured, lets log it for further debugging."+e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
MyExceptionTest mt = new MyExceptionTest();
mt.methodTest();
}
}
I just want to handle those exceptions based on the error code.
You need a common superclass for all your custom exceptions, let say MessageCodeException, extending Exception and the accept this super class type as a parameter inside of your processErrorCodes method
public abstract class MessageCodeException extends Exception {
public abstract String getCode();
// you can have a same abstract method for message
}
public class BackgroundException extends MessageCodeException {
// ...
}
public class InvalidException extends MessageCodeException {
// ...
}
//and now the process method will look like
private static void processErrorCodes(Exception e) throws ... {
// ...
}
That's abvious that for current implementation you cannot access code field, because Exception class interface does not provide anything like this
BTW it seems to be very bad idea to create Exception driven business validation logic. Wouldn't it be better to create some kind of ValidationResult object with list (lists) of errors/warning/successes and to process such validation result at the end? The purpose of the Exception existence is not to control application flow, but to force user to provide some support for critical situations (or to handle somehow unexpected situations with RuntimeException)
I am trying to call the URL retrieving method inside the static block, the Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError.
I am trying to get a WSDL url from the config file. this configuration data stored DB.
static
{
URL url = null;
WebServiceException e = null;
try
{
url = getVertexConfiguration();
} catch (MalformedURLException ex) {
e = new WebServiceException(ex);
}
}
private static URL getVertexConfiguration() throws MalformedURLException
{
try {
configuration = configurationDAO.getByRefName("tax/vertex",
SecureSession.getUser().getDataDomain() != null ?
SecureSession.getUser().getDataDomain() : "app.cantata");
} catch (B2BTransactionFailed b2BTransactionFailed) {
}
Map<String, DynamicAttribute> vertexTaxConfig = configuration.getConfigs();
vertexWsdlUrl = vertexTaxConfig.get("vertexWsdlUrl").getValue().toString();
return new URL(vertexWsdlUrl);
}
}
I am getting static block, the Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError.
The root cause is that static block is the earliest step when setup as class level initialization which even ahead of constructor calling. That is to say your dependency in static block such as that configurationDAO has not initialized yet. You shouldn't use static for it. Instead, you should make it a normal Instance method.
Why should you even try this? I think your configurationDAO is not even initialized at the moment you're trying to access it.
As we discussed in the comments, I would definitely recommend you, author, to inject your dependencies correctly, like:
#Service
public class ConfigurationService {
private final ConfigurationDao configurationDao;
private URL url;
public ConfigurationService(ConfigurationDao configurationDao) {
this.configurationDao = configurationDao;
}
#PostConstruct
private void init() {
// your stuff here
}
}
Or you can even initialize your url in constructor:
#Service
public class ConfigurationService {
private final ConfigurationDao configurationDao;
private final URL url;
public ConfigurationService(ConfigurationDao configurationDao) {
this.configurationDao = configurationDao;
this.url = getVertexConfiguration();
}
private URL getVertexConfiguration() {
// your stuff here
}
}
You get ExceptioninInitializerBlock if there are some errors in the static initializer block. You handle only MalformedURLException, however, there are may be others.
You should add another catch for all exceptions and see what happens there.
static {
URL url = null;
WebServiceException e = null;
try {
url = getVertexConfiguration();
} catch (MalformedURLException ex) {
e = new WebServiceException(ex);
} catch (Exception e) {
//real problem
}
}
That exception is a relaying mechanism for an error which occurred while running a static initializer. The exception should have a cause, which will describe the actual error. Per your description, above, there look to be three layers of exception: Error reporting from bean initialization, the ExceptionInInitializer exception, then the cause of the ExceptionInInitializer exception. The exception processing should display all three layers, but might not, which will make uncovering the base exception more difficult.
From the ExceptionInInitializer javaDoc:
* Signals that an unexpected exception has occurred in a static initializer.
* An <code>ExceptionInInitializerError</code> is thrown to indicate that an
* exception occurred during evaluation of a static initializer or the
* initializer for a static variable.
As a fall-back, you could put inside getVertexConfiguration a try-catch on Throwable, and have the catch block print out the stack:
private static URL getVertexConfiguration() throws MalformedURLException {
try {
// Code omitted
} catch ( Throwable th ) {
th.printStackTrace();
return null;
}
}
I'm designing a Java exception handling mechanism for a 2 component system {front-end, back-end}. The back-end will generate exceptions by using Exception classes for different error conditions. Front-end has to map those exception classes to a customer visible error code. This list of Exception classes can be pretty big and may continue to increase in size. What is the best way to map those Exception classes to customer visible error codes?
I could create a Map<Class, Integer> MAP_EX_CLASS_TO_ERROR_CODE and keep it updated, but is it the right/scalable way to map exceptions?
------- Edits after receiving initial set of answers, see Comments below ----
I want to represent similar types of exceptions, or exceptions that demand similar handling with one exception class. For e.g. UserExceptions can be:
RESOURCE_NAME_TOO_LONG
RESOURCE_NOT_FOUND
RESOURCE_NOT_OWNED
...
and InternalExceptions can be:
SERVER_UNAVAILABLE
REQUEST_TIMEOUT
...
If I make an enum for all these error codes, then is it still useful to implement the grouping? I wanted to do the grouping instead of defining one single class for checked exceptions because it'll force me to pay attention to the catch-ing of exceptions every time I add a new line of code that throws a different checked exception than existing code.
for e.g.
public enum ECodes {
RESOURCE_NAME_TOO_LONG(/*number*/0, UserException.class),
RESOURCE_NOT_FOUND(1, UserException.class),
RESOURCE_NOT_OWNED(2, UserException.class),
SERVER_UNAVAILABLE(3, InternalException.class),
REQUEST_TIMEOUT(4, InternalException.class);
// constructor and stuff
}
public class Prot1ExceptionMapper {
static Map<Ecode, /*CustomerCode*/Integer> MAP_EX_CLASS_TO_ERROR_CODE = new HashMap<>();
static {
MAP_EX_CLASS_TO_ERROR_CODE.add(Ecode.RESOURCE_NAME_TOO_LONG, PROT1_CUSTOMER_CODE1);
// Other mappings here
}
public static Integer map(Ecode ecode) {
// Lookup ecode
}
}
public class Prot2ExceptionMapper {
static Map<Ecode, /*CustomerCode*/Integer> MAP_EX_CLASS_TO_ERROR_CODE = new HashMap<>();
static {
MAP_EX_CLASS_TO_ERROR_CODE.add(Ecode.RESOURCE_NAME_TOO_LONG, PROT2_CUSTOMER_CODE1);
// Other mappings here
}
public static Integer map(Ecode ecode) {
// Lookup ecode
}
}
public class UserException extends Exception {
public UserException(ECodes ecode, String message) {
assert ecode.class == UserException.class;
}
}
public class InternalException extends Exception {
public InternalException(ECodes ecode, String message) {
assert ecode.class == UserException.class;
}
}
class DummyClass {
public void doFirstJob() throws UserException {}
public void doSecondJob() throws InternalException {}
}
class Protocol1MainClass {
public static void main(final String[] args) {
try {
doFirstJob();
doSecondJob();
} catch (UserException e1) {
// Do UserException specific stuff
throw Prot1ExceptionMapper.map(e1);
} catch (InternalException e2) {
// Do InternalException specific stuff
throw Prot1ExceptionMapper.map(e2);
}
My aim is to make a simple chat program. I'm new at RMI. What I've got so far is that the server works. I start it. Then I start the client, it transfers the strings to the server through RMI. But then it doesn't appear on the GUI I made. That's where my problem lies.
My project structure
My StartClient class. I created a chatClient, and put the chatServer stub as parameter.
public StartClient() throws RemoteException, NotBoundException, MalformedURLException {
chatServer = (ChatServer) Naming.lookup("rmi://localhost:1099/chatServer");
}
private void run() throws RemoteException, MalformedURLException, NotBoundException {
ChatClientImpl chatClient1 = new ChatClientImpl(chatServer, "ikke");
new ChatFrame(chatClient1);
ChatClientImpl chatClient2 = new ChatClientImpl(chatServer, "bla");
new ChatFrame(chatClient2);
}
public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {
StartClient start = new StartClient();
start.run();
}
In the ChatClientImpl constructor I use the remote method register.
public ChatClientImpl(ChatServer chatServer, String name) throws MalformedURLException, NotBoundException, RemoteException {
this.chatServer = chatServer;
this.name = name;
chatServer.register(this);
}
Now we're in the ChatServerImpl class, in the REGISTER method. I add the client to an ArrayList of clients. Then I use the method SENT to display the text. It calls the RECEIVE method that each client object has.
public class ChatServerImpl extends UnicastRemoteObject implements ChatServer {
private List<ChatClient> clients;
public ChatServerImpl() throws RemoteException {
this.clients = new ArrayList<ChatClient>();
}
public void register(ChatClientImpl client) throws RemoteException {
clients.add(client);
send("server", client.getName() + " has entered the room");
}
public void unregister(ChatClientImpl client) throws RemoteException {
clients.remove(client);
send("server", client.getName() + " has left the room");
}
public void send(String name, String message) throws RemoteException {
for(ChatClient client : clients) {
client.receive(name + ": " + message);
}
}
}
This is where things go wrong. The textReceiver is ALWAYS null. (textReceiver is attribute/field of the client object.)
public void receive(String message) {
if (textReceiver == null) return;
textReceiver.receive(message);
}
The ArrayList of clients are server-side and all the clients in there all have their textReceivers set on null. If you look back at StartClient there's an important line. The new ChatFrame(chatClient). In the ChatFrame's constructor is where I set the textReceiver.
public ChatFrame(ChatClientImpl chatClient) {
this.chatClient = chatClient;
chatClient.setTextReceiver(this);
String name = chatClient.getName();
setTitle("Chat: " + name);
createComponents(name);
layoutComponents();
addListeners();
setSize(300, 300);
setVisible(true);
}
This project works when I don't use RMI and they're in one package but once I separate them into client-server this problem arose. How do I communicate between them? Server-side I have an (irrelevant?) list of ChatClients that don't influence anything even though the text arrives.
Do I use RMI for every separate ChatClient and make the ChatServer connect with it and send the text like that? Seems very complicated to me. How do I go about this?
EDIT:
ChatClientImpl class
public class ChatClientImpl implements ChatClient, Serializable {
private ChatServer chatServer;
private TextReceiver textReceiver;
private String name;
public ChatClientImpl(ChatServer chatServer, String name) throws MalformedURLException, NotBoundException, RemoteException {
this.chatServer = chatServer;
this.name = name;
chatServer.register(this);
}
public String getName() {
return name;
}
public void send(String message) throws RemoteException {
chatServer.send(name, message);
}
public void receive(String message) {
if (textReceiver == null) return;
textReceiver.receive(message);
}
public void setTextReceiver(TextReceiver textReceiver) {
this.textReceiver = textReceiver;
}
public void unregister() throws RemoteException {
chatServer.unregister(this);
}
}
Your ChatClientImpl class isn't an exported remote object, so it will be serialized to the server, and execute there. And because register() happens during construction, it will be serialized before the setReceiverTextReceiver() method is called. So, the corresponding field will be null. At the server. This is not what you want and it is also not where you want it.
So, make it extend UnicastRemoteObject and implement your ChatClient (presumed) remote interface. If you have problems with doing that, solve them. Don't just mess around with things arbitrarily. And it should not implement Serializable.
NB The signature of register() should be register(ChatClient client). Nothing to do with the ChatClientImpl class. Ditto for unregister().
I'm learning Java RMI so that i'm writing and testing this code, the problem here is that the client (notificationSink class) send a message and register itself with the server but the server (notificationSource class) doesn't do anything.
This is RemoteThingInterface that extends Remote class:
public interface RemoteThingInterface extends Remote{
public void register(NotificationSink sink) throws RemoteException;
public void notifySink(String text) throws RemoteException;
}
This is NotificationSink class:
public class NotificationSink{
private String name;
private static String hostName = "Shine";
private static int serverPort = 2712;
private static String text = (new Date()).toString();
public NotificationSink(String name){
name = this.name;
}
public static void main(String [] args){
RemoteThingInterface rmiserver;
Registry reg;
System.out.println("Sending "+text+" to "+hostName+" through port "+serverPort);
try{
reg = LocateRegistry.getRegistry(hostName, serverPort);
rmiserver = (RemoteThingInterface) reg.lookup("server");
NotificationSink s = new NotificationSink("Eagle 1");
rmiserver.register(s);
rmiserver.notifySink(text);
}catch(RemoteException ex){} catch (NotBoundException ex) {
ex.printStackTrace();
}
}
}
This is NotificationSource class:
public class NotificationSource extends UnicastRemoteObject implements RemoteThingInterface{
private ArrayList sinks = new ArrayList<>();
int port;
Registry registry;
public NotificationSource() throws RemoteException{
try{
port = 2712;
registry = LocateRegistry.createRegistry(port);
registry.rebind("server", this);
}catch(RemoteException ex){
ex.printStackTrace();
}
}
#Override
public void register(NotificationSink sink) {
sinks.add(sink);
}
public ArrayList getSinks(){
return sinks;
}
#Override
public void notifySink(String text){
System.out.println("new sink registered, he is "+getSinks().get(0));
System.out.println(text);
}
public static void main(String [] args){
try{
NotificationSource s = new NotificationSource();
}catch(Exception e){
e.printStackTrace();
}
}
}
Please help to explain where i'm wrong and how to fix this. I tried to add some code to find the size of arraylist in server, it find out successfully, but other methods don't work .... codes are below:
adding this line to remotethinginterface: ArrayList getArray() throws RemoteException;
adding this line to notiSource:
#Override
public ArrayList getArray() throws RemoteException {
return sinks;
}
adding this line to notiSink: System.out.println(rmiserver.getArray().size()); (before rmiserver.register()
the client (notificationSink class) send a message
No it doesn't.
and register itself with the server
No it doesn't.
but the server (notificationSource class) doesn't do anything.
Why should it? There is no client request to do anything with. There can't be. It's impossible.
catch(RemoteException ex){}
The first major problem is here. You are ignoring RemoteException. Don't do that. Log it, print it, never ignore an exception unless you really know what you're doing. In this case you will therefore have ignored the nested NotSerializableException that was thrown when you called register().
The second major problem is that NotificationSink needs to either:
Implement Serializable, if you want it to execute at the server, or
Implement a remote interface and extend UnicastRemoteObject, if you want it to execute at the client.