0

Im using Jdbctemplate and trying to set a boolean value inside the mapRow method. But it doesnt allow, It says

Cannot refer to a non-final variable isEveryTransactionNotClosed inside an inner class defined in a different method

Here is my code

public boolean isEveryTransactionNotClosed (String txIds) throws QiibException {
    String sql = "<Query> ";
    logger.info("isEveryTransactionNotClosed SQL :"+sql);
    boolean isEveryTransactionNotClosed = true;
    try {
        isEveryDealNotClosed =  getJdbcTemplate().queryForObject(sql, new Object[] {dealIds}, 
                new RowMapper<Boolean>()  {
                public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException {
                    if (!rs.next()) {
                        isEveryTransactionNotClosed = false;    -->                         
                    }
                }
        });
    } catch(EmptyResultDataAccessException e) {
        logger.error("Empty result data - isEveryTransactionNotClosed ");   
    }
   return isEveryTransactionNotClosed ;
}

How can I use isEveryTransactionNotClosed inside class?

Yakhoob
  • 559
  • 1
  • 12
  • 32
  • by calling it? can you show how you try to call it now? don't give your variables the same names as your methods. declare your variable as final and try again – Stultuske Oct 23 '17 at 07:16
  • @Stultuske, I'm calling the method as boolean result = isEveryTransactionNotClosed (String dealIds); – Yakhoob Oct 23 '17 at 07:22
  • there are some issues in your code. check the answer I just posted, and try again. – Stultuske Oct 23 '17 at 07:24
  • Check this answer https://stackoverflow.com/questions/29029849/why-do-java-8-lambdas-allow-access-to-non-final-class-variables – Shettyh Oct 23 '17 at 07:25
  • You can't access a local variable into an inner class if that local is not final (or since java 8 effectively final) – AxelH Oct 23 '17 at 07:28
  • A fast way to do it is change the type of your `boolean isEveryTransactionNotClosed` to `final AtomicBoolean isEveryTransactionNotClosed` – Alex Oct 23 '17 at 07:45
  • @Alex, can you please explain with the example – Yakhoob Oct 23 '17 at 07:47

3 Answers3

1

There are some issues with your code:

    public boolean isEveryTransactionNotClosed (String txIds) throws QiibException {
        String sql = "<Query> ";
        logger.info("isEveryTransactionNotClosed SQL :"+sql);
        try {
            final boolean isEveryDealNotClosed =  getJdbcTemplate().queryForObject(sql, new Object[] {dealIds}, 
                    new RowMapper<Boolean>()  {
                    public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException {
                        if (!rs.next()) {
                            isEveryTransactionNotClosed = false;    -->                         
                        }
                    }
            });
        } catch(EmptyResultDataAccessException e) {
            logger.error("Empty result data - isEveryTransactionNotClosed ");   
        }
       return isEveryTransactionNotClosed ;
    }

would solve the issue you have now, which would give two new issues:

 1. You would try to re-assign a final variable
 2. Your method has a return value Boolean, but doesn't return anything.

Change your code to:

public boolean isEveryTransactionNotClosed (String txIds) throws QiibException {
    String sql = "<Query> ";
    logger.info("isEveryTransactionNotClosed SQL :"+sql);
    boolean isEveryDealNotClosed = true;
    try {
        isEveryDealNotClosed =  getJdbcTemplate().queryForObject(sql, new Object[] {dealIds}, 
                new RowMapper<Boolean>()  {
                public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException {
                    return rs.next();
                }
        });
    } catch(EmptyResultDataAccessException e) {
        logger.error("Empty result data - isEveryTransactionNotClosed ");   
    }
   return isEveryDealNotClosed;
}
Stultuske
  • 9,296
  • 1
  • 25
  • 37
1

The solution of Stultuske is correct. But it is not explaining the reason of the error.

The short answer is that you can't use a non-final local variable in an inner-class. It can be effectivly final (so it doesn't really need the keyword).

From the JLS - 8.1.3. Inner Classes and Enclosing Instances

Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final.

Explaining your problem.

It is not final and definitly not effectivly final since your inner class alter the local variable.

Another solutions :

  • Inner class are allowed to access and modify member variables,
  • Use wrapper to create the final instance olding your value
AxelH
  • 14,325
  • 2
  • 25
  • 55
  • 1
    I think you miss a part in your post: "It is not final and definitly not effectivly final since your inner class the variable" (I assume you mean re-assigns or changes)? – Stultuske Oct 23 '17 at 07:46
  • @Stultuske indeed, didn't review that line... thanks. – AxelH Oct 23 '17 at 07:48
1

You may use AtomicBoolean in place of boolean if you need a final changeable boolean. See below for the changes on your code.

However, there is some other errors in your code, as stated by others. You may need to change it as well in order to make it work.

public boolean isEveryTransactionNotClosed (String txIds) throws QiibException {
    String sql = "<Query> ";
    logger.info("isEveryTransactionNotClosed SQL :"+sql);
    // changed line
    final AtomicBoolean isEveryTransactionNotClosed = new AtomicBoolean(true);
    try {
        isEveryDealNotClosed =  getJdbcTemplate().queryForObject(sql, new Object[] {dealIds}, 
                new RowMapper<Boolean>()  {
                public Boolean mapRow(ResultSet rs, int rowNum) throws SQLException {
                    if (!rs.next()) {
                        // changed line
                        isEveryTransactionNotClosed.set(false);                         
                    }
                }
        });
    } catch(EmptyResultDataAccessException e) {
        logger.error("Empty result data - isEveryTransactionNotClosed ");   
    }
   return isEveryTransactionNotClosed.get();
}
Alex
  • 803
  • 4
  • 9
  • but you are still using isEveryDealNotClosed (inside try, first statement). That should be isEveryTransactionNotClosed , right – Yakhoob Oct 23 '17 at 08:08
  • I just copied your code and change the lines to illustrate how to use `AtomicBoolean` in inner class. There are still other errors, like the one stated by others that your method `mapRow` has to return a `Boolean`, has to be changed. – Alex Oct 23 '17 at 08:11