Activiti`s RuntimeServiceImpl::startProcessInstanceByKey cannot work well in a concurrent environment - java

I've got a very strange question in RuntimeServiceImpl::startProcessInstanceByKey.
The code is like this:
#Override
public String startProcessInstanceByKey(String processDefinitionKey, String businessKey,
String authenticatedUserId, Map < String, Object > variables) throws RiskManageException {
log.info("startProcessInstanceByKey,收到开启工作流 processDefinitionKey:{} ,businessKey:{},authenticatedUserId:{},variables:{}", //This can be printed normally
processDefinitionKey, businessKey, authenticatedUserId, JSON.toJSON(variables));
try {
Assert.notNull(authenticatedUserId, "userCode 不能为空");
Assert.notNull(processDefinitionKey, "流程定义key 不能为空");
processCoreService.getIdentityService().setAuthenticatedUserId(authenticatedUserId);
return processCoreService.getRuntimeService()
.startProcessInstanceByKey(processDefinitionKey, businessKey, variables).getProcessInstanceId(); //This statement didn`t execute
} catch (Exception e) {
throw new RiskManageException(ExceptionCodeEnum.START_PROCESS_ERROR, e); //Here throws an exception but the caller didn`t catch any
}
}
The process instance couldn't be created sometimes in a concurrent environment without any exception. It often happens when JDBC connections are about to use up. I want to know more detailed information, what should I do?

Related

Android unreported exception IOException error

I am new to android apps development. Recently,Im writing an application which able to show public ip based on Ipify. So far, i already:
Download the required jar file and put inside libs folder
I also compile file within gradle
Then i import required class it to my class
How to use Ipify, according to its website:
import org.ipify.Ipify;
public class HelloIP {
public static void main(String[] args) throws IOException {
System.out.println(Ipify.getPublicIp());
}
}
I write the following method to be invoked from another class:
public static String getPublicIp() throws IOException{
String ip = Ipify.getPublicIp();
return ip;
}
Another Class
//Get wifi
getWifiName wifiInfo = new getWifiName();
String myIP = wifiInfo.getPublicIp();
However, i keep getting:
Error:(52, 43) error: unreported exception IOException; must be caught
or declared to be thrown
I tried to modify the code and use the following try and catch, but still got the same error.
public static String getPublicIp() throws IOException{
String myip = Ipify.getPublicIp();
try{
return myip;
}
catch (IOException e){
System.out.println("General I/O exception: " + e.getMessage());
e.printStackTrace();
}
}
Im not too good in catch and throw exception, and already spent the whole day for this.I dont have idea anymore to fix this error..T.T
public static String getPublicIp() {
try{
return Ipify.getPublicIp();
}catch (IOException e){
System.out.println("General I/O exception: " + e.getMessage());
e.printStackTrace();
}
return null;
}
In case it didn't help, clean project in your IDE. You may have some data cached and it might be a reason.
Your problem is in another class! As you have declared the method getPublicIp() to throw IOException that class is afraid of receiving the Exception and therefor requests catching it.
In Java you have two types of Exceptions. Checked and unchecked. Checked Exceptions must be caught.
In Java Exceptions are used for marking unexpected situations. For example parsing non-numeric String to a number (NumberFormatException) or calling a method on a null reference (NullPointerException). You can catch them in many ways.
Unchecked Exceptions are those which extend RunTimeException. They are used for marking unexpected states usually caused by user's input. They shouldn't cause harm and should be worked out with business logic. You don't have to catch them, but sometimes you should.
On the other hand there are Checked Exceptions which mark dangerous situations. For example the application being unable to open a file. As those situations are found dangerous, you must catch them.
try{
//some code
} catch (NumberFormatException e1) {
e.printStackTrace() //very important - handles the Exception but prints the information!
} catch (NullPointerException e2) {
e.printStackTrace();
}
or using the fact, that they all extend Exception:
try {
//somecode
} catch (Exception e) {
e.printStackTrace;
};
or since Java 7:
try {
//somecode
} catch (NullPointerException | NumberFormatException e) {
e.printStackTrace;
};

Testing if custom exception was thrown when a run time exception is thrown using mockito

I have this code where I'm catching some exception and throwing a custom exception instead.
#Override
public void config() throws CustomException{
File jsonFile = new File("config.json");
try {
ConfigMapper config = mapper.readValue(jsonFile, ConfigMapper.class);
try {
this.instanceId = Integer.parseInt(config.getConfig().getClientId());
this.configParams = config.getConfig().getConfigParams();
} catch (NumberFormatException ex) {
throw new CustomException("Please provide a valid integer for instance ID", ex);
//LOGGER.log(Level.SEVERE, "error initializing instanceId. Should be an integer " + e);
}
} catch (IOException ex) {
throw new CustomException("Error trying to read/write", ex);
// LOGGER.log(Level.SEVERE, "IOException while processing the received init config params", e);
}
}
I need to write a unit test for this and below is how I wrote it.
#Test
public void should_throw_exception_when_invalid_integer_is_given_for_instanceID(){
boolean isExceptionThrown = false;
try{
Mockito.doThrow(new NumberFormatException()).when(objectMock).config();
barcodeScannerServiceMock.config();
} catch (CustomException ex) {
isExceptionThrown = true;
}
assertTrue(isExceptionThrown);
}
But its throwing a number format exception and not the CustomException as I want it to be. But this makes sense as I'm using the mock object to throw the exception as a result of which my code logic is not executed. But if that's the case, how do I test this scenario? Please advice.
1.) Remove the line Mockito.doThrow(new NumberFormatException()).when(objectMock).config();
2.) Change the Client-ID in your JSON-File to something that cannot be converted to an Integer.
this.instanceId = Integer.parseInt(config.getConfig().getClientId()); will fail due to that and thus throw an exception.
One advice regarding names: The name of your test method should be what's written in the Java-Doc. Just name it "testCustomException" & explain the methods function in the Java-Documentation. There are Naming-Conventions in Java (click here) which are basically general guidelines.
Practicing these is very helpful as it allows you to quickly get into your code again after not working on it for a month or so due to the increased readability.

JUnit tests: How to check for errors with a try-catch block

So, I need to write a test for some (legacy) code I'm improving. In a method, I try to parse some string (which should be legal JSON). Then a possible JSONException is caught if the string doesn't represents valid JSON. Something like:
public void transformToJSON(String source) {
try {
JSONObject js = new JSONObject(new JSONTokener(item.getHtml()));
}
catch (JSONException e) {
log(e)
}
//than js is added to an Hashset and the method is done
}
So I want to write a test for good input (to see if I have generated a correct JSON-object). This is 'easy' by checking the object in the Set.
For wrong input however, I need to find out if the correct error has been thrown.
I know if an error was thrown in the code, I can check for it in the test.
By setting the rule public ExpectedException thrown=
ExpectedException.none(); and checking for it in test method.
By adding #Test(expected = JSONException.class) above the test
But both wont work for try..catch blocks.
How can I test if the proper exception is caught by catch block? I want to change as little of the source code as possible.
In the JUnit test class you can do is use fail("this should not have happened") in the try or catch block depending on what should and should not work (as in: try and catch in the JUnit class, not in your actual method!).
However, with a try/catch block within your method you cannot see whether an Exception occured or not, because it is handled within the method. So you would have to throw the exception in the method instead of catching it, i.e.,
public void transformToJSON(String source) throws JSONException { ... }
Then it will work to check whether an exception occured or not.
Alternatively you could return a boolean that states whether the transformation was successful or not. Then you can test whether the return value was true/false and if that was what you expected.
public boolean transformToJSON(String source) {
boolean success = true;
try {
JSONObject js = new JSONObject(new JSONTokener(item.getHtml()));
}
catch (JSONException e) {
log(e)
success = false;
}
//than js is added to an Hashset and the method is done
return success;
}
In your test class:
#Test
public void testTransformToJSON() {
assertTrue(transformToJSON("whatever"));
}
Based on the logging being used in the code, you can use Mockito to verify the message logged inside catch block.
Please go through the following link for more details on setting up the unit tests
http://bloodredsun.com/2010/12/09/checking-logging-in-unit-tests/
Your legacy code is swallowing the Exception. If it throws an exception, then your junit #Test ( expected = JSONException.class) would work.
I'd change the code slightly so it is
public void transformToJSON(String source) {
try {
JSONObject js = getJSON(item.getHtml()));
}
catch (JSONException e) {
log(e)
}
//than js is added to an Hashset and the method is done
}
public JSONObject getJSON(String source) throws JSONException {
return new JSONObject(new JSONTokener(source));
}
and then test against getJSON. This throws an exception and as other have said (and you) you can use the expectedException in the test class
use a bad formatted json string, and then do assertions or whatever in the catch block of ur test.
#Test
public void shouldCatchException(){
String source = "{ \"name\":\"John\", \"age\":30, \"car\":null ";
try {
jsonHelper.transformToJSON(source);
}catch (JSONException e){
Assert.assertThat(e, notNullValue());
assertTrue(StringUtils.isNotBlank(e.getMessage());
//whatever else u need to assert
}
}

Using specific try catch, error overrides

This is my Exception:
public class MyException extends Exception {
private String errorCode="Unknown_Exception";
public MyException(String message, String errorCode){
super(message);
this.errorCode=errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
Now immagine the next scenario, the code is way too long to paste here:
1 I got a Presentation class made in Swing in Presentation package
2 In package calculations I made simple operations with few numbers from received database fields
3 In package connections I got the database connections
Trouble comes here:
-In presentation layer I catch all errors, like this:
try {
//here is a method called updateCombo() wich throws:
//throw new MyException(e.getMessage(),"ERROR_UPDATING_COMBO_BOX");
} catch (MyException ex) {
try {
//Here we process error code, if error is not defined, uses default errors.
processCode(ex);
} catch (MyException ex1) {
Logger.getLogger(Presentacion.class.getName()).log(Level.SEVERE, null, ex1);
}
}
processCode is a simple list with cases, like this:
private void processCode(MyException e) throws MyException {
switch (e.getErrorCode()) {
case "ERROR_UPDATING_COMBO_BOX":
lblErrorText.setText("Error updating combo.");
throw e;
case "ERROR_SELECTING_PRIMARY_KEY":
lblErrorText.setText("Error selecting PK");
throw e;
case "ERROR_OPENING_CONNECTION":
lblErrorText.setText("Error opening connection.");
throw e;
default:
lblErrorText.setText("Excepcion not defined: "+ e.getMessage());
e.printStackTrace();
}
This is the scenario, the connection fails in 3rd package and leads to this:
throw new MyException(e.getMessage(),"ERROR_OPENING_CONNECTION");
As I said, the error is thrown to the upper layer with throws clause in method header, this beeing 2nd package.
2nd package also throws a new exception to Presentation, because of failing connection:
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
Presentation methods also throw this exception becase 2nd layer failed:
throw new MyException(e.getMessage(),"ERROR_UPDATING_COMBO_BOX");
The main problem:
Using debug i found out that the program does what it has to do. It gets to the connection layer and does this successfully:
throw new MyException(e.getMessage(),"ERROR_OPENING_CONNECTION");
But, in 2nd layer, calculations, if connection fails it throws a new exception:
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
This is the problem:
throw new
throwing new exception overrides ERROR_OPENING_CONNECTION with ERROR_SELECTING_PRIMARY_KEY. When it gets to presentation due to its "throw new" overrides ERROR_SELECTING_PRIMARY_KEY with ERROR_UPDATING_COMBO_BOX, resulting in the final error shown in the screen:
lblErrorText.setText("Error updating combo.");
Is there any way to return to presentation once first error is caught without overriding by next errors?
Maybe I misunderstood the concept but I want to catch all possible errors because:
-If connection is OK but method in 2nd layer fails it should throw ERROR_SELECTING_PRIMARY_KEY.
-If 2nd layer (calculations) does it OK but there is error in presentation it should lead to ERROR_UPDATING_COMBO_BOX.
You can use e.getCause() which will return a Throwable and check if this cause belongs to MyException. In case it is, you can check the e.getCause() again recursively until you obtain the deepest error code in the stacktrace and perform the validation for this exception.
Here's an example:
public MyException getDeepestException(MyException e) {
Throwable t = e.getCause();
if (t instanceof MyException) {
return getDeepestException((MyException)t);
}
return e;
}
As pointed out by #RealSkeptic, in order to use this approach, you will need to add an additional constructor to your custom exception:
public MyException(String message, Throwable cause, String errorCode){
super(message, cause);
this.errorCode = errorCode;
}
And when throwing your exception, call the proper constructor:
try {
//...
} catch (SomeException e) {
throw new MyException(<a proper message should be here>, e, "ERROR_SELECTING_PRIMARY_KEY");
}
If I understand you correctly, if the exception caught by one package happens to be a MyException, you want the original MyException to be passed up, otherwise (if the exception is some other type of Exception) you want to create a new MyException.
In this case, you should have two catch clauses.
try {
// Whatever you do in the try clause
} catch ( MyException myEx ) {
throw myEx;
} catch ( Exception e ) {
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
}

Logging with NullPointerException? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Log runtime Exceptions in Java using log4j
I am developing a desktop application. I used Log4j to write log. How can I write log with NullPointerException? I didn't predict that could happen.
If you mean just how to print the exception to the log, assuming the configuration is OK:
try {
....something
} catch(RuntimeException e) {
log.error("Got unexpected exception", e);
}
NullPointerException inherits from RuntimeExepction so you can safely catch it and any other runtime ones with the above code.
The above code will NOT catch any exception which is inherit from Exception but not from RuntimeException.
If I understand your question properly, you do not want to put Try catch statements throughout your code to handle NullPointer Exception as it is not expected.
Simple way to handle is to put a null check before using the object reference for any operation. Also , place these null checks only on those objects where you can expect that it might not be initialized due to some other exception or error scenario.
i.e
if (objectReference!=null)
objectReference.CallSomeMethod();
Another example
String listofDefaulters =null;
String defaulters = getDefauter();
/**you might expect that you will always get defaulters from the method call but it might happen dat it can return null value also.
So always put a null check where you are not 100% sure if value will not be null**/
if (defaulters !=null)
defaulters.doSomeOperation();
If you want to do aspect oriented programming, you may want to write an advice around Exception including NullPointerException and perform the logging e.g. below:
#Aspect
public class ExceptionLogging {
private static Logger log = null;
#Pointcut ("call(* *.*(..)))
public void exceptionLogMethods(){
}
#AfterThrowing(pointcut="exceptionLogMethods()", throwing="e")
public void handleException(Throwable ex, JoinPoint jointPoint) {
log = Logger.getLogger(jointPoint.getThis().getClass());
log.debug(jointPoint.getThis().getClass() + ex.getMessage());
}
}
You can use the class Preconditions too in the Guava libraries for customize the exceptions and the messages.
The method Preconditions#checkNotNull(T, java.lang.Object) throws a NullPointerException if the reference T is null.
void method(String name) {
Preconditions.checkNotNull(name, "The name is null.");
// do something with the name
}
void otherMethod() {
try {
method("zerone"); // OK
method(null); // throws NPE
} catch(RuntimeExcetion e) {
LOG.error(e.getMessage(), e); // Message: "The name is null."
}
}

Categories

Resources