Step 3: ExpenseController Class#

For the WebService in this tutorial, the ExpenseController defines the endpoints for the various Read and Write (CRUD) operations.

Create the ExpenseController Class#

Tip

Various aspects related to CRUD operations with the Inrupt Client Libraries are noted as comments in the code. For more details, see CRUD.

In the src/main/java/com/example/gettingstarted/ directory, create ExpenseController.java file with the content below:

package com.example.gettingstarted;

import com.inrupt.client.Request;
import com.inrupt.client.Response;
import com.inrupt.client.auth.Session;
import com.inrupt.client.openid.OpenIdSession;
import com.inrupt.client.solid.SolidSyncClient;
import com.inrupt.client.webid.WebIdProfile;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import java.io.PrintWriter;
import java.net.URI;
import java.util.Set;

@RequestMapping("/api")
@RestController
public class ExpenseController {

    /**
     * Note 1: Authenticated Session
     * Using the client credentials, create an authenticated session.
     */
    final Session session = OpenIdSession.ofClientCredentials(
            URI.create(System.getenv("MY_SOLID_IDP")),
            System.getenv("MY_SOLID_CLIENT_ID"),
            System.getenv("MY_SOLID_CLIENT_SECRET"),
            System.getenv("MY_AUTH_FLOW"));
    /**
     * Note 2: SolidSyncClient
     * Instantiates a synchronous client for the authenticated session.
     * The client has methods to perform CRUD operations.
     */
    final SolidSyncClient client = SolidSyncClient.getClient().session(session);
    private final PrintWriter printWriter = new PrintWriter(System.out, true);

    /**
     * Note 3: SolidSyncClient.read()
     * Using the SolidSyncClient client.read() method, reads the user's WebID Profile document and returns the Pod URI(s).
     */
    @GetMapping("/pods")
    public Set<URI> getPods(@RequestParam(value = "webid", defaultValue = "") String webID) {
        printWriter.println("ExpenseController:: getPods");
        try (final var profile = client.read(URI.create(webID), WebIdProfile.class)) {
            return profile.getStorage();
        }
    }

    /**
     * Note 4: SolidSyncClient.create()
     * Using the SolidSyncClient client.create() method,
     * - Saves the Expense as an RDF resource to the location specified in the Expense.identifier field.
     */
    @PostMapping(path = "/expenses/create")
    public String createExpense(@RequestBody Expense newExpense) {
        printWriter.println("ExpenseController:: createExpense");
        client.create(newExpense);
        return getResourceAsTurtle(String.valueOf(newExpense.getIdentifier()));
    }

    /**
     * Note 5: SolidSyncClient.read()
     * Using the SolidSyncClient client.read() method,
     * - Reads the RDF resource into the Expense class.
     */
    @GetMapping("/expenses/get")
    public Expense getExpense(@RequestParam(value = "resourceURL", defaultValue = "") String resourceURL) {
        printWriter.println("ExpenseController:: getExpense");
        try (var resource = client.read(URI.create(resourceURL), Expense.class)) {
            return resource;
        } catch (Exception e) {
            e.printStackTrace();
            throw new ResponseStatusException(HttpStatus.NOT_FOUND);
        }
    }

    /**
     * Note 6: SolidSyncClient.update()
     * Using the SolidSyncClient client.update() method,
     * - Updates the Expense resource.
     */
    @PutMapping("/expenses/update")
    public String updateExpense(@RequestBody Expense expense) {
        printWriter.println("ExpenseController:: updateExpense");
        client.update(expense);
        return getResourceAsTurtle(String.valueOf(expense.getIdentifier()));
    }


    /**
     * Note 7: SolidSyncClient.delete()
     * Using the SolidSyncClient client.delete() method,
     * - Deletes the resource located at the resourceURL.
     */

    @DeleteMapping("/expenses/delete")
    public void deleteExpense(@RequestParam(value = "resourceURL") String resourceURL) {
        printWriter.println("ExpenseController:: deleteExpense");
        try {
            client.delete(URI.create(resourceURL));
            
            // Alternatively, you can specify an Expense object to the delete method.
            // The delete method deletes  the Expense recorde located in the Expense.identifier field. 
            // For example: client.delete(new Expense(URI.create(resourceURL)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Note 8: Build and issue custom GET Request
     * - Use Inrupt's Request builder to create a GET Request to get the resource as MIME-type "text/turtle".
     * - Use SolidSyncClient.send() to send the Request and return the response body.
     */

    @GetMapping("/resource/get")
    public String getResourceAsTurtle(@RequestParam(value = "resourceURL", defaultValue = "") String resourceURL) {
        Request request = Request.newBuilder()
                .uri(URI.create(resourceURL))
                .header("Accept", "text/turtle")
                .GET()
                .build();
        Response<String> response = client.send(
                request,
                Response.BodyHandlers.ofString());
        return response.body();
    }

}