REST APIS is available in plenty nowadays. As cryptocurrencies are a hot topic nowadays, there is always a need to compare the different cryptocurrencies and get the corresponding value in different currencies. As a sample, let us take a REST API call as
https://min-api.cryptocompare.com/data/price?fsym=LTC&tsyms=BTC,USD,EUR,INR
Here fym represents the cryptocurrency for which we need the current price tsyms represents another cryptocurrency in which comparison occurs USD, EUR, and INR are the currency symbols and we get the price value in the respective currency.
Output is in JSON format:
Let us see a few Cryptocurrencies and their symbols
Cryptocurrency |
Symbol |
---|---|
Bitcoin | BTC |
Ethereum | ETH |
Litecoin | LTC |
Zcash | ZEC |
Iota | MIOTA |
Ok, now let us start preparing the Spring MVC project and render the JSON response in our desired way.
Implementation
Project Structure:
It is a maven-driven project
pom.xml
XML
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 < modelVersion >4.0.0</ modelVersion > < groupId >com.cryptocurrencycompare.cryptocurrencycompare_Rest_API</ groupId > < artifactId >cryptocurrencycompare_Rest_API</ artifactId > < packaging >war</ packaging > < version >0.0.1-SNAPSHOT</ version > < name >cryptocurrencycomparator</ name > < properties > < failOnMissingWebXml >false</ failOnMissingWebXml > < spring-version >5.1.0.RELEASE</ spring-version > </ properties > < dependencies > < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-webmvc</ artifactId > < version >${spring-version}</ version > </ dependency > < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-test</ artifactId > < version >${spring-version}</ version > </ dependency > <!-- JSTL Dependency --> < dependency > < groupId >javax.servlet.jsp.jstl</ groupId > < artifactId >javax.servlet.jsp.jstl-api</ artifactId > < version >1.2.1</ version > </ dependency > < dependency > < groupId >taglibs</ groupId > < artifactId >standard</ artifactId > < version >1.1.2</ version > </ dependency > <!-- Servlet Dependency --> < dependency > < groupId >javax.servlet</ groupId > < artifactId >javax.servlet-api</ artifactId > < version >3.1.0</ version > < scope >provided</ scope > </ dependency > <!-- JSP Dependency --> < dependency > < groupId >javax.servlet.jsp</ groupId > < artifactId >javax.servlet.jsp-api</ artifactId > < version >2.3.1</ version > < scope >provided</ scope > </ dependency > < dependency > < groupId >com.google.code.gson</ groupId > < artifactId >gson</ artifactId > < version >2.8.6</ version > </ dependency > < dependency > < groupId >commons-io</ groupId > < artifactId >commons-io</ artifactId > < version >2.5</ version > </ dependency > < dependency > < groupId >junit</ groupId > < artifactId >junit</ artifactId > < version >4.12</ version > < scope >test</ scope > </ dependency > </ dependencies > < build > < finalName >CryptoCompareDetails</ finalName > < sourceDirectory >src/main/java</ sourceDirectory > < plugins > < plugin > < artifactId >maven-compiler-plugin</ artifactId > < version >3.5.1</ version > < configuration > < source >1.8</ source > < target >1.8</ target > </ configuration > </ plugin > <!-- This should be added to overcome Could not initialize class org.apache.maven.plugin.war.util.WebappStructureSerializer --> < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-war-plugin</ artifactId > < version >3.3.2</ version > </ plugin > </ plugins > </ build > </ project > |
Let us start with the invoking page i.e. the JSP page where we can provide from currency and to currency
HTML
<!DOCTYPE html> < html lang = "en" > < head > < meta charset = "utf-8" > < meta http-equiv = "X-UA-Compatible" content = "IE=edge" > < meta name = "viewport" content = "width=device-width, initial-scale=1" > < title >Cryptocurrency</ title > < link rel = "stylesheet" href = "https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" > < style type = "text/css" > .main-form, .profile-area { width: 500px; } .main-form { margin: 50px auto 0px; } .profile-area { margin: 10px auto; } .main-form section, .profile-area section { margin-bottom: 15px; background: #df5b47; box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); } .main-form section { padding: 30px; } .profile-area section { padding: 30px 30px 30px; } .profile-area section > div { text-align: center; } .main-form h3 { margin: 0 0 15px; } .form-control, .btn { min-height: 38px; border-radius: 2px; } .btn { font-size: 15px; font-weight: bold; font-family: verdana; } .hideElement { display: none; } </ style > </ head > < body > < div class = "main-form" id = "main-form" > < section > < h5 class = "text-center" >Enter a Cryptocurrency that need to be compared </ h5 > < div class = "form-group" > < input id = "fsym" type = "text" class = "form-control" placeholder = "Enter a Cryptocurrency that need to be compared..." required = "required" > </ div > < h5 class = "text-center" >Enter a comparison Cryptocurrency </ h5 > < div class = "form-group" > < input id = "tsyms" type = "text" class = "form-control" placeholder = "Enter a comparison Cryptocurrency ..." required = "required" > </ div > < div class = "form-group" > < button onclick = "loadData()" class = "btn btn-primary btn-block" >Compare Cryptocurrencies</ button > </ div > </ section > </ div > < div class = "profile-area hideElement" id = "profile-area" > < section > < div id = "loader" class = "hideElement" > < div class = "spinner-border" role = "status" > < span class = "sr-only" >Loading...</ span > </ div > </ div > < div id = "profile" class = "hideElement" > < br >< br > < p >< strong >USD : < span id = "USD" ></ span ></ strong ></ p > < p >< strong >EUR : < span id = "EUR" ></ span ></ strong ></ p > < p >< strong >INR : < span id = "INR" ></ span ></ strong ></ p > </ div > </ section > </ div > </ body > < script > function loadData() { document.getElementById("profile-area").classList.remove("hideElement"); document.getElementById("loader").classList.remove("hideElement"); document.getElementById("profile").classList.add("hideElement"); var fsym = document.getElementById("fsym").value; var tsyms = document.getElementById("tsyms").value; if(fsym != "" && fsym != null && tsyms != "" && tsyms != null) { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var jsonResponse = JSON.parse(this.responseText); document.getElementById("USD").innerHTML = jsonResponse.USD; document.getElementById("EUR").innerHTML = jsonResponse.EUR; document.getElementById("INR").innerHTML = jsonResponse.INR; document.getElementById("loader").classList.add("hideElement"); document.getElementById("profile").classList.remove("hideElement"); } }; xhttp.open("GET", "getCryptocurrencyComparisonDetailsByName?fsym=" + fsym + "&tsyms=" + tsyms, true); xhttp.send(); console.log("done"); } else { console.log("Enter from and to cryptocurrency...") } } </ script > </ html > |
Output:
Let us provide from and to cryptocurrency values
For getting the JSON response rendered properly, we are following the controller file to perform the action via Spring. Let us see important files
AppConfig.java
Java
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @Configuration @EnableWebMvc @ComponentScan (basePackages = { "com.cryptocurrencycompare.cryptocurrencycompare_Rest_API" }) public class AppConfig { @Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setViewClass(JstlView. class ); resolver.setPrefix( "/" ); resolver.setSuffix( ".jsp" ); return resolver; } } |
SpringMvcDispatcherServletInitializer.java
Java
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class SpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return null ; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[] { AppConfig. class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } } |
Controller class
CryptocurrencyComparatorController.java
Java
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.StringTokenizer; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.google.gson.Gson; import com.google.gson.JsonObject; @Controller public class CryptocurrencyComparatorController { @RequestMapping ( "/getCryptocurrencyComparisonDetailsByName" ) public @ResponseBody JsonObject getCryptocurrencyComparatorDetails(String fsym,String tsyms) throws IOException { JsonObject jsonObject = new JsonObject(); jsonObject = getCryptocurrencyComparatorData(fsym,tsyms); String data = jsonObject.toString().replaceAll( "^\"|\"$" , "" ); StringTokenizer jsonTokenizer = new StringTokenizer(data, "," ); String internalData[]; String expectedCryptocurrencyOutput = null ; while (jsonTokenizer.hasMoreTokens()) { expectedCryptocurrencyOutput = jsonTokenizer.nextToken(); internalData = StringUtils.split(expectedCryptocurrencyOutput, ":" ); System.out.println(internalData[ 0 ]+internalData[ 1 ]); if (internalData[ 0 ].substring( 2 ,internalData[ 0 ].length()- 1 ).equalsIgnoreCase( "BTC" )) { jsonObject.addProperty( "BTC" ,internalData[ 1 ].substring( 0 ,internalData[ 1 ].length())); } if (internalData[ 0 ].substring( 1 ,internalData[ 0 ].length()- 1 ).equalsIgnoreCase( "USD" )) { jsonObject.addProperty( "USD" ,internalData[ 1 ].substring( 0 ,internalData[ 1 ].length())); } if (internalData[ 0 ].substring( 1 ,internalData[ 0 ].length()- 1 ).equalsIgnoreCase( "EUR" )) { jsonObject.addProperty( "EUR" ,internalData[ 1 ].substring( 0 ,internalData[ 1 ].length())); } if (internalData[ 0 ].substring( 1 ,internalData[ 0 ].length()- 1 ).equalsIgnoreCase( "INR" )) { jsonObject.addProperty( "INR" ,internalData[ 1 ].substring( 0 ,internalData[ 1 ].length()- 1 )); } } return jsonObject; } private JsonObject getCryptocurrencyComparatorData(String fromCryptocurrency,String toCryptocurrency) throws IOException { StringBuilder responseData = new StringBuilder(); JsonObject jsonObject = null ; URL url = null ; url = new URL( "https://min-api.cryptocompare.com/data/price?fsym=" +fromCryptocurrency+ "&tsyms=" +toCryptocurrency+ ",USD,EUR,INR" ); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod( "GET" ); con.setRequestProperty( "User-Agent" , "Mozilla/5.0" ); int responseCode = con.getResponseCode(); System.out.println( "\nSending 'GET' request to URL : " + url); System.out.println( "Response Code : " + responseCode); try (BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream()))) { String line; while ((line = in.readLine()) != null ) { responseData.append(line); } jsonObject = new Gson().fromJson(responseData.toString(), JsonObject. class ); } System.out.println(jsonObject); return jsonObject; } } |
Let us test the same by using JUNIT test cases and the testing is carried out by using MockMvc
Java
import static org.junit.Assert.assertEquals; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.StringTokenizer; import org.junit.Before; import org.junit.Test; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.util.StringUtils; import com.google.gson.Gson; import com.google.gson.JsonObject; public class CryptocurrencyComparatorControllerTest { private MockMvc mockMvc; @Before public void setup() { this .mockMvc = MockMvcBuilders.standaloneSetup( new CryptocurrencyComparatorController()).build(); } @Test public void testCryptocurrencyComparisonDetails() throws Exception { // expected String expectedData = null ; StringBuilder responseData = new StringBuilder(); JsonObject expectedJsonObject = null ; String expectedBTC = null ,expectedUSD = null ,expectedEUR = null ,expectedINR = null ; HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod( "GET" ); con.setRequestProperty( "User-Agent" , "Mozilla/5.0" ); try (BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream()))) { String line; while ((line = in.readLine()) != null ) { responseData.append(line); } expectedJsonObject = new Gson().fromJson(responseData.toString(), JsonObject. class ); //expectedData = expectedJsonObject.get("data").toString(); expectedData = expectedJsonObject.toString().replaceAll( "^\"|\"$" , "" ); StringTokenizer jsonTokenizer = new StringTokenizer(expectedData, "," ); String internalData[]; String expectedCryptocurrencyOutput = null ; while (jsonTokenizer.hasMoreTokens()) { expectedCryptocurrencyOutput = jsonTokenizer.nextToken(); internalData = StringUtils.split(expectedCryptocurrencyOutput, ":" ); System.out.println(internalData[ 0 ]+internalData[ 1 ]); if (internalData[ 0 ].substring( 2 ,internalData[ 0 ].length()- 1 ).equalsIgnoreCase( "BTC" )) { expectedBTC = internalData[ 1 ].substring( 0 ,internalData[ 1 ].length()); } if (internalData[ 0 ].substring( 1 ,internalData[ 0 ].length()- 1 ).equalsIgnoreCase( "USD" )) { expectedUSD = internalData[ 1 ].substring( 0 ,internalData[ 1 ].length()); } if (internalData[ 0 ].substring( 1 ,internalData[ 0 ].length()- 1 ).equalsIgnoreCase( "EUR" )) { expectedEUR = internalData[ 1 ].substring( 0 ,internalData[ 1 ].length()); } if (internalData[ 0 ].substring( 1 ,internalData[ 0 ].length()- 1 ).equalsIgnoreCase( "INR" )) { expectedINR = internalData[ 1 ].substring( 0 ,internalData[ 1 ].length()- 1 ); } } System.out.println(expectedBTC + " " + expectedUSD + " " + expectedEUR + " " + expectedINR); } // actual MvcResult result = mockMvc.perform(get( "/getCryptocurrencyComparisonDetailsByName?fsym=LTC&tsyms=BTC" )) .andReturn(); String recievedResponse = result.getResponse().getContentAsString(); JsonObject actualJsonObject = new Gson().fromJson(recievedResponse, JsonObject. class ); String actualBTC = actualJsonObject.get( "BTC" ).toString(); actualBTC = actualBTC.replaceAll( "^\"|\"$" , "" ); String actualUSD = actualJsonObject.get( "USD" ).toString(); actualUSD = actualUSD.replaceAll( "^\"|\"$" , "" ); String actualEUR = actualJsonObject.get( "EUR" ).toString(); actualEUR = actualEUR.replaceAll( "^\"|\"$" , "" ); String actualINR = actualJsonObject.get( "INR" ).toString(); actualINR = actualINR.replaceAll( "^\"|\"$" , "" ); String internalData[]; internalData = StringUtils.split(expectedBTC, "." ); System.out.println(internalData[ 0 ]+internalData[ 1 ]); assertEquals(expectedBTC, actualBTC); assertEquals(expectedUSD, actualUSD); assertEquals(expectedEUR, actualEUR); assertEquals(expectedINR, actualINR); } } |
Output: