# Step 6: Run (Part 2)

## Run Your Local Web Server

Open a terminal window.

### Enter Your Client Credentials

{% hint style="danger" %}
Safeguard your **`Client ID`** and **`Client Secret`** values. Do not share these with any third parties as anyone with your **`Client ID`** and **`Client Secret`** values can impersonate you and act fully on your behalf.
{% endhint %}

Export your registered client credentials (see the [Prerequisites](/sdk/java-sdk/tutorial/prerequisites.md)) as environment variables.

1. Identity Provider (the IDP with whom you registered your application):

```sh
read -s MY_SOLID_IDP && export MY_SOLID_IDP
```

Enter `https://login.inrupt.com`

2. Client ID:

```sh
read -s MY_SOLID_CLIENT_ID && export MY_SOLID_CLIENT_ID
```

Enter your Client ID.

3. Client Secret:

```sh
read -s MY_SOLID_CLIENT_SECRET && export MY_SOLID_CLIENT_SECRET
```

Enter your Client Secret.

4. Authentication Flow Method:

```sh
read -s MY_AUTH_FLOW && export MY_AUTH_FLOW
```

Enter `client_secret_basic`

### Run the Application

Once you have entered your client credentials, start your application. From your project ( `getting-started/` ) directory, run your Spring Boot application:

* For Java, this tutorial assumes a Spring Boot Web Maven Project.
* For Kotlin, this tutorial assumes a Spring Boot Web Gradle Project.

{% tabs %}
{% tab title="Java" %}

```sh
./mvnw spring-boot:run
```

{% endtab %}

{% tab title="Kotlin" %}

```sh
./gradlew bootRun
```

{% endtab %}
{% endtabs %}

Your Web service runs on `http://localhost:8080` .

{% hint style="info" %}
Reminder\
The application is running **as** you, the user who registered it.
{% endhint %}

## Test the Service

Open another terminal window. To test, call the new endpoints defined in the **`ExpenseController`** class:

<table><thead><tr><th width="267.5859375">Endpoint</th><th>Description</th></tr></thead><tbody><tr><td><strong><code>/api/expenses/receipts/add</code></strong></td><td>Saves a non-RDF resource, namely an image file of a receipt, to a location in the Pod and updates the <strong><code>Expense</code></strong> object with the receipt location. Returns the updated <strong><code>Expense</code></strong> object.</td></tr><tr><td><strong><code>/api/resource/nonRDF/add</code></strong></td><td>Saves a non-RDF resource to a location in the Pod. Returns the identifier (as String) for the saved resource.</td></tr></tbody></table>

### Get Pod URL

To find your Pod URL, issue the following **`curl`** command, substituting your WebID (e.g., **`https://id.inrupt.com/yourUserName`** ):

```sh
curl -X GET http://localhost:8080/api/pods\?webid\=SUBSTITUTE_YOUR_WEBID
```

Upon success, the operation should return an array with your Pod Root URL; for example:

```sh
["https://storage.inrupt.com/your-root-container/"]
```

{% hint style="info" %}
Note\
In the following operations, substitute **`your-root-container`** with the value of your root container.
{% endhint %}

### Add a Receipt to Existing Expense

To add a receipt to an existing expense created in Part 1, call the **`api/expenses/receipts/add`** endpoint with a local **`.png`** file (can be a different file type **`.jpg`** , **`.pdf`** , etc. as well), **substituting** the path to your local file and your root container in the request body:

<pre class="language-sh"><code class="lang-sh">
curl -X PUT http://localhost:8080/api/expenses/receipts/add \
          -H "Content-Type: multipart/form-data" \
<strong>          -F "destinationURL=https://storage.inrupt.com/your-root-container/expenses/20230315/receipt.png" \
</strong><strong>          -F "file=@/my/local/file/path/to/receipt.png" \
</strong><strong>          -F "expenseURL=https://storage.inrupt.com/your-root-container/expenses/20230315/expense1"
</strong>
</code></pre>

{% hint style="info" %}
Tip

* If you encounter an **`HTTP 403 Forbidden`** error, double check that you have substituted **`your-root-container`** in the command.
* If you encounter a **`PreconditionFailedException`** , check that the **`receipt.png`** does not already exist at the the specified identifier. The **`.create()`** operation errors with **`PreconditionFailedException`** if a resource already exists. See [CRUD Module](/sdk/java-sdk/crud-data.md) for details.
  {% endhint %}

Upon success, the operation should return the updated **`Expense`** object as JSON (as well as print out, on the server-side, the content formatted in Turtle):

{% tabs %}
{% tab title="Returned Expense Object" %}

<pre class="language-json"><code class="lang-json">
{
    "identifier": "https://storage.inrupt.com/your-root-container/expenses/20230315/expense1",
    "merchantProvider": "Example Restaurant",
    "expenseDate": "2023-03-15T00:00:00.000+00:00",
    "description": "Team Lunch",
    "amount": 100,
    "currency": "USD",
    "category": "Travel &#x26; Entertainment",
<strong>    "receipts": [
</strong><strong>        "https://storage.inrupt.com/your-root-container/expenses/20230315/receipt.png"
</strong><strong>    ],
</strong>    "rdftype": "https://schema.org/Invoice"
}
</code></pre>

{% endtab %}

{% tab title="Content Formatted as Turtle" %}

<pre class="language-turtle"><code class="lang-turtle">
&#x3C;https://storage.inrupt.com/your-root-container/expenses/20230315/expense1>
        a                              &#x3C;https://schema.org/Invoice> ;
        &#x3C;https://schema.org/purchaseDate>
                "2023-03-15T00:00:00Z"^^&#x3C;http://www.w3.org/2001/XMLSchema#dateTime> ;
        &#x3C;https://schema.org/category>  "Travel &#x26; Entertainment" ;
        &#x3C;https://schema.org/description>
                "Team Lunch" ;
<strong>        &#x3C;https://schema.org/image>     &#x3C;https://storage.inrupt.com/your-root-container/expenses/20230315/receipt.png> ;
</strong><strong>        &#x3C;https://schema.org/priceCurrency>
</strong>                "USD" ;
        &#x3C;https://schema.org/provider>  "Example Restaurant" ;
        &#x3C;https://schema.org/totalPrice>
                "100"^^&#x3C;http://www.w3.org/2001/XMLSchema#decimal> .
</code></pre>

{% endtab %}
{% endtabs %}

See also [CRUD Module](/sdk/java-sdk/crud-data.md).

### Save a Non-RDF File

To save a receipt (a non-RDF resource) to your Pod, issue the following **`curl`** command to the **`api/resource/nonRDF/add`** endpoint, <mark style="color:red;">**substituting**</mark> the path to your local file and your root container in the request body:

<pre class="language-sh"><code class="lang-sh">curl -X PUT http://localhost:8080/api/resource/nonRDF/add \
          -H "Content-Type: multipart/form-data" \
<strong>          -F "destinationURL=https://storage.inrupt.com/your-root-container/expenses/20230327/receipt.png" \
</strong><strong>          -F "file=@/my/local/file/path/to/newreceipt.png"
</strong></code></pre>

{% hint style="info" %}
Tip

* If you encounter an **`HTTP 403 Forbidden`** error, double check that you have substituted **`your-root-container`** in the command.
* If you encounter a **`PreconditionFailedException`** , check that the resource does not already exist at the the specified identifier. The **`.create()`** operation errors with **`PreconditionFailedException`** if a resource already exists. See [CRUD Module](/sdk/java-sdk/crud-data.md) for details.
  {% endhint %}

Upon success, the operation returns identifier (as string) of the resource:

```none
https://storage.inrupt.com/your-root-container/expenses/20230327/receipt.png
```

See also [CRUD Module](/sdk/java-sdk/crud-data.md).

### Create an Expense Record

Using the receipt saved in the Save a Non-RDF File section, create a new expense that includes the receipt info, <mark style="color:red;">**substituting**</mark> your root container in the request body:

<pre class="language-sh"><code class="lang-sh">
curl -X POST http://localhost:8080/api/expenses/create \
   -H 'Content-type:application/json'  \
   -d '{
<strong>      "identifier": "https://storage.inrupt.com/your-root-container/expenses/20230327/expense1",
</strong><strong>      "merchantProvider": "Example Supply Store",
</strong>      "description": "Chair",
      "expenseDate": "2023-03-27",
      "amount": 400,
      "currency": "USD",
      "category": "Office Equipment &#x26; Supplies",
<strong>      "receipts": [ "https://storage.inrupt.com/your-root-container/expenses/20230327/receipt.png"] }'
</strong>
</code></pre>

{% hint style="info" %}
Tip

* If you encounter an **`HTTP 403 Forbidden`** error, double check that you have substituted **`your-root-container`** in the command.
* If you encounter a **`PreconditionFailedException`** , check that the resource does not already exist at the the specified identifier. The **`.create()`** operation errors with **`PreconditionFailedException`** if a resource already exists. See [CRUD Module](/sdk/java-sdk/crud-data.md) for details.
  {% endhint %}

Upon success, the operation should return the updated **`Expense`** object as JSON (as well as print out, on the server-side, the content formatted in Turtle):

{% tabs %}
{% tab title="Returned Expense Object" %}

```json
{
    "identifier": "https://storage.inrupt.com/your-root-container/expenses/20230327/expense1",
    "merchantProvider": "Example Supply Store",
    "expenseDate": "2023-03-27T00:00:00.000+00:00",
    "description": "Chair",
    "amount": 400,
    "currency": "USD",
    "category": "Office Equipment & Supplies",
    "receipts": [
        "https://storage.inrupt.com/your-root-container/expenses/20230327/receipt.png"
    ],
    "rdftype": "https://schema.org/Invoice"
}
```

{% endtab %}

{% tab title="Content Formatted as Turtle" %}

```turtle
<https://storage.inrupt.com/your-root-container/expenses/20230327/expense1>
        a                              <https://schema.org/Invoice> ;
        <https://schema.org/purchaseDate>
                "2023-03-27T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
        <https://schema.org/category>  "Office Equipment & Supplies" ;
        <https://schema.org/description>
                "Chair" ;
        <https://schema.org/image>     <https://storage.inrupt.com/your-root-container/expenses/20230327/receipt.png> ;
        <https://schema.org/priceCurrency>
                "USD" ;
        <https://schema.org/provider>  "Example Supply Store" ;
        <https://schema.org/totalPrice>
                "400"^^<http://www.w3.org/2001/XMLSchema#decimal> .
```

{% endtab %}
{% endtabs %}

See also [CRUD Module](/sdk/java-sdk/crud-data.md).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.inrupt.com/sdk/java-sdk/tutorial/step6.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
