DEV Community

Cover image for Happy Path: Web UI for Ollama using Java Only
Sami Ekblad
Sami Ekblad

Posted on

Happy Path: Web UI for Ollama using Java Only

I found that getting a local LLM up and running is becoming easier and easier, so it's time to update the guides. In this article, I'm setting up Ollama and building a minimal web UI—all in Java.

  • A full-stack application with a Vaadin frontend and Spring Boot backend.
  • Real-time chatting capability using a local Ollama in a container.
  • Dynamic message streaming and display of Markdown for the UX you would expect.

We will need the following installed:

  • Java 21
  • Maven for building the app
  • Local Docker container environment for running Ollama

Install and Run Ollama Container

First, set up the Ollama Docker container:



docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama


Enter fullscreen mode Exit fullscreen mode

Next, we need to install some of the supported LLM models, with 'mistral' being the default. This will take a while to download:



docker exec ollama ollama pull mistral


Enter fullscreen mode Exit fullscreen mode

Once done, you can check if the model is up and running by calling the REST API from the command line. For example:



curl http://localhost:11434/api/chat -d '{"model": "mistral", "messages": [{"role": "user", "content": "is black darker than white?"}], "stream":false}'


Enter fullscreen mode Exit fullscreen mode

Creating the Web UI

Generate a new Spring Boot project using Spring Initializr. You can configure the dependencies you need, but for this, we only need:

  • Ollama - Spring AI APIs for the local LLM
  • Vaadin - for Java web UI

Here is direct link to the configuration.

This will create a ready-to-run project that you can import into your Java IDE.

Adding Extras

To use Vaadin add-ons, configure the dependencies in your pom.xml. We want to use the Viritin add-on for handy Markdown streaming.



<dependency>
    <groupId>in.virit</groupId>
    <artifactId>viritin</artifactId>
    <version>2.8.14</version>
</dependency>


Enter fullscreen mode Exit fullscreen mode

Building the Web UI

We still need the UI. Create a MainView class to handle the chat UI and interaction with the local LLM. Injecting Spring beans into the Vaadin UI, this is all that is needed:



@Route("") // map view to the root
class MainView extends VerticalLayout {

    private final ArrayList<Message> chatHistory = new ArrayList<>();

    VerticalLayout messageList = new VerticalLayout();
    Scroller messageScroller = new Scroller(messageList);
    MessageInput messageInput = new MessageInput();

    MainView(StreamingChatClient chatClient) {
        add(messageScroller, messageInput);
        setSizeFull();
        setMargin(false);
        messageScroller.setSizeFull();
        messageInput.setWidthFull();

        // Add system message to help the AI to behave
        chatHistory.add(new SystemMessage("Only if the user asks you about Vaadin, reply in bro style. Always show a piece a code."));

        messageInput.addSubmitListener(ev -> {
            // Add use input as markdown message
            chatHistory.add(new UserMessage(ev.getValue()));
            messageList.add(new MarkdownMessage(ev.getValue(),"Me"));

            // Placeholder message for the upcoming AI reply
            MarkdownMessage reply = new MarkdownMessage("Assistant");
            messageList.add(reply);

            // Ask AI and stream back the reply to UI
            Prompt prompt = new Prompt(chatHistory);
            chatClient.stream(prompt)
                    .doOnComplete(() -> chatHistory.add(new AssistantMessage(reply.getMarkdown())))
                    .subscribe(cr -> reply.appendMarkdownAsync(cr.getResult().getOutput().getContent()));
            reply.scrollIntoView();
        });
    }
}


Enter fullscreen mode Exit fullscreen mode

You can run the application either by running the main Application.java class from your IDE or from the command line using Maven: `mvn spring-boot:run'.

Now we can chat with the Ollama Mistral model locally at localhost:8080

Ollama Web Chat UI

Conclusion

This was another one of those step-by-step guides that I wrote mostly for myself when setting up a small demo application. The full app is in GitHub (note the branch), if you wish to use it as a starting point for your own demos.

If you find it useful, let me know in the comments. Thanks!

Top comments (4)

Collapse
 
thinii profile image
thinii

Would it possible to use Testcontainers and not Docker? They support Ollama. java.testcontainers.org/modules/ol...

Collapse
 
samiekblad profile image
Sami Ekblad

Good idea! I haven't tried that, but why not. I don't think you can skip Docker, but instead use it from the Java app. I'm wondering how would it behave in application restart (during development you get those a lot)?

Collapse
 
samiekblad profile image
Sami Ekblad

I made some testing and with some tricks you can actually use Testcontainers. To keep the LLM models over restarts and expose a fixed port from Ollama you need some container configuration like this:

new OllamaContainer("ollama/ollama:0.1.48")
.withCreateContainerCmdModifier(cmd ->
{
cmd.withBinds(Bind.parse("ollama:/root/.ollama"));
cmd.withPortBindings(new PortBinding(Ports.Binding.bindPort(11434), new ExposedPort(11434)));
});

Collapse
 
tmsanghoclaptrinh profile image
Sáng Minh Trần