Ehcache - Not fetching value from Cache

1.4k views Asked by At

I was looking for some examples of using ehcache with dao(I do not use any framework, its custom jdbc dao) I have bunch of dao's which I need to cache since their values do not change very often.

I get data as a list in dao, how do I put that data in cache and retrieve it ? Where do we normally put the cache class is it in DAO implementation class or in controller class ? I would like to make a call to db only when item is not found in cache so I quess dao class would be best for it.Appreciate some thoughts on this.

Ok I have some playground code with ehcache,but for some reasons it never goes into cache layer to fetch value.

Here is my dao code and I know it get values from db.

public class GetCitiesbyStateCode {

    private static final Logger logger = LogManager.getLogger(GetCitiesbyStateCode.class);
    private Connection dbConnection = null;
    ResultSet rs;

    public GetCitiesbyStateCode() throws SQLException {

        try {
            dbConnection = CreateConnection.getConnection();
        } catch (Exception e) {
            logger.error("Error getting DB Connection" + e);
        }

    }
//SELECT Distinct(city) FROM `cities_extended` WHERE state_code='AL' 

    public List<BnGetCitiesbyStateCodeBn> GetCitiesbyStateCode(String state_code) throws SQLException {
        List<BnGetCitiesbyStateCodeBn> citiesDAO = new LinkedList<>();
        if (dbConnection != null) {
            Statement stmt = dbConnection.createStatement();
            try {
                logger.info("state code in dao class is " + state_code);
                try {
                    rs = stmt.executeQuery("select Distinct city,state_code from cities_extended WHERE state_code ='" + state_code + "'");
                } catch (SQLException ex) {
                    logger.error("SQL Exception executing query" + ex);
                }
                while (rs.next()) {
                    BnGetCitiesbyStateCodeBn city = new BnGetCitiesbyStateCodeBn();
                    city.setCity(rs.getString("city"));
                    city.setState_code(rs.getString("state_code"));                                   
                    citiesDAO.add(city);
                  }
            } catch (SQLException | IllegalArgumentException | IllegalStateException e) {
                logger.error("Error retreving Cities " + e);
            }                 
     }
        return citiesDAO;

    }

}

This is my cache service layer,(this code never gets value from cache, every call goes to db, so I need someone to take a look at this class),

I am retrieving close to about 1000 cities with this code from db and ehcache xml looks something like below,

 <cache name="citiesCache"  maxEntriesLocalHeap="1000" eternal="true"  memoryStoreEvictionPolicy="FIFO"> </cache>

public class CitiesServicesEhCache {

private static final Logger logger = LogManager.getLogger(CitiesServicesEhCache.class);

public List<BnGetCitiesbyStateCodeBn> getcities(String state_code) throws Exception {
    logger.info("State Code from request at Cache service is " + state_code);
    List<BnGetCitiesbyStateCodeBn> CacheCities = new LinkedList<>();
//    BnGetCitiesbyStateCodeBn CacheCities = null;
    Cache cache = EhCacheManager.getCache();
    Element element = cache.get(CacheCities);
    if (element == null) {
        logger.info("Missed the Cache");
        GetCitiesbyStateCode citiesDao = new GetCitiesbyStateCode();
        try {
            CacheCities = citiesDao.GetCitiesbyStateCode(state_code);
        } catch (SQLException ex) {
            logger.error("Got the SQL Exception" + ex);
        }
        try {
            cache.put(new Element(CacheCities,CacheCities));
        } catch (IllegalArgumentException | IllegalStateException | CacheException ex) {
            logger.error("Failed to put object in cache" + ex);
        }
    } else {
        logger.info("I hit Cache layer");
        CacheCities =  (List<BnGetCitiesbyStateCodeBn>) element.getObjectValue();
    }

    return CacheCities;
}

}

This is my action class for Struts 2. Actually this code is for me to get started on getting cache on my app, so its more playground for testing my codes before I actually implement it on my app.

public class S2 extends ActionSupport {

    private static final long serialVersionUID = 5686197289029560661L;
    private static final Logger logger = LogManager.getLogger(S2.class);
    private String state_code;
    private String t;
    private List <BnGetCitiesbyStateCodeBn> cities;

//    private static final String EHCACHE_CONFIG = "src/main/resources/ehcache.xml";
//    private static final String CACHE_NAME = "citiesCache";
//    CacheManager manager = new CacheManager(EHCACHE_CONFIG);
//    Ehcache cache = manager.getCache(CACHE_NAME);

    public S2() {

    }

    /**
     * @param state_code the state_code to set
     */
    public void setState_code(String state_code) {
        this.state_code = state_code;
    }

    /**
     * @return the t
     */
    public String getT() {
        return t;
    }

    /**
     * @param t the t to set
     */
    public void setT(String t) {
        this.t = t;
    }

       /**
     * @return the state_code
     */
    public String getState_code() {
        logger.info("State code is " + state_code);
        return state_code;
    }

    @Override
    public String execute() {
//        try {
//            GetCitiesbyStateCode citydao = new GetCitiesbyStateCode();
//            cities = citydao.GetCitiesbyStateCode(state_code);
//        } catch (SQLException ex) {
//            logger.error(ex);
//        }
        CitiesServicesEhCache service = new CitiesServicesEhCache();
        try {
            cities = service.getcities(state_code);
        } catch (Exception e) {
            logger.error("Got the Exception" + e);
        }       
        return "success";
    }

    /**
     * @return the cities
     */
    public Object getCities() {
        return cities;
    }

    /**
     * @param cities the cities to set
     */
    public void setCities(Object cities) {
        this.cities = (List<BnGetCitiesbyStateCodeBn>) cities;
    }



}

This is my model/entity class,

public class BnGetCitiesbyStateCodeBn implements Serializable {
    private String city;
    private String state_code;


    /**
     * @return the city
     */
    public String getCity() {
        return city;
    }

    /**
     * @param city the city to set
     */
    public void setCity(String city) {
        this.city = city;
    }

    /**
     * @return the state_code
     */
    public String getState_code() {
        return state_code;
    }

    /**
     * @param state_code the state_code to set
     */
    public void setState_code(String state_code) {
        this.state_code = state_code;
    }
   @Override
    public String toString() {
        return "BnGetCitiesbyStateCodeBn [city=" + city + ", state_code=" + state_code + "]";
    }

}

Here is code which I use to check cache stats and I can see that it add data to cache,but unfortunately it adds twice rather than one time, so I need to some eyes to see what's wrong with my put operation,why is it adding twice and not doing gets from cache even once.Anyone please.

@WebServlet(name = "GetCacheStats", urlPatterns = {"/GetCacheStats"})
public class GetCacheStats extends HttpServlet {

    Cache cache = EhCacheManager.getCache();
    SampledCache sampledCache;

    public GetCacheStats() throws NotCompliantMBeanException {
        this.sampledCache = new SampledCache(cache);
    }

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet GetCacheStats</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1> Size of Cache: " + cache.getSize() + "</h1>");
            out.println("<h1> Cache Status: " + cache.getStatus() + "</h1>");
            out.println("<h1> Name of cache is " + cache.getName() + "</h1>");
            out.println("<h1> Guid of cache: " + cache.getGuid() + "</h1>");
            out.println("<h1> Cache put count is : " + sampledCache.getPutCount() + "</h1>");
            out.println("<h1> Cache missed count is: " + sampledCache.getCacheMissCount() + "</h1>");
            out.println("<h1> Cache Hit count is: " + sampledCache.getCacheHitCount() + "</h1>");
//            out.println("<h1> getMemoryStoreEvictionPolicy()  at " +   cache.getKeysNoDuplicateCheck() + "</h1>");
//            out.println("<h1> getKeysWithExpiryCheck()  at " +   cache.getKeysWithExpiryCheck() + "</h1>");
            out.println("<h1> GetKeys : " + cache.getKeys() + "</h1>");

            out.println("</body>");
            out.println("</html>");
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Servlet to get Ehcache Cache Stats";
    }// </editor-fold>

}
2

There are 2 answers

1
Mr_Thorynque On

In the DAO

public class GetCitiesbyStateCode {

private static final Logger logger =        LogManager.getLogger(GetCitiesbyStateCode.class);
private Connection dbConnection = null;
ResultSet rs;

Cache cache ; public GetCitiesbyStateCode() throws SQLException {

    try {
        dbConnection = CreateConnection.getConnection();
        cache = EhCacheManager.getCache("citiesCache");

    } catch (Exception e) {
        logger.error("Error getting DB Connection" + e);
    }

}

//SELECT Distinct(city) FROM cities_extended WHERE state_code='AL'

public List<BnGetCitiesbyStateCodeBn> GetCitiesbyStateCode(String state_code) throws SQLException {
    //check cache first
    Element el = cache.get(state_code);
    if (el != null){
       return el.getObjectValue();
    }
    List<BnGetCitiesbyStateCodeBn> citiesDAO = new LinkedList<>();
    if (dbConnection != null) {
        Statement stmt = dbConnection.createStatement();
        try {
            logger.info("state code in dao class is " + state_code);
            try {
                rs = stmt.executeQuery("select Distinct city,state_code from cities_extended WHERE state_code ='" + state_code + "'");
            } catch (SQLException ex) {
                logger.error("SQL Exception executing query" + ex);
            }
            while (rs.next()) {
                BnGetCitiesbyStateCodeBn city = new BnGetCitiesbyStateCodeBn();
                city.setCity(rs.getString("city"));
                city.setState_code(rs.getString("state_code"));                                   
                citiesDAO.add(city);
              }
        } catch (SQLException | IllegalArgumentException | IllegalStateException e) {
            logger.error("Error retreving Cities " + e);
        }                 
 }
  cache.set(state_code,citiesDAO);
    return citiesDAO;

}

}

Manage exception and that's all

0
Vikas Deshmukh On

Just add "implements Serializable" to0 the the custom class in which you are storing the data, if you are not getting data using the get method on the cache.