Java ternary operator badly evaluating null - java

I had a weird situation today while I was writing tests. Basically, I had a class with data. Let's say Toy for example, from which we can retrieve a name:
public class Toy {
private String name;
public Toy(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
And I had an exception, which was working in a way similar to this (e.g. just displaying data about all the objects on which we were working before it went bad); I also included a main for test purpose:
public class ToyFactoryException extends Exception {
public ToyFactoryException(Toy firstToy, Toy secondToy) {
super("An error occurred when manufacturing: " +
"\nfirstToy: " + firstToy != null ? firstToy.getName() : null +
"\nsecondToy: " + secondToy != null ? secondToy.getName() : null);
}
public static void main(String[] args) {
try {
throw new ToyFactoryException(null, new Toy("hi"));
} catch (ToyFactoryException myException) {
System.out.println("It should be there.");
} catch (Exception exception) {
System.out.println("But it's there instead.");
}
}
}
As I wrote in the first catch block, the exception should be caught in the ToyFactoryException.
However, in the exception, it's trying to read firstToy.getName() right here: firstToy != null ? firstToy.getName() : null
firstToy != null should evaluate to false, which means it shouldn't be trying to call firstToy.getName() in the first place. When you write it in the reverse order:
public ToyFactoryException(Toy firstToy, Toy secondToy) {
super("An error occurred when manufacturing: " +
"\nfirstToy: " + firstToy != null ? null : firstToy.getName() +
"\nsecondToy: " + secondToy != null ? secondToy.getName() : null);
}
You realise it reads null instead now, which means it's truly reading firstToy != null as true.
If you write the main this way instead (the null is the second parameter of the constructor):
public static void main(String[] args) {
try {
throw new ToyFactoryException(new Toy("hi"), null);
} catch (ToyFactoryException myException) {
System.out.println("It should be there.");
} catch (Exception exception) {
System.out.println("But it's there instead.");
}
}
It works properly, despite the secondToy ternary condition being written the same way as the firstToy ternary.
Why is the ternary condition on firstToy not evaluating null properly?

You should put parentheses around your conditional expression.
This:
"string " + firstToy != null ? firstToy.getName() : null
means this:
("string " + firstToy) != null ? firstToy.getName() : null
You need this:
"string " + (firstToy != null ? firstToy.getName() : null)

Related

Spring Boot: #Transactional rollbackFor checked Exception

I am trying to achieve transactional rollback when i will get checked exception from "invokeProcedureForLead" method(code mentioned below). I have tried multliple ways and some reference still
it is not working for me .
For more understanding please find below code
#Transactional(rollbackFor = Exception.class)
public LeadResponseDTO processDataInDB(LMCRAResponseData lmcraResponse,
Boolean crnPresentFlag, Map<Integer, Integer> craProcData,
Map<Integer, Integer> crnProcData,LeadResponseDTO leadResponseDTO,LMCRARequestData lmcraRequestData) throws CRAProcessDBException,SQLException, CRAProcessClientException {
try{
leadResponseDTO = extractDecision(lmcraResponse,crnPresentFlag);
decisionEngineResponseDao.invokeProceduresForLead(craProcData, crnProcData, lmcraResponse);
}catch(Exception e){
log.error("error in invokeProcCalls", e);
if (masterErrorCodes.getErrorDTO("6006") != null)
logException(lmcraResponse, masterErrorCodes.getErrorDTO("6006"));
leadResponseDTO=new LeadResponseDTO();
getLeadResponseDTO(lmcraRequestData,leadResponseDTO,e.getMessage());
}
return leadResponseDTO;
}
public void invokeProceduresForLead(Map<Integer, Integer> craProcData,
Map<Integer, Integer> crnProcData, LMCRAResponseData lmcraResponseData) throws Exception {
int noCRNFlag = 0;
String commonLogs = CommonUtil.printDECommonLogs(lmcraResponseData);
if (lmcraResponseData.isBureauMatch() && crnProcData.isEmpty())
noCRNFlag = 1;
if (lmcraResponseData.isBureauMatch()
&& invokeProcLeads(craProcData, DBConstants.CALL_PROC_PROCESS_CRA_DATA_LEAD,
Integer.parseInt(lmcraResponseData.getCaseID())) != null) {
log.info("invokeProcLeads for Cra block - 1 for runId {} " , commonLogs);
throw new CRAProcessDBException("error in invokeProcCalls for CRA");
}
if (crnProcData != null
&& !crnProcData.isEmpty()
&& invokeProcLeads(crnProcData, DBConstants.CALL_PROC_PROCESS_CRN_DATA_LEAD,
Integer.parseInt(lmcraResponseData.getCaseID())) != null) {
log.info("invokeProcLeads for crn block - 2 for runId {} " , commonLogs);
throw new CRAProcessDBException("error in invokeProcCalls for CRN");
}
if (((crnProcData == null || crnProcData.isEmpty()) || !lmcraResponseData.isBureauMatch())
&& invokeNoCrnForLeads(DBConstants.CALL_PROC_PROCESS_NO_CRN_DATA_LEAD,
Integer.parseInt(lmcraResponseData.getCaseID()), noCRNFlag) != null) {
log.info("invokeNoCrnForLeads block - 3 for runId {} " , commonLogs);
throw new CRAProcessDBException("error in invokeProcCalls for NOCRN");
}
I think the code needs to change like this -
log.error("error in invokeProcCalls", e);
if (masterErrorCodes.getErrorDTO("6006") != null)
logException(lmcraResponse, masterErrorCodes.getErrorDTO("6006"));
leadResponseDTO=new LeadResponseDTO(); getLeadResponseDTO(lmcraRequestData,leadResponseDTO,e.getMessage());
}
throw e;
Note that **throw e; ** line added..
The problem is you are throwing an exception from internal call, but then swallowing it in outer method. So the exception is never thrown from outer method, which results in no rollback happening.

My Custom Exception is not thrown, instead the ArrayOutOfBoundsException Is thrown (JunitTest Error)

i have a Problem with my Custom Exception, i want to throw a Custom Exception when the entered row/col does not excist in my shelf[][] which only kind of works. The custom exception does get thrown when i compile my main (error message is printed)- even though the throw part in my Code is apparently never reached (https://i.stack.imgur.com/1OY52.png) - but it also throws the ArrayIndexOutOfBoundsException. So when i Junit test my method for throwing InvalidRow/ColumnException it fails because it throws the ArrayOutOfBoundsException.
How do i solve this problem so my Junit test assertThrows(InvalidRowException.class,() -> shelf.addItem(3, 0, bottle)); doesnt catch the ArrayIndexOutOfBoundsException but instead only my InvalidRowException?
This is my Exception Class:
public class InvalidRowException extends ArrayIndexOutOfBoundsException {
public InvalidRowException(int wrongRow){
super("passed Row " + wrongRow + " doesnt excist.");
}
}
This is my Method
public void addItem(int row, int coll, Product product) throws InvalidRowException, InvalidColumnException {
if (row < 0 | row > shelf.length)
throw new InvalidRowException(row);
if (coll < 0 | coll > shelf[1].length)
throw new InvalidColumnException(coll);
try {
if (!(product instanceof Placeable)) {
throw new ProductNotPlaceableException(product);
} else if (shelf[row][coll] != null) {
System.out.println("Replacing product with serial " + shelf[row][coll].getSerialNumber()
+ " by product with serial " + product.getSerialNumber());
shelf[row][coll] = product;
} else {
shelf[row][coll] = product;
}
} catch (ProductNotPlaceableException e) {
System.out.println(e.getMessage());
}
}
You throw exception for
row > shelf.length
You should check for row > shelf.length -1 as arrays are 0 based
Similarly for coll the correct check is coll> shelf[row].length-1

Java continue statement not allowed in anonymous inner class

I am threading a time consuming for-loop and executing them inside N number of threads. A continue statement is throwing error
Getting the error "Continue cannot be used outside of a loop"
for (final Message m : messagelistholder.getMessage()) {
Callable<Void> tasksToExecute = new Callable<Void>() {
public Void call() {
if (guidanceonly1 == true && !QuoteUtil.isECPQuote(list.get(0))) {
String msg = "Message From " + m.getSource() + " when retrieving Guidance values: "
+ m.getDescription();
String lcladdStatusMessages = CommonUtil.getLoclizedMsg(
"PRCE_LNE_ITM_MSG_FRM_WHN_RETRVNG_GUIDNCE_VAL",
new String[]{m.getSource(), m.getDescription()}, msg);
list.get(0).addStatusMessages("Info", lcladdStatusMessages);
} else if ("Error".equalsIgnoreCase(m.getSeverity())) {
if (m.getCode().indexOf("_NF") > 0) {
continue; // price not found due to private sku
}
if ("Eclipse".equalsIgnoreCase(m.getSource())) {
String msg1 = "Please check Sold To customer data. ";
String lcladdStatusMessages1 = CommonUtil
.getLoclizedMsg("PRCE_LNE_ITM_PLS_CHK_SLDTO_CUST_DTA", null, msg1);
String msg2 = "Discount information may not be returned from Optimus due to "
+ m.getSeverity() + " From " + m.getSource() + " " + m.getDescription();
String lcladdStatusMessages2 = CommonUtil.getLoclizedMsg(
"PRCE_LNE_ITM_DSCNT_INFO_MNT_RTRND_FRM_OPTMS_DUETO_FRM",
new String[]{m.getSeverity(), m.getSource(), m.getDescription()}, msg2);
list.get(0).addStatusMessages(m.getSeverity(),
(m.getDescription().contains("MDCP") ? lcladdStatusMessages1 : "")
+ lcladdStatusMessages2);
} else {
if (response1.getItems() == null) {
String lcladdStatusMessages = CommonUtil.getLoclizedMsg("PRCE_LNE_ITM_OPTMS_ERR",
new String[]{m.getSource(), m.getDescription()}, m.getDescription());
list.get(0).addStatusMessages("Error", lcladdStatusMessages);
list.get(0).setOptimusError(true);
} else {
if (!QuoteUtil.isECPQuote(list.get(0))) {
String lcladdStatusMessages = CommonUtil.getLoclizedMsg(
"PRCE_LNE_ITM_MSG_FRM_WHN_RETRVNG_GUIDNCE_VAL",
new String[]{m.getSource(), m.getDescription()},
"Message From " + m.getSource() + " " + m.getDescription());
list.get(0).addStatusMessages("Info", lcladdStatusMessages);
list.get(0).setOptimusError(true);
}
}
}
}
if (list.get(0).getFlags().get(QtFlagType.ESCALATIONFORPARTNER) != null) {
list.get(0).getFlags().get(QtFlagType.ESCALATIONFORPARTNER).setFlgVl(null);
}
if (m.getCode() != null) {
String pricingServiceMsgCode = m.getCode();
String pricingServiceSeverity = m.getSeverity();
Map<Integer, AutoEscalationScenario> categoryMap;
if (StringUtils.equals("ERROR", pricingServiceSeverity)) {
categoryMap = getScenario("SEVERITY", globalAccount1, null, true, null);
if (categoryMap.size() != 0) {
finalCategorylist.get(0).putAll(categoryMap);
}
}
if (partnerExclusivityAutoEscalation1) {
categoryMap = getScenario(pricingServiceMsgCode, globalAccount1, null, true, null);
if (categoryMap != null && categoryMap.size() != 0) {
finalCategorylist.get(0).putAll(categoryMap);
}
}
}
return null;
}
};
runnableTasks.add(tasksToExecute);
}
Can someone help me to skip the particular loop for the speicified condition but without using continue statement since it throws error.
What's happening is that you are actually calling continue outside of a loop because the call() function itself does not have a for loop, so it doesn't matter if are only calling call() from a loop.
What can you do to fix this is making the call function to return a boolean and replacing the continues with return true and return false if no return true has been reached.
Then replace the:
call()
on the loop(s) for
if(call()) continue
So the I'm not saying I fully understand you code, but it appears that you are using continue to break out of that thread. On a normal multi-threaded application, it looks like you are launching multiple threads from one one loop. The continue call is inside the new thread, not the loop. As soon as you start writing the call() method, you leave the loop to run it. Looking at the code, I would try replacing continue with return. Normally I would try running it myself before I suggest it, but without the rest of the code I cannot verify that it works.

java - verify input validity using assert-like methods

I have a tokenizer, and I need to extract each token, and write it to an output file. The tokens must exist in some logical order (according to a language grammar). Thus, I must also validate that the tokens order follows the grammar specification.
Currently, I'm doing that by using assert-like methods that throw exceptions with appropriate messages.
Here is the code:
public void compileVarDec() throws IOException, IllegalSyntaxException {
output.write("<varDec>\n");
verifyStaticField();
output.write("<keyword> " + tokenizer.keyWord() + " </keyword>\n");
tokenizer.advance();
verifyLegalType();
output.write("<keyword> " + tokenizer.keyWord() + " </keyword>\n");
tokenizer.advance();
verifyIdentifier();
output.write("<identifier> " + tokenizer.identifier() + " </identifier>\n");
tokenizer.advance();
verifySymbol(JackTokenizer.SEMI_COLON);
output.write("<symbol> " + tokenizer.symbol() + " </symbol>\n");
tokenizer.advance();
output.write("</varDec>\n");
}
private void verifySymbol(char token) throws IllegalSyntaxException {
if (tokenizer.tokenType() != JackTokenizer.TOKEN_TYPE.SYMBOL ||
tokenizer.symbol() != token)
throw new IllegalSyntaxException("Expected the symbol '" + token + "'");
}
private void verifyStaticField() throws IllegalSyntaxException {
if (tokenizer.tokenType() != JackTokenizer.TOKEN_TYPE.KEYWORD ||
(!tokenizer.keyWord().equals(JackTokenizer.FIELD) &&
!tokenizer.keyWord().equals(JackTokenizer.STATIC))) {
throw new IllegalSyntaxException("Expected 'static' or 'field'");
}
}
private void verifyLegalType() throws IllegalSyntaxException {
if (tokenizer.tokenType() != JackTokenizer.TOKEN_TYPE.KEYWORD ||
(!tokenizer.keyWord().equals(JackTokenizer.INT) &&
!tokenizer.keyWord().equals(JackTokenizer.CHAR) &&
!tokenizer.keyWord().equals(JackTokenizer.BOOLEAN)))
throw new IllegalSyntaxException("Expected a legal type");
}
private void verifyIdentifier() throws IllegalSyntaxException {
if (tokenizer.tokenType() != JackTokenizer.TOKEN_TYPE.IDENTIFIER)
throw new IllegalSyntaxException("Expected an identifier");
}
Is it considered good practice to validate input that way? To call a method that would check the input, then, if it's invalid, will throw an exception, and the current method will just ignore the thrown exception and pass it on?
If you have other suggestions I'll be glad to hear. Note, I want to avoid running over the tokens twice, so I have to validate the input and write the output simultaneously

Condition Error

i am trying to have a check on that if value is null then don't show the message and recall the constructor, i did the following way but its not working.
if (title == null) {
JOptionPane.showMessageDialog(null, "Please Enter All Values");
new InfoFrame();
}
else {
try {
System.out.println(title+""+date);
System.out.println(title+""+date);
s.execute("INSERT INTO task ([title],[deadline],[priority],[time]) VALUES ('"+ title+ "','"+ date+ "','"+ priority + "','"+ time + "')");
JOptionPane.showMessageDialog(null,"Your Task has been added to the Database:");
} catch (Exception e) {
System.out.println(e.getMessage());
}
*Edited the var Title like stupid naming conventions
if (Title.isEmpty()) {
Will do the trick.
If you want to check both null or empty
if (Title == null || Title.isEmpty()) {
Also its better to start your variable in simple letters.

Categories

Resources