In my Java project SonarQube says that an expression is always false. However I cannot see why. This is the code in question:
BaseException baseException = null;
for (SpaceInfo i: spaceInfos) {
try {
processSingle(i.getSpaceKey(), i.getContentType());
} catch (BaseException e) {
baseException = BaseException.chain(baseException, e);
}
}
// Here sonar say that this condition will always evaluate to false.
if (baseException != null) {
throw baseException;
}
However in my opinion if the processSingle method throws a BaseException then baseException should not be null and therefore the expression should not evaluate to false.
The processSingle method is declared as follows:
private void processSingle(String spaceKey, String contentType) throws BaseException
And there are definitely cases in which the processSingle method will throw a BaseException. So I think that Sonar is mistaken. Or is there something going on here that I am not seeing?
Update:
This is what BaseException.chain() does:
public static BaseException chain (BaseException a, BaseException b) {
if (a == null) { return b; }
a.setNextException(b);
return a;
}
And this is the code of processSingle:
private void processSingle(String spaceKey, String contentType) throws BaseException {
assert ContentTypes.Page.equals(contentType) || ContentTypes.BlogPost.equals(contentType);
Content content;
try {
content = createEmptyContent(spaceKey, contentType);
} catch (Exception e) {
throw new MessageToContentProcessorProcessSingleException(contentType, spaceKey, e);
}
BaseException baseException = null;
try {
contentCreator.addMetadata(content);
} catch (BaseException e) {
baseException = BaseException.chain(baseException, e);
}
Pair<List<AttachmentInfo>, FailedToSaveAttachmentException> pair = contentCreator.saveAttachments(messageParser.getContent(), content);
List<AttachmentInfo> attachments = pair.getLeft();
baseException = BaseException.chain(baseException, pair.getRight());
try {
String html = htmlGenerator.generateHtml(attachments, messageParser.getContent());
contentCreator.updateBodyOfContent(content, html);
} catch (BaseException e) {
baseException = BaseException.chain(baseException, e);
}
if (baseException != null) {
throw new MessageToContentProcessorProcessSingleException(contentType, spaceKey, baseException);
}
}
Just for testing/curiosity, I would try:
} catch (BaseException e) {
baseException = e;
}
this would show if Sonar thinks the exception can be thrown or not. Or if it is getting confused by the chain method or assignment statement (assigning to basseException but using it (still null) on the right side of assignment).
I know this is changing the logic, just for testing
even try (but I do not believe this would trick Sonar)
} catch (BaseException e) {
var tmp = BaseException.chain(baseException, e);
baseException = tmp;
}
Try changing chain() to help SonarQube:
public static BaseException chain (BaseException a, BaseException b) {
if (a == null) {
return b;
} else {
a.setNextException(b);
return a;
}
}
thinking about it, hardly possible to be the problem - almost trivial that a is not null here
I would try and see if it works:
BaseException baseException;
for (SpaceInfo i: spaceInfos) {
try {
processSingle(i.getSpaceKey(), i.getContentType());
baseException = null;
} catch (BaseException e) {
baseException = BaseException.chain(baseException, e);
}
}
Related
I know it is required that in a non-void method, return or throw is a must.
But I don't like the dummy return in catch block in such case:
public int call() throws Exception {
try {
return calcMethod();
} catch (Exception e) {
process(e);
return 0;
}
}
protected void process(Exception e) throws xxxException {
if ( isTypeAException(e) ) { throw new TypeAException() ; }
else if ( isTypeBException(e) ) { throw new TypeBException() ; }
else ( isTypeCException(e) ) { throw new TypeCException() ; }
}
...
process will certainly throws an exception, then why return is still required in catch block?
In one sense, throwing the exception in process() is to be construed as "a problem with processing", which is also not what you mean.
As you want the exception to be raised by call(), so the solution here is to make process() an exception factory:
public int call() throws Exception {
try {
return calcMethod();
} catch (Exception e) {
throw process(e);
}
}
protected xxxException process(Exception e) throws xxxException {
if (isTypeAException(e))
return new TypeAException();
else if (isTypeBException(e))
return new TypeBException();
else
return new TypeCException();
}
I put a simple retry because the operation can rarely fail. The simplified code is below. The method putObject can accidentally throw an exception, in this case the retry should allow to invoke this method again. Is it possible to write a JUnit test for this?
I know that with Mockito library we can force to throw an Exception invoking a method but how to force this exception to be thrown only once?
public class RetryExample {
Bucket bucket = new Bucket();
static int INTERNAL_EXCEPTION_CODE = 100;
class AException extends RuntimeException {
private static final long serialVersionUID = 1L;
int statusCode;
public int getStatusCode() {
return statusCode;
}
}
class Bucket {
public void putObject(String fileName, byte[] data) throws AException {
System.out.println("PutObject=" + fileName + " data=" + data);
}
}
public void process(String fileName, byte[] data) throws AException {
try {
retryOperation((f, d) -> bucket.putObject(f, d), fileName, data);
} catch (Exception ex) {
throw new AException("Failed to write data", ex);
}
}
private <T, U> void retryOperation(BiConsumer<T, U> biConsumer, T t, U u) {
int retries = 0;
boolean retry = false;
AException lastServiceException = null;
do {
try {
biConsumer.accept(t, u);
} catch (AException e) {
lastServiceException = e;
int statusCode = e.getStatusCode();
if (statusCode == INTERNAL_EXCEPTION_CODE) {
throw e;
} else {
break;
}
}
retries++;
if (retries >= 3) {
retry = false;
}
} while (retry);
if (lastServiceException != null) {
throw lastServiceException;
}
}
Test Class:
public class RetryExampleTest {
...
#Test
public void test() {
RetryExample retryExample = new RetryExample();
String fileName = "TestFile";
byte[] data = simulatedPayload(10000);
try {
retryExample.process(fileName, data);
} catch (Exception e) {
fail("Exception thrown=" + e);
}
}
According to the Mockito documentation you can set different behavior for consecutive method calls.
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");
In case of a void method you can do something similar (Mockito documentation)
doThrow(new RuntimeException())
.doNothing()
.when(mock).doSomething();
I think you can use a global data object to store the times of throw Exceptions, so in the Mockito library invoke the Exception method just taken the global data object to record the times. It would be simple. Just all by your control.
Spring has made it so incredibly easy to set up application properties...but how would you do it without Spring?
I need to deploy a Java / Groovy application to a server where using Spring is out of the question... and I also don't have the liberty to install anything like Redis either. One option I am considering is to set up a Spring Cloud Config Server elsewhere and have my application consume properties from the config server. Trouble is, that is a bit of an overkill for my project now.
Could anyone suggest a way to do this in good, old, plain Java? :)
This is a really simple and basic example, but you can modify it as you like:
PropertyConfigurator.java
public class PropertiesConfigurator
{
Properties properties = new Properties();
String configInputPath = null;
InputStream configInputStream = null;
public PropertiesConfigurator(String configInputPath)
{
this.configInputPath = configInputPath;
}
public PropertiesConfigurator load() throws IOException, PropertyException
{
try
{
this.configInputStream = new FileInputStream(this.configInputPath);
// load a properties file
this.properties.load(this.configInputStream);
validate();
}
catch (IOException ex)
{
System.out.println("Failed load properties file: " + this.configInputPath);
throw ex;
}
catch (PropertyException ex)
{
System.out.println("One or more properties are empty");
throw ex;
}
finally
{
if (this.configInputStream != null)
{
try
{
this.configInputStream.close();
}
catch (IOException ex)
{
System.out.println("Failed to close input stream");
throw ex;
}
}
}
return this;
}
private void validate() throws PropertyException
{
Enumeration<?> e = this.properties.propertyNames();
while (e.hasMoreElements())
{
String key = (String) e.nextElement();
String value = this.properties.getProperty(key);
if (value.isEmpty())
{
System.out.println(String.format("Property %s is empty!", key));
throw new PropertyException("One or more properties are empty");
}
}
}
public String getProperty(String key)
{
return this.properties.getProperty(key);
}
#Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof PropertiesConfigurator))
return false;
PropertiesConfigurator that = (PropertiesConfigurator) o;
if (properties != null ? !properties.equals(that.properties) : that.properties != null)
return false;
if (configInputPath != null ? !configInputPath.equals(that.configInputPath) : that.configInputPath != null)
return false;
return configInputStream != null ?
configInputStream.equals(that.configInputStream) :
that.configInputStream == null;
}
#Override
public int hashCode()
{
int result = properties != null ? properties.hashCode() : 0;
result = 31 * result + (configInputPath != null ? configInputPath.hashCode() : 0);
result = 31 * result + (configInputStream != null ? configInputStream.hashCode() : 0);
return result;
}
}
PropertyException.java
public class PropertyException extends Exception
{
public PropertyException()
{
}
public PropertyException(String message)
{
super(message);
}
public PropertyException(String message, Throwable throwable)
{
super(message, throwable);
}
}
MainRunner.java
public class MainRunner
{
public static void main(String[] args)
{
try
{
String configFilePath = "application.properties";
PropertiesConfigurator propertiesConfigurator = new PropertiesConfigurator(configFilePath).load();
String prop1 = propertiesConfigurator.getProperty("keyprop1");
// Do whatever you want with prop1
// ...
}
catch (PropertyException ex)
{
System.out.println("Failed to load properties");
System.exit(1);
}
catch (Exception ex)
{
System.out.println("Error in main application");
System.exit(1);
}
}
}
Example of application.properties
keyprop1=value1
keyprop2=value2
Again, it's very basic and you should definitely improve this code and add your logic, validation, etc.
Take a look at http://constretto.org. That's easy to use configuration framework.
try
{
if(ruleName.equalsIgnoreCase("RuleName"))
{
cu.accept(new ASTVisitor()
{
public boolean visit(MethodInvocation e)
{
if(rule.getConditions().verify(e, env, parentKeys, astParser, file, cu)) // throws ParseException
matches.add(getLinesPosition(cu, e));
return true;
}
});
}
// ...
}
catch(ParseException e)
{
throw AnotherException();
}
// ...
I need to catch thrown exception in the bottom catch, but I cannot overload method via throws construction. How to do with that, please advice? Thanks
Create custom exception, write try catch block in anonymous class and catch it in your catch block.
class CustomException extends Exception
{
//Parameterless Constructor
public CustomException () {}
//Constructor that accepts a message
public CustomException (String message)
{
super(message);
}
}
now
try
{
if(ruleName.equalsIgnoreCase("RuleName"))
{
cu.accept(new ASTVisitor()
{
try {
public boolean visit(MethodInvocation e)
{
if(rule.getConditions().verify(e, env, parentKeys, astParser, file, cu)) // throws ParseException
matches.add(getLinesPosition(cu, e));
return true;
}
catch(Exception e){
throw new CustomException();
}
});
}
// ...
}
catch(CustomException e)
{
throw AnotherException();
}
As suggested already, an unchecked exception could be used. Another option is to mutate a final variable. Eg:
final AtomicReference<Exception> exceptionRef = new AtomicReference<>();
SomeInterface anonymous = new SomeInterface() {
public void doStuff() {
try {
doSomethingExceptional();
} catch (Exception e) {
exceptionRef.set(e);
}
}
};
anonymous.doStuff();
if (exceptionRef.get() != null) {
throw exceptionRef.get();
}
I'm trying to read a serialized Java file containing instances of classes I don't have in my classpath while reading.
Is there a way (perhaps by writing my own ObjectInputStream?) to ignore those ClassNotFoundException and replace the corresponding object of the stream by null ?
The object I want to read is similar to this one :
public class Log {
private String someField;
private Throwable throwable;
}
Actually, that Log object is read, but I don't have in my classpath the concrete class of some Log.throwable values. I would want that in that case, the throwable field value would be null but I want my Log object with the other fields read.
If I catch the exception, I couldn't even have my Log object.
Actually, I have tried multiple way to do this (extend ObjectInputStream and implement ObjectInputStream.readClassDescriptor() in order to return a Proxy of an ObjectStreamClass which would return null for default method ObjectStreamClass.getResolveException(), using Javassist because JDK cannot proxify classes, but the problem is : ObjectStreamClass cannot be instantiated outside of java.io package).
But I finally found a (rather ugly) way to do this :
public class DecompressibleObjectInputStream extends ObjectInputStream {
private static Logger logger = LoggerFactory.getLogger(DecompressibleObjectInputStream.class);
public DecompressibleObjectInputStream(InputStream in) throws IOException {
super(in);
try {
// activating override on readObject thanks to https://stackoverflow.com/a/3301720/535203
Field enableOverrideField = ObjectInputStream.class.getDeclaredField("enableOverride");
enableOverrideField.setAccessible(true);
Field fieldModifiersField = Field.class.getDeclaredField("modifiers");
fieldModifiersField.setAccessible(true);
fieldModifiersField.setInt(enableOverrideField, enableOverrideField.getModifiers() & ~Modifier.FINAL);
enableOverrideField.set(this, true);
} catch (NoSuchFieldException e) {
warnCantOverride(e);
} catch (SecurityException e) {
warnCantOverride(e);
} catch (IllegalArgumentException e) {
warnCantOverride(e);
} catch (IllegalAccessException e) {
warnCantOverride(e);
}
}
private void warnCantOverride(Exception e) {
logger.warn("Couldn't enable readObject override, won't be able to avoid ClassNotFoundException while reading InputStream", e);
}
#Override
public void defaultReadObject() throws IOException, ClassNotFoundException {
try {
super.defaultReadObject();
} catch (ClassNotFoundException e) {
logger.warn("Potentially Fatal Deserialization Operation.", e);
}
}
#Override
protected Object readObjectOverride() throws IOException, ClassNotFoundException {
// copy of JDK 7 code avoiding the ClassNotFoundException to be thrown :
/*
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
try {
Object obj = readObject0(false);
handles.markDependency(outerHandle, passHandle);
ClassNotFoundException ex = handles.lookupException(passHandle);
if (ex != null) {
throw ex;
}
if (depth == 0) {
vlist.doCallbacks();
}
return obj;
} finally {
passHandle = outerHandle;
if (closed && depth == 0) {
clear();
}
}
*/
try {
int outerHandle = getObjectInputStreamFieldValue("passHandle");
int depth = getObjectInputStreamFieldValue("depth");
try {
Object obj = callObjectInputStreamMethod("readObject0", new Class<?>[] {boolean.class}, false);
Object handles = getObjectInputStreamFieldValue("handles");
Object passHandle = getObjectInputStreamFieldValue("passHandle");
callMethod(handles, "markDependency", new Class<?>[] {int.class, int.class}, outerHandle, passHandle);
ClassNotFoundException ex = callMethod(handles, "lookupException", new Class<?>[] {int.class}, passHandle);
if (ex != null) {
logger.warn("Avoiding exception", ex);
}
if (depth == 0) {
callMethod(getObjectInputStreamFieldValue("vlist"), "doCallbacks", new Class<?>[] {});
}
return obj;
} finally {
getObjectInputStreamField("passHandle").setInt(this, outerHandle);
boolean closed = getObjectInputStreamFieldValue("closed");
if (closed && depth == 0) {
callObjectInputStreamMethod("clear", new Class<?>[] {});
}
}
} catch (NoSuchFieldException e) {
throw createCantMimicReadObject(e);
} catch (SecurityException e) {
throw createCantMimicReadObject(e);
} catch (IllegalArgumentException e) {
throw createCantMimicReadObject(e);
} catch (IllegalAccessException e) {
throw createCantMimicReadObject(e);
} catch (InvocationTargetException e) {
throw createCantMimicReadObject(e);
} catch (NoSuchMethodException e) {
throw createCantMimicReadObject(e);
} catch (Throwable t) {
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
if (t instanceof IOException) {
throw (IOException)t;
}
throw createCantMimicReadObject(t);
}
}
private IllegalStateException createCantMimicReadObject(Throwable t) {
return new IllegalStateException("Can't mimic JDK readObject method", t);
}
#SuppressWarnings("unchecked")
private <T> T getObjectInputStreamFieldValue(String fieldName) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Field declaredField = getObjectInputStreamField(fieldName);
return (T) declaredField.get(this);
}
private Field getObjectInputStreamField(String fieldName) throws NoSuchFieldException {
Field declaredField = ObjectInputStream.class.getDeclaredField(fieldName);
declaredField.setAccessible(true);
return declaredField;
}
#SuppressWarnings("unchecked")
private <T> T callObjectInputStreamMethod(String methodName, Class<?>[] parameterTypes, Object... args) throws Throwable {
Method declaredMethod = ObjectInputStream.class.getDeclaredMethod(methodName, parameterTypes);
declaredMethod.setAccessible(true);
try {
return (T) declaredMethod.invoke(this, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
#SuppressWarnings("unchecked")
private <T> T callMethod(Object object, String methodName, Class<?>[] parameterTypes, Object... args) throws Throwable {
Method declaredMethod = object.getClass().getDeclaredMethod(methodName, parameterTypes);
declaredMethod.setAccessible(true);
try {
return (T) declaredMethod.invoke(object, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
}
Then I overrode the ObjectInputStream.readClassDescriptor() in order to ignore differences between serialVersionUID also (as described in that answer) and I've got an ObjectInputStream which can read nearly everything !
I don't think there is a way to do this ... apart from cloning and modifying the Java serialization implementation.
Certainly, readObject and readResolve hooks won't help, because they rely on methods of the class that you cannot load.