Sample Project in IntelliJ

Sample Project in IntelliJ

How do I pull data from VetView?

VetView is closed source, but our library of API calls is available directly from your local installation.  

This walkthrough will detail how to connect to and interact with the VetView API using all accepted action types (GET, POST, PUT, & DELETE).
This also covers generating a pdf on the fly and serving it to the user.
This walkthrough utilizes the VetView API library documented here.

Create a new IntelliJ project.

First, select Gradle in the left pane.

Then select create-app in the middle panel.

Finally, at the top, select your Project SDK (Java Runtime) or create a new one.

Enter a project name, a module name, and select the location(s) to save.

Once created, open the application.yml file located in the app/grails-app/conf folder.

Replace the developent: dataSource section with 2 new settings called authToken and baseUrl.

You will need to create the app: and info: sections.

The development portion of the environment section should look like this:

environments:
    development:
        info:
            app:
                authToken: "TOKEN PASTED FROM VETVIEW"
                baseUrl: "http://IP.ADDRESS.OR.URL"

Next, open the files UrlMappings located in app/grails.app/Controllers directory and replace:

"/"(view:"/index")

with:

"/"(controller: 'index', action: 'index')

This change allows us to create an IndexController to control the root of our website, such as http://localhost/

Create a new Grails Controller called IndexController in the app/grails-app/controllers/app/ folder.

Modify the file to match this:

package sampleapiwebapp

class IndexController {

    def index() {
        return [result: "Sample API Webapp"]
    }
}

This returns a simple string to be used to test that our view is connected to our controller.

Next, create a new folder named index located in the app/grails-app/views/ folder.

Next, drag the index.gsp view into the index folder.

The default options on the move dialog can be used.

Click OK to move the file.

Add in a simple piece of code to verify the controller and view are communicating with each other.

This takes the string we returned on index load in IndexController and displays it in the header of the index.gsp page.

Before running the project, you may want to modify the build configuration so that IntelliJ does not open a new browser window every time you run/debug the app.

You can do this by clicking on the Build Configuration button and choosing Edit Configuration.

Deselect the Launch Browser setting and then click the OK button.

Click either the Run button or the Debug button to launch the app.

Once running, click the link in the Console window.

The page should contain the string we created in IndexController in the header portion of the index.gsp view.

Remove Branding in Project

Next, we will connect to VetView to retrieve data and display it in our view.

First, we will remove the default branding done by Grails.

Delete the file located at app/grails-app/views/layouts/main.gsp

Remove references to the deleted file.

Remove this line:

<meta name="layout" content="main">

Connect to VetView

Now that the page opens we need to import the VetView API Tools jar library.

Paste file into the root of your project.

Add into build.gradle the following line at the end of your dependencies list.

implementation files('vetview-api-0.1-plain.jar')

The first step is to check connections status to VetView.
This will be done in the index contoller.

IndexController.groovy
package sampleapiwebapp

import vetview.api.ApiService

class IndexController {
    def apiService = new ApiService(getGrailsApplication())

    def index() {
        try {
            def result = apiService.getResponse('common/getConnectionStatus', "")
            session.specimenLocations = result.results
            return [result: result]
        }
        catch (Exception ex) {
            println(ex.message)
            return [result: ex.message]
        }
    }
}

Note: In this walkthrough we perform minimal, if any, error-handling and validation.
Each call in groovy will have a try catch and each gsp has a simple conditional to display errors, but production environments will require more.

Edit index.gsp to be a simple welcome screen that checks connection status to VetView.
The source code of index.gsp should match this:
This includes a begin link that links to the first controller action we'll create in the next step.

index.gsp
<!doctype html>
<html>
<head>
    <title>Welcome to VetView API Example</title>
</head>
<body>
<div id="content" role="main">
    <section class="row colset-2-its">
        <h1>Welcome to our Sample VetView API Web App</h1>
        <p>
            In this sample tutorial VetView API app, we will perform several actions that utilize our most common API tasks.
        </p>
        <g:if test="${result.responseStatus == 'success'}">
            <p>Successfully connected to VetView.</p>
            <p><a href="specimens/listLocations/">Begin</a></p>
        </g:if>
        <g:elseif test="${result.responseStatus == 'failure'}">
            <p>Failed with error: ${result.message}</p>
        </g:elseif>
        <g:else>
            <p>Failed without error message.</p>
        </g:else>
    </section>
</div>
</body>
</html>

When run, it looks like:

For this project, we will leave the styling as the default black text on white background.

Next, we will create a new controller and gsp page.
For this sample project we will work with lab specimens.
Create a new controller named SpecimensController.

There are a few imports we will need:

import vetview.api.ApiService
import java.text.DateFormat
import java.text.SimpleDateFormat

We will create an instance of the API Service class for use in all of our functions.

class SpecimensController {
    def apiService = new ApiService(getGrailsApplication())
}

SpecimensController should match:

package sampleapiwebapp

import vetview.api.ApiService
import java.text.DateFormat
import java.text.SimpleDateFormat

class SpecimensController {
    def apiService = new ApiService(getGrailsApplication())
}

The first action we will complete is to display a list of available specimen locations.

Create the function for that in the SpecimensController called listLocations.

    def listLocations () {
        try {
            def result = apiService.getResponse('labs/specimens/listSpecimenLocations', "")
            session.specimenLocations = result.results
            return [result: result]
        }
        catch (Exception ex) {
            return [result: ex.message]
        }
    }

  1. Creates the method.
  2. Creates a Map variable and calls the getResponse function from the VetView API Service. getResponse makes a GET call to VetView.
  3. Saves the list of locations in the session for use later on.
  4. Returns the Map for use in the gsp.

Create a new gsp named listLocations.gsp.

NOTE: All remaining gsp pages will also be created in the folder views/Specimens/

In this gsp we will take the specimen locations and loop through them to display each as a link to a new action that we'll create named createSpecimen and passing in the location id.

specimenLocations.gsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>Specimen Locations</title>
</head>

<body>
<g:if test="${result.responseStatus == 'success'}">
    <h3>Choose location to create a new specimen for.</h3>
    <ul>
        <g:each var="location" in="${result.results}">
            <li><a href="/specimens/createSpecimen/${location.id}">${location.name}</a></li>
        </g:each>
    </ul>
</g:if>
<g:elseif test="${result.responseStatus == 'failure'}">
    <p>Failed with error: ${result.message}</p>
</g:elseif>
<g:else>
    <p>Failed without error message.</p>
</g:else>
</body>
</html>

For brevity, the remaining actions and gsp pages will be explained minimally and the descriptions will reference line numbers.
Also, there will be some pre-selected values to reduce complexity and length.

The next page and action is createSpecimen.
The createSpecimen call is an example of a POST call to the VetView API.

    def createSpecimen() {
        DateFormat apiDateFormat = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a")
        Map newSpecimen = [:]
        newSpecimen.put('accessionID', 577144) //pre-selected
        newSpecimen.put('specimenCodeID', 35) //pre-selected
        newSpecimen.put('specimenQty', 1)
        newSpecimen.put('specimenLocationID', params?.id)
        newSpecimen.put('testTubeNo', 'Thirteen')
        newSpecimen.put('sampledDate', apiDateFormat.format(new Date()))

        try {
            Map result = apiService.callPost("labs/specimens/createSpecimen", "", newSpecimen)
            return [result: result]
        }
        catch (Exception ex) {
            return [result: ex.message]
        }
    }

2: The VetView API takes dates in this specific format.
3-9: Create a Map variable to store the details of our new specimen.
      All calls that use a JSON body must be done with a POST call.
      The fields here must match the JSON bodies as shown in the API Swagger documentation.
      The callPost method accepts a third parameter, which is the Map of the new object.
12-13: Make the call to VetView using the callPost method from the API Service class and return the response to the gsp.

createSpecimen.gsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>Create Specimen</title>
</head>
<body>
<g:if test="${result.responseStatus == 'success'}">
    <p>Created new specimen with the id: ${result.id}</p>
    <p>Click <a href="/specimens/printLabel/${result.id}">here</a> to print the specimen label.</p>
    <g:if test="${session?.specimenLocations != null}">
        <p>Click on a location below to move the specimen to that location.</p>
        <ul>
            <g:each var="location" in="${session?.specimenLocations}">
                <li>
                   <a href="/specimens/changeLocation/${location?.id}?specimenId=${result.id}">${location.name}</a>
                </li>
            </g:each>
        </ul>
    </g:if>
</g:if>
<g:elseif test="${result.responseStatus == 'failure'}">
    <p>Failed with error: ${result.message}</p>
</g:elseif>
<g:else>
    <p>Failed without error message.</p>
</g:else>
</body>
</html>

8: Displays the id of the created specimen record.
9: Provides a link to a file that is a generated pdf.
10-18: Display the list of locations from the session variable for use in the next action, which is changeLocation.

changeLocation utilizes a PUT call, which can be done using the sendPut method of the API Service.

    def changeLocation() {
        try {
            Map result = apiService.sendPut("labs/specimens/updateSpecimenLocation", "?id=${params?.specimenId}&locationId=${params?.id}")
            return [result: result]
        }
        catch (Exception ex) {
            return [result: ex.message]
        }
    }

3-4 Sends the PUT command and returns the data.

changeLocation.gsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>Change Location</title>
</head>

<body>
<g:if test="${result.responseStatus == 'success'}">
    <p>Successfully moved specimen to new location.</p>
    <p>Click <a href="/specimens/createSpecimenPoolLink/${result.id}">here</a> to create a specimen pool link.</p>
</g:if>
<g:elseif test="${result.responseStatus == 'failure'}">
    <p>Failed with error: ${result.message}</p>
</g:elseif>
<g:else>
    <p>Failed without error message.</p>
</g:else>
</body>
</html>

Displays success message and links to the create specimen pool link page.


Also includes link for viewing the pdf label.

createSpecimenPoolLink:

    def createSpecimenPoolLink() {
        Map specimenPoolLink = [:]
        specimenPoolLink.put('poolSpecimenId', params?.id)
        specimenPoolLink.put('memberSpecimenId', 1579710) //pre-selected
        try {
            Map result = apiService.callPost("labs/specimens/createSpecimenPoolLink", "", specimenPoolLink)
            return [result: result]
        }
        catch (Exception ex) {
            return [result: ex.message]
        }
    }

Another example of a POST call with a Map object.

createSpecimenPoolLink.gsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>Create Specimen Pool Link</title>
</head>
<body>
<g:if test="${result.responseStatus == 'success'}">
    <p>Successfully created specimen pool link.</p>
    <p>Click <a href="/specimens/deleteSpecimenPoolLink/${result.id}">here</a> to delete the specimen pool link.</p>
</g:if>
<g:elseif test="${result.responseStatus == 'failure'}">
    <p>Failed with error: ${result.message}</p>
</g:elseif>
<g:else>
    <p>Failed without error message.</p>
</g:else>
</body>
</html>

Displays success and links to the final action for this sample project, deleteSpecimenPoolLink.

    def deleteSpecimenPoolLink() {
        println(params?.id)
        try {
            Map result = apiService.sendDelete("labs/specimens/deleteSpecimenPoolLink", "?id=${params?.id}")
            return [result: result]
        }
        catch (Exception ex) {
            println(ex.message)
            return [result: ex.message]
        }
    }

The fourth type of call, DELETE, is demonstrated using the sendDelete method of the API Service.

deleteSpecimenPoolLink.gsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>Delete Specimen Pool Link</title>
</head>
<body>
<g:if test="${result.responseStatus == 'success'}">
    <p>Successfully deleted specimen pool link.</p>
    <p><a href="/">Start Over</a></p>
</g:if>
<g:elseif test="${result.responseStatus == 'failure'}">
    <p>Failed with error: ${result.message}</p>
</g:elseif>
<g:else>
    <p>Failed without error message.</p>
</g:else>
</body>
</html>

Success message with a link to start over.

VetView Wiki

Most recent releases of VetView:  Version 5.0.2 and 4.2.8 Hotfix (Released 12/20/2024) 

Contents