...

Membuat Spring 4 Rest API Service tanpa DB

REST atau REpresentational State Transfer umum digunakan dalam disribusi resources melalui jenis media seperti JSON, XML atau juga teks. Berikut kita mencoba untuk mengimplementasikan REST dengan Spring 4 MVC tanpa akses Database.

REST bekerja berdasarkan arsitektur client-server dimana permintaan (Request) dikirimkan ke Server dan Server mengembalikan Response. Dalam REST metoda Request dapat berupa GET, POST, PUT, PATCH atau DELETE

Mari kita memulai membuat REST API dengan Spring MVC 4

1. Buat Project Maven baru dengan Eclipse JEE

Klik File > New > Maven Project

Kemudian klik > Next

Setelah itu pilih maven-archetype-webapp dan klik > Next

Beri nama untuk Group Id (com.kodefin.spring) dan Artifact Id (RestAPI), kemudian klik > Finish

2. Update pom.xml

Setelah Eclipse JEE berhasil membuat Project baru, maka pilih file maven pom.xml (seperti gambar dibawah)

Edit file pom.xml dengan menambahkan elemen properties untuk Spring Framework dan Jackson, sbb :

<properties>
   <springframework.version>4.2.0.RELEASE</springframework.version>
   <jackson.version>2.5.3</jackson.version>
</properties>

Serta tambahkan juga dependency yang dibutuhkan sbb :

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>${springframework.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-tx</artifactId>
	<version>${springframework.version}</version>
</dependency>
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>${jackson.version}</version>
</dependency>
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>3.1.0</version>
</dependency>

3. Class Model Siswa

Buatlah Package baru didalam source folder src/main/java dan beri nama com.kodefin.spring.model (atau nama lain yang kamu inginkan)

Dan buatlah Class baru dalam package com.kodefin.spring.model dengan nama class Siswa

Buka file class Siswa dan tuliskan kode class sbb:

public class Siswa {
	private long id;
	private String nama;
	private String jurusan;
	private double ipk;

	public Siswa(){
		id=0;
	}
	
	public Siswa(long id, String nama, String jurusan, double ipk){
		this.id = id;
		this.nama = nama;
		this.jurusan = jurusan;
		this.ipk = ipk;
	}
	
	public long getId() {
		return id;
	}

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

	public String getNama() {
		return nama;
	}

	public void setNama(String nama) {
		this.nama = nama;
	}

	public String getJurusan() {
		return jurusan;
	}

	public void setJurusan(String jurusan) {
		this.jurusan = jurusan;
	}

	public double getIpk() {
		return ipk;
	}

	public void setIpk(double ipk) {
		this.ipk = ipk;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (id ^ (id >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Siswa other = (Siswa) obj;
		if (id != other.id)
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Siswa [id=" + id + ", nama=" + nama + ", jurusan=" + jurusan
				+ ", ipk=" + ipk + "]";
	}
}

4. Interface Service dan Class Implementasi Service

Buatlah Package baru didalam source folder src/main/java dan beri nama com.kodefin.spring.service

Setelah itu buatlah Interface baru dalam package com.kodefin.spring.service dengan nama interface SiswaService. Kemudian buat juga class baru dalam package yang sama dengan nama class SiswaServiceImpl

Pilih interface SiswaService dan tuliskan kode Java sbb :

public interface SiswaService {
	Siswa findById(long id);
	Siswa findByNama(String nama);
	void saveSiswa(Siswa siswa);
	void updateSiswa(Siswa siswa);
	void deleteSiswaById(long id);
	List<Siswa> findAllSiswa(); 
	void deleteAllSiswa();
	public boolean isSiswaExist(Siswa siswa);
}

Dalam interface SiswaService kita mendeklarasikan Metoda yang nanti didefinisikan pada class SiswaServiceImpl

Kemudian pilih class SiswaServiceImpl tuliskan anotasi 

@Service("siswaService")
@Transactional

yang menyatakan bahwa class SiswaServiceImpl merupakan Service Class dari Interface SiswaService dan merupakan proses transaksi atomic.

Edit class SiswaServiceImpl dengan menambahkan implements SiswaService

public class SiswaServiceImpl implements SiswaService{
...

Tuliskan data atribut class sbb : 

private static final AtomicLong counter = new AtomicLong();
private static List<Siswa> siswaList;
static {
	siswaList = isiDataSiswa();
}

Dimana siswaList dibuat untuk kebutuhan dummy data Siswa.

Tambahkan implementasi metoda pada class SiswaServiceImpl, sbb :

// Ambil data Siswa berdasarkan id
public Siswa findById(long id) {
	for(Siswa siswa : siswaList){
		if(siswa.getId() == id){
			return siswa;
		}
	}
	return null;
}

// Ambil data Siswa berdasarkan nama
public Siswa findByNama(String nama) {
	for(Siswa siswa : siswaList){
		if(siswa.getNama().equalsIgnoreCase(nama)){
			return siswa;
		}
	}
	return null;
}

// Sismpan data Siswa
public void saveSiswa(Siswa siswa) {
	siswa.setId(counter.incrementAndGet());
	siswaList.add(siswa);
	
}

// Update data Siswa
public void updateSiswa(Siswa siswa) {
	int index = siswaList.indexOf(siswa);
	siswaList.set(index, siswa);
	
}

// Hapus data Siswa berdasarkan id
public void deleteSiswaById(long id) {
	for (Iterator<Siswa> iterator = siswaList.iterator(); iterator.hasNext(); ) {
		Siswa siswa = iterator.next();
	    if (siswa.getId() == id) {
	        iterator.remove();
	    }
	}
}

// Hapus seluruh data Siswa
public void deleteAllSiswa() {
	siswaList.clear();
}

// Apakah Siswa dengan nama yang sama sudah ada ?
public boolean isSiswaExist(Siswa siswa) {
	return findByNama(siswa.getNama())!=null;
}

// Membuat data dummy Siswa
private static List<Siswa> isiDataSiswa(){
	List<Siswa> siswaList = new ArrayList<Siswa>();
	siswaList.add(new Siswa(counter.incrementAndGet(),"Jaka Suryana","Manajemen Informatika", 2.3));
	siswaList.add(new Siswa(counter.incrementAndGet(),"Surya Budiman","Teknik Informatik", 2.3));
	siswaList.add(new Siswa(counter.incrementAndGet(),"Yuyun Sulistia","Sistem Informasi", 2.3));
	siswaList.add(new Siswa(counter.incrementAndGet(),"Susi Susanti","Teknik Komputer", 2.3));
	return siswaList;
}

5. Class Controller

Buatlah Package baru didalam source folder src/main/java dan beri nama com.kodefin.spring.controller (atau nama lain yang kamu inginkan)

Dan buatlah Class baru dalam package com.kodefin.spring.controller dengan nama class RestAPIController

Buka file class RestAPIController dan tambahkan anotasi @RestController, dan tuliskan data member dan metoda sbb :

@RestController
public class RestAPIController {
	 
    @Autowired
    SiswaService siswaService;  //Service which will do all data retrieval/manipulation work
 
     
    //------------------- Mengambil seluruh data Siswa--------------------------------------------------------
     
    @RequestMapping(value = "/siswa/", method = RequestMethod.GET)
    public ResponseEntity<List<Siswa>> listAllSiswa() {
        List<Siswa> siswaList = siswaService.findAllSiswa();
        if(siswaList.isEmpty()){
            return new ResponseEntity<List<Siswa>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND
        }
        return new ResponseEntity<List<Siswa>>(siswaList, HttpStatus.OK);
    }
 
 
    //-------------------Mengambil Satu data Siswa--------------------------------------------------------
     
    @RequestMapping(value = "/siswa/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Siswa> getSiswa(@PathVariable("id") long id) {
        System.out.println("Ambil Siswa dengan id " + id);
        Siswa siswa = siswaService.findById(id);
        if (siswa == null) {
            System.out.println("Siswa dengan id " + id + " tidak ditemukan");
            return new ResponseEntity<Siswa>(HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity<Siswa>(siswa, HttpStatus.OK);
    }
 
     
     
    //-------------------Membuat Siswa baru--------------------------------------------------------
     
    @RequestMapping(value = "/siswa/", method = RequestMethod.POST)
    public ResponseEntity<Void> createSiswa(@RequestBody Siswa siswa, UriComponentsBuilder ucBuilder) {
        System.out.println("Buat Siswa baru " + siswa.getNama());
 
        if (siswaService.isSiswaExist(siswa)) {
            System.out.println("Siswa dengan nama " + siswa.getNama() + " telah ada sebelumnya");
            return new ResponseEntity<Void>(HttpStatus.CONFLICT);
        }
 
        siswaService.saveSiswa(siswa);
 
        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(ucBuilder.path("/siswa/{id}").buildAndExpand(siswa.getId()).toUri());
        return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
    }
 
     
    //------------------- Update Siswa --------------------------------------------------------
     
    @RequestMapping(value = "/siswa/{id}", method = RequestMethod.PUT)
    public ResponseEntity<Siswa> updateSiswa(@PathVariable("id") long id, @RequestBody Siswa siswa) {
        System.out.println("Update Siswa " + id);
         
        Siswa currentSiswa = siswaService.findById(id);
         
        if (currentSiswa==null) {
            System.out.println("Siswa dengan id " + id + " tidak ditemukan");
            return new ResponseEntity<Siswa>(HttpStatus.NOT_FOUND);
        }
 
        currentSiswa.setNama(siswa.getNama());
        currentSiswa.setJurusan(siswa.getJurusan());
        currentSiswa.setIpk(siswa.getIpk());
         
        siswaService.updateSiswa(currentSiswa);
        return new ResponseEntity<Siswa>(currentSiswa, HttpStatus.OK);
    }
 
    //------------------- Hapus Siswa --------------------------------------------------------
     
    @RequestMapping(value = "/siswa/{id}", method = RequestMethod.DELETE)
    public ResponseEntity<Siswa> deleteSiswa(@PathVariable("id") long id) {
        System.out.println("Hapus Siswa dengan id " + id);
 
        Siswa siswa = siswaService.findById(id);
        if (siswa == null) {
            System.out.println("Tidak dapat menghapus. Siswa dengan id " + id + " tidak ditemukan");
            return new ResponseEntity<Siswa>(HttpStatus.NOT_FOUND);
        }
 
        siswaService.deleteSiswaById(id);
        return new ResponseEntity<Siswa>(HttpStatus.NO_CONTENT);
    }
 
     
    //------------------- Hapus semua Siswa --------------------------------------------------------
     
    @RequestMapping(value = "/siswa/", method = RequestMethod.DELETE)
    public ResponseEntity<Siswa> deleteAllSiswa() {
        System.out.println("Hapus seluruh Siswa");
 
        siswaService.deleteAllSiswa();
        return new ResponseEntity<Siswa>(HttpStatus.NO_CONTENT);
    }
 
}

6. Spring Config dan filter CORS

Buatlah package baru dengan nama com.kodefin.spring.config. Kemudian dalam package tersebut buat dua class baru, yang pertama adalah RestConfig dan yang kedua adalah CORSFilter, sbb :

Tuliskan kode berikut pada class RestConfig


@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.kodefin.spring")
public class RestConfig {

}

Class CORSFilter memungkian adanya Cross Origin Request terhadap Aplikasi Spring kita, kode Java untuk CORSFilter adalah sebagai berikut :

public class CORSFilter implements Filter {

	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		HttpServletResponse response = (HttpServletResponse) res;
		response.setHeader("Access-Control-Allow-Origin", "*");
		response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
		response.setHeader("Access-Control-Max-Age", "3600");
		response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
		chain.doFilter(req, res);
	}

	public void init(FilterConfig filterConfig) {}

	public void destroy() {}

}

7. Class Initializer

Terakhir adalah class Initializer yang kita tempatkan dalam package com.kodefin.spring dengan nama class RestAPIAppInitializer

public class RestAPIAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { RestConfig.class };
    }
  
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }
  
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
    
    @Override
    protected Filter[] getServletFilters() {
    	Filter [] singleton = { new CORSFilter()};
    	return singleton;
    }

}

8. Menjalankan Aplikasi Spring 4 MVC

Setelah selesai mari kita coba untuk menjalankan Aplikasi Spring pada Server Tomcat, sbb :

Tambahkan aplikasi RestAPI dalam Server Tomcat

Jalankan Server Tomcat

9. Memanggil Request ke REST API kita

Setelah Server Tomcat kita jalankan, mari kita mencoba untuk melakukan request terhadap Rest API yang telah kita buat sebelumnya

Dari request diatas terlihat bahwa Server memberikan Response dengan mengembalikan data Siswa melalui tipe Media JSON.

Silahkan Mencoba dan Terima Kasih