1

I am implementing cache system in maven project.I am not using spring or any framework.The concept is to :

 1.At first user will hit the API and Check whether the data is available in cache or not.
 2.If cache is empty ,call the database and put values in cache and send them back.
 3.If cache is not empty, then return the values from cache.

So,for proper organization,I used the Java caching System(JCS) library,which I took reference from:

https://www.javaworld.com/article/2077936/open-source-java-projects-java-caching-system.html

So,I need to have cache.ccf file which will have all configuration for cache memory.

The logic I used in my service class is.This method will be called from API call:

 public List<Album> getAllMusic() {
        try
             {
             Properties props = new Properties();
            props.load(new FileInputStream("src/main/resources/log4j.properties"));
            PropertyConfigurator.configure(props); 

       List<Album> albumList = (List) cache.get("musicCache");
     System.out.println("Size of album is"+albumList.size());
        if(albumList!=null) {
            System.out.println("Returning data from cache");
          return albumList;
           }
     } catch(Exception e ){

             try{
                 System.out.println("Putting data in cache");
                 musicDao.putIncache();
             }
             catch(Exception ef){

             }
             return musicDao.getAllTopHundredMusic();
     }

        return null;

    }

At,first I will check the cache using:

List<Album> albumList = (List) cache.get("musicCache");

and in the first instance it will be always empty,so I will call the DAO layer and also put the datas in the cache in same time which is:

System.out.println("Putting data in cache");
                 musicDao.putIncache();

So,the data gets loaded in the cache,but again when i hit the URL,the cache is still null and it again hits the DAO layer(as in 2nd time hit,it needs to get data from cache not from DAO).I try to check my cache size,but its always empty.When i put the data in cache,its being added in cache but when I try to retrieve it,it is always empty. The logic to put all the data in cache is in DAO layer is:

public void putIncache() {
        try {


            CompositeCacheManager ccm = CompositeCacheManager.getUnconfiguredInstance();
            Properties props = new Properties();

            props.put("jcs.default","DC");
            props.put("jcs.default.cacheattributes",
                    "org.apache.jcs.engine.CompositeCacheAttributes");
// lots more props.put - this is basically the contents of cache.ccf
            Logger log
                    = Logger.getLogger(MusicDao.class);

            ccm.configure(props);

            // Load the cache
            cache = JCS.getInstance("musicCache");


            int i=0;
            for(Album a:albumList){
                cache.put(new Integer(i+1), a);

            }


        } catch (CacheException e) {
            System.out.println("here");
            e.printStackTrace();
        }
    }

I am putting my full codes now: my model class is:

package com.ashwin.cacheapp.model;

import java.io.Serializable;

public class Album implements Serializable {
    private Integer id;
    private String artist;
    private String title;

    public Album() {
    }

    public Album( Integer id, String artist, String title ) {
        this.id = id;
        this.artist = artist;
        this.title = title;
    }

    public Integer getId() {
        return id;
    }

    public void setId( Integer id ) {
        this.id = id;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist( String artist ) {
        this.artist = artist;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle( String title ) {
        this.title = title;
    }

    public String toString() {
        return artist + ": " + title;
    }
}

The APi call happens through this class:

package com.ashwin.cacheapp;

import com.ashwin.cacheapp.model.Album;
import com.ashwin.cacheapp.response.ResponseGen;
import com.ashwin.cacheapp.service.MusicService;

import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PUT;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("hello")
@RequestScoped
public class ApiResource {

    MusicService musicService=new MusicService();


    @GET
    @Path("getAllMusic")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Album> getAllMusic() {
        List<Album> albumList=musicService.getAllMusic();

        return musicService.getAllMusic();

    }


}

MusicService.java

package com.ashwin.cacheapp.service;

import com.ashwin.cacheapp.dao.MusicDao;
import com.ashwin.cacheapp.model.Album;

import org.apache.jcs.JCS;

import java.util.List;

import org.apache.log4j.PropertyConfigurator;

import java.io.FileInputStream;
import java.util.Properties;

//@Stateless
public class MusicService {

    private MusicDao musicDao=new MusicDao();
  private JCS cache;


    public List<Album> getAllMusic() {
        try
             {
             Properties props = new Properties();
            props.load(new FileInputStream("src/main/resources/log4j.properties"));
            PropertyConfigurator.configure(props); 

       List<Album> albumList = (List) cache.get("musicCache");
     System.out.println("Size of album is"+albumList.size());
        if(albumList!=null) {
            System.out.println("Returning data from cache");
          return albumList;
           }
     } catch(Exception e ){

             try{
                 System.out.println("Putting data in cache");
                 musicDao.putIncache();
             }
             catch(Exception ef){

             }
             return musicDao.getAllTopHundredMusic();
     }

        return null;

    }
}

The Dao Class is:(I am using dummy datas)

package com.ashwin.cacheapp.dao;


import com.ashwin.cacheapp.model.Album;
import org.apache.jcs.JCS;
import org.apache.jcs.access.exception.CacheException;
import org.apache.jcs.engine.control.CompositeCacheManager;
import org.apache.log4j.Logger;

import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;


public class MusicDao {
  private List<Album> albumList=new ArrayList<Album>();
    private JCS cache;

    public List<Album> getAllMusic() {
           return null;

    }

    public List<Album> getAllTopHundredMusic() {


        albumList.add(new Album(1, "Toby Mac", "Diverse City"));
        albumList.add(new Album(2, "Toby Mac", "Diverse City"));
        albumList.add(new Album(3, "Toby Mac", "Diverse City"));
        albumList.add(new Album(4, "Toby Mac", "Diverse City"));
        albumList.add(new Album(5, "Toby Mac", "Diverse City"));
        albumList.add(new Album(6, "Toby Mac", "Diverse City"));
        albumList.add(new Album(7, "Toby Mac", "Diverse City"));
        albumList.add(new Album(8, "Toby Mac", "Diverse City"));
        albumList.add(new Album(9, "Toby Mac", "Diverse City"));
        albumList.add(new Album(10, "Toby Mac", "Diverse City"));
        albumList.add(new Album(11, "Toby Mac", "Diverse City"));
        albumList.add(new Album(12, "Toby Mac", "Diverse City"));
        albumList.add(new Album(13, "Toby Mac", "Diverse City"));
        albumList.add(new Album(14, "Toby Mac", "Diverse City"));
        albumList.add(new Album(15, "Toby Mac", "Diverse City"));
        albumList.add(new Album(16, "Toby Mac", "Diverse City"));
        albumList.add(new Album(17, "Toby Mac", "Diverse City"));
        albumList.add(new Album(18, "Toby Mac", "Diverse City"));
        albumList.add(new Album(19, "Toby Mac", "Diverse City"));

       return albumList;

    }

    public void putIncache() {
        try {


            CompositeCacheManager ccm = CompositeCacheManager.getUnconfiguredInstance();
            Properties props = new Properties();

            props.put("jcs.default","DC");
            props.put("jcs.default.cacheattributes",
                    "org.apache.jcs.engine.CompositeCacheAttributes");
// lots more props.put - this is basically the contents of cache.ccf
            Logger log
                    = Logger.getLogger(MusicDao.class);

            ccm.configure(props);

            // Load the cache
            cache = JCS.getInstance("musicCache");


            int i=0;
            for(Album a:albumList){
                cache.put(new Integer(i+1), a);

            }


        } catch (CacheException e) {
            System.out.println("here");
            e.printStackTrace();
        }
    }
}

In src/main/resource i have config file cache.ccf as:

jcs.default=
jcs.default.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes
jcs.default.cacheattributes.MaxObjects=200
jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache
jcs.default.elementattributes.IsEternal=false
jcs.default.elementattributes.MaxLifeSeconds=86400
jcs.default.elementattributes.IdleTime=86400

I dont know whether this file is either called from class path or not so i added in my pom.xml as:

 <resources>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.ccf</include>
        </includes>
      </resource>
        </resources>

in pom.xml it is:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ashwin</groupId>
    <artifactId>CacheApp</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>CacheApp</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <repositories>  
        <repository>
    <id>jfrog-libs</id>
    <name>jfrog-libs</name>
    <url>http://repo.jfrog.org/artifactory/libs-releases</url>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
</repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-jcs-core</artifactId>
            <version>2.2.1</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>

         <!-- https://mvnrepository.com/artifact/jcs/jcs -->
    <dependency>
      <groupId>jcs</groupId>
      <artifactId>jcs</artifactId>
      <version>1.3</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.16</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/concurrent/concurrent -->
    <dependency>
      <groupId>concurrent</groupId>
      <artifactId>concurrent</artifactId>
      <version>1.3.4</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.8</version>
</dependency>


<dependency>
    <groupId>com.google.guava</groupId> 
    <artifactId>guava</artifactId> 
    <version>16.0</version> 
</dependency>


    </dependencies>

    <build>

        <resources>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.ccf</include>
        </includes>
      </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

My output when i call api http://localhost:8080/api/hello/getAllMusic is:

Putting data in cache 
Putting data in cache 
Putting data in cache 
Putting data in cache 

My expected output is:

 Putting data in cache 
Returning data from cache
Returning data from cache
Returning data from cache
Returning data from cache

Edited Source code: I made the new class MusicClass.java

package com.ashwin.cacheapp.dao;

import com.ashwin.cacheapp.model.Album;
import com.ashwin.cacheapp.model.Student;
import java.util.Properties;
import org.apache.jcs.JCS;
import org.apache.jcs.access.exception.CacheException;
import org.apache.jcs.engine.control.CompositeCacheManager;
import org.apache.log4j.Logger;



public class MusicCache {
     private JCS cache;


       // static variable single_instance of type Singleton 
    private static MusicCache single_instance=null; 


    // private constructor restricted to this class itself 
    private MusicCache() 
    { 
          try {
           CompositeCacheManager ccm = CompositeCacheManager.getUnconfiguredInstance();
            Properties props = new Properties();

            props.put("jcs.default","DC");
            props.put("jcs.default.cacheattributes",
                    "org.apache.jcs.engine.CompositeCacheAttributes");
// lots more props.put - this is basically the contents of cache.ccf
            Logger log
                    = Logger.getLogger(MusicDao.class);

            ccm.configure(props);

            // Load the cache
            cache = JCS.getInstance("musicCache");

            cache.put( "123", new Student( 123, "John", "Swizher", "Weige", "Civil") );
            cache.put( "143", new Student( 143, "Theoder", "", "Sattler", "Computer Science" ) );
            cache.put( "153", new Student( 153, "Martin", "Sam", "Suckhorozka", "Electrical" ) );
            cache.put( "163", new Student( 163, "Russel", "", "Latour", "Mechanical" ) );


        } catch (CacheException e) {
            System.out.println("here");
            e.printStackTrace();
        }
    } 

    // static method to create instance of Singleton class 
    public static MusicCache Singleton() 
    { 
        // To ensure only one instance is created 
        if (single_instance == null) 
        { 
            single_instance = new MusicCache(); 
        } 
        return single_instance; 
    } 
}

Changing in function of service class is:

  public  List<Album> getAllMusic() {
        try
             {
             Properties props = new Properties();
            props.load(new FileInputStream("src/main/resources/log4j.properties"));
            PropertyConfigurator.configure(props); 

     List<Album> albumList = (List) cache.get("musicCache");
     System.out.println("Size of album is"+albumList.size());
        if(albumList!=null) {
            System.out.println("Returning data from cache");
          return albumList;
           }
     } catch(Exception e ){

             try{
                 System.out.println("Putting data in cache");
                 MusicCache x = MusicCache.Singleton();
             }
             catch(Exception ef){

             }
             return musicDao.getAllTopHundredMusic();
     }

        return null;

    }

Still I got the same output

Ashwin Karki
  • 249
  • 4
  • 18
  • Replace cache.get("musicCache") with cache.get(1) to get the first album. – cruftex Aug 31 '19 at 04:56
  • so in real world scenario,i may not know how may element are there in cache? cant i make it dynamic, so that all list will return from cache? – Ashwin Karki Aug 31 '19 at 05:02
  • i want all the items in the cache dynamically,not by passing key .. cant i get cache element like that? – Ashwin Karki Aug 31 '19 at 05:04
  • A new resource is created for each request, which means a new MusicService, which means a new MusicDao. Either make the resource class a singleton, in which case you need to take care of thread safety, or make the service a static field. – Paul Samsotha Aug 31 '19 at 08:36
  • can u please show me example @PaulSamsotha i m stuck this problem for a week – Ashwin Karki Aug 31 '19 at 08:45
  • 1) Do you understand what I am saying about the reason this is happening? 2) Do you know what the keyword `static` does and how it will solve the problem? Figure these two things out and you will be on your way to success. – Paul Samsotha Aug 31 '19 at 09:04
  • if we instantiate keyword with static then it can be called by class name not by object. – Ashwin Karki Aug 31 '19 at 09:05
  • You need to do some more research. This is basic Java. You need to know this stuff. – Paul Samsotha Aug 31 '19 at 09:07
  • i have used static methods and class to call them so that i can call the class methoda without creating object.If there is any use I can use in this project then please show me – Ashwin Karki Aug 31 '19 at 09:09
  • please see the some code i changed and added at last as you told me to make it singleton class,but i still got the same output – Ashwin Karki Aug 31 '19 at 09:40

0 Answers0