<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Brown</title>
    <description>The latest articles on DEV Community by David Brown (@davebrown1975).</description>
    <link>https://dev.to/davebrown1975</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F198946%2Fd475a0f4-201e-48d3-ac6d-d5a7b6272af1.jpeg</url>
      <title>DEV Community: David Brown</title>
      <link>https://dev.to/davebrown1975</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davebrown1975"/>
    <language>en</language>
    <item>
      <title>Building a multi-step AI agent in Java with Spring AI 2.0</title>
      <dc:creator>David Brown</dc:creator>
      <pubDate>Tue, 30 Jun 2026 19:02:21 +0000</pubDate>
      <link>https://dev.to/davebrown1975/building-a-multi-step-ai-agent-in-java-with-spring-ai-20-4nk3</link>
      <guid>https://dev.to/davebrown1975/building-a-multi-step-ai-agent-in-java-with-spring-ai-20-4nk3</guid>
      <description>&lt;p&gt;I wanted to try Spring AI's agentic tooling on something that resembles a real production project rather than the usual weather-API call, so I built an example Spring Boot API: a civic research assistant. You give it a plain-English issue and a UK postcode, and it works out the most effective way to raise that issue with Parliament. It uses an LLM (ChatGPT) along with the free UK postcode and Open Parliament APIs. The flow isn't dictated in code. We register a handful of @Tool methods (resolve the postcode, find the MP, search bills, find committees and open inquiries, check the voting record) and let the model decide which to call and in what order. It chains them itself and returns a final answer with a citation on every claim. The stack is Java 25, Spring Boot 4.1 and Spring AI 2.0.&lt;br&gt;
The &lt;a href="https://tucanoo.com/building-an-agentic-workflow-in-java-multi-step-ai-agents-with-spring-ai-and-tool-calling/" rel="noopener noreferrer"&gt;full tutorial&lt;/a&gt; walks through the Spring AI 2.0 tool-calling setup and what changed since 1.x, registering the tools, getting structured typed output back instead of free text, and a small guard that checks every citation actually came from a tool call so the model can't quietly invent a source. It's all runnable, with the complete code on GitHub.&lt;/p&gt;

&lt;p&gt;Full tutorial: &lt;a href="https://tucanoo.com/building-an-agentic-workflow-in-java-multi-step-ai-agents-with-spring-ai-and-tool-calling/" rel="noopener noreferrer"&gt;https://tucanoo.com/building-an-agentic-workflow-in-java-multi-step-ai-agents-with-spring-ai-and-tool-calling/&lt;/a&gt;&lt;br&gt;
Source: &lt;a href="https://github.com/tucanoo/spring-ai-civic-research-assistant" rel="noopener noreferrer"&gt;https://github.com/tucanoo/spring-ai-civic-research-assistant&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're using Spring AI's tool calling on anything that touches real data, I'd be interested in how you're handling grounding to keep the model from citing things it never fetched.&lt;/p&gt;

</description>
      <category>java</category>
      <category>ai</category>
      <category>springboot</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Big Beautiful Bot - A Spring Boot &amp; LLM Chatbot with SSE -&gt; Next.js</title>
      <dc:creator>David Brown</dc:creator>
      <pubDate>Fri, 26 Jun 2026 07:16:09 +0000</pubDate>
      <link>https://dev.to/davebrown1975/the-big-beautiful-bot-a-spring-boot-llm-chatbot-with-sse-nextjs-15p4</link>
      <guid>https://dev.to/davebrown1975/the-big-beautiful-bot-a-spring-boot-llm-chatbot-with-sse-nextjs-15p4</guid>
      <description>&lt;p&gt;There's not much material out there showing how to use SSE (Server-Sent Events) with a Spring Boot back end connected to an LLM to power a ChatGPT-style Next.js front end, so I put together a full tutorial on it, with the complete code repository as always.&lt;/p&gt;

&lt;p&gt;Tutorial -&amp;gt; &lt;a href="https://tucanoo.com/streaming-llm-responses-end-to-end-a-spring-boot-sse-backend-and-a-next-js-frontend/" rel="noopener noreferrer"&gt;https://tucanoo.com/streaming-llm-responses-end-to-end-a-spring-boot-sse-backend-and-a-next-js-frontend/&lt;/a&gt;&lt;br&gt;
Repo -&amp;gt; &lt;a href="https://github.com/tucanoo/streaming-llm-spring-next" rel="noopener noreferrer"&gt;https://github.com/tucanoo/streaming-llm-spring-next&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>springboot</category>
      <category>java</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Virtual Threads in Spring Boot 4: I rewrote a blocking service and measured everything</title>
      <dc:creator>David Brown</dc:creator>
      <pubDate>Sun, 21 Jun 2026 09:52:15 +0000</pubDate>
      <link>https://dev.to/davebrown1975/virtual-threads-in-spring-boot-4-i-rewrote-a-blocking-service-and-measured-everything-d83</link>
      <guid>https://dev.to/davebrown1975/virtual-threads-in-spring-boot-4-i-rewrote-a-blocking-service-and-measured-everything-d83</guid>
      <description>&lt;p&gt;I took one realistic blocking Spring Boot 4 service — a PostgreSQL query through HikariCP plus a downstream HTTP call — flipped spring.threads.virtual.enabled=true, and benchmarked exactly what changed: throughput, tail latency, and where the bottleneck went.&lt;/p&gt;

&lt;p&gt;TL;DR: ~6× throughput at 2,500 concurrent users from one flag — but the connection pool quietly becomes your new ceiling, so you have to resize it. I also measured the JEP 491 pinning change (the "avoid synchronized" advice is now out of date).&lt;/p&gt;

&lt;p&gt;Full write-up, raw data, charts and a reproducible repo on the Tucanoo blog&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://tucanoo.com/virtual-threads-in-spring-boot-4" rel="noopener noreferrer"&gt;https://tucanoo.com/virtual-threads-in-spring-boot-4&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>webperf</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Localised notifications with Firebase cloud messaging (FCM)</title>
      <dc:creator>David Brown</dc:creator>
      <pubDate>Wed, 09 Nov 2022 09:08:05 +0000</pubDate>
      <link>https://dev.to/davebrown1975/localised-notifications-with-firebase-cloud-messaging-fcm-ecn</link>
      <guid>https://dev.to/davebrown1975/localised-notifications-with-firebase-cloud-messaging-fcm-ecn</guid>
      <description>&lt;p&gt;If you need to send localised push notifications from a Java server side application to mobile devices with Firebase Cloud Messaging (FCM), whether your server side is Grails, Spring boot or any other Java based framework utilising the Firebase (Admin) SDK then search no more as it's not so clear in the official documentation.  Most examples focus on the REST or JS implementations.&lt;/p&gt;

&lt;p&gt;In my use case, I wanted to alert users subscribing to a specific Topic of a particular event.  Users of this app are distributed globally so it was important to localise the messages depending on the users locale according to their device.  From the server side, I just want to generate the notification and let Firebase's servers handle the notifications to each device subscribed to the topic and then the device it self display a locales message, both the title and subtitle,  on both Android and IOS devices. &lt;/p&gt;

&lt;p&gt;Fortunately Firebase lets us do this by specifying localised 'keys', instead of specifying the title and body.    However finding an example was more of a struggle as the documentation is somewhat lacking.&lt;/p&gt;

&lt;p&gt;What we have to do is establish Options objects for each platform, i.e. one for Android and one for Apple devices and then deep within nested Builders we can finally set the localised keys.  These then can be interpreted from the resources within the mobile App itself and will be displayed to the user, both when the app is in the foreground AND also when it's in the background.&lt;/p&gt;

&lt;p&gt;So without further ado,  let's look at the code:  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: I'm omitting the rest of the app code assuming you already know how to setup Firebase etc and just need to see how to generate the notification.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void sendLocalisedNotification(String topic, String titleKey, String bodyKey) {
        // Set localisation key for Android
        AndroidConfig androidConfig = AndroidConfig.builder()
            .setNotification(
                AndroidNotification.builder()
                    .setTitleLocalizationKey(titleKey)
                    .setBodyLocalizationKey(bodyKey)
                    .build()
            ).build()

        // Set localisation key for Apple devices
        ApnsConfig apnsConfig = ApnsConfig.builder()
            .setAps(Aps.builder()
                .setAlert(ApsAlert.builder()
                    .setTitleLocalizationKey(titleKey)
                    .setSubtitleLocalizationKey(bodyKey)
                    .build()
                ).build()
            ).build()

        Message message = Message.builder()
            .setTopic(topic)
            .setAndroidConfig(androidConfig)
            .setApnsConfig(apnsConfig)
            .build();

        // And then send the message to the devices subscribed to the provided topic.
        try {
            String response = FirebaseMessaging.getInstance().send(message);

            // Response is a message ID string.
            log.debug("Firebase message $topic sent: " + response);
        } catch (Exception ex) {
            log.warn("Firebase message $topic failed: " + ex.message);
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So that's the gist of it, this method can be called with the topic we want to publish to, the title key and the body key.&lt;/p&gt;

&lt;p&gt;I hope this helps save someone time discovering how to accomplish localised messages under a Java environment using the FCM SDK.  &lt;/p&gt;

&lt;p&gt;Dave / &lt;a href="https://tucanoo.com" rel="noopener noreferrer"&gt;Tucanoo Solutions&lt;/a&gt;&lt;/p&gt;

</description>
      <category>firebase</category>
      <category>java</category>
      <category>notifications</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Super Fast Prototyping with Grails Tutorial Available</title>
      <dc:creator>David Brown</dc:creator>
      <pubDate>Wed, 12 Feb 2020 08:39:54 +0000</pubDate>
      <link>https://dev.to/davebrown1975/super-fast-prototyping-with-grails-tutorial-available-1aij</link>
      <guid>https://dev.to/davebrown1975/super-fast-prototyping-with-grails-tutorial-available-1aij</guid>
      <description>&lt;p&gt;One of the greatest benefits of the Grails framework is how it allows you to put together a Proof Of Concept(POC) or a web app prototype in such a short period time.&lt;/p&gt;

&lt;p&gt;In a current world where there is lots of focus on UI frameworks and microservice architectures, sometimes, you just need to build something quickly without worrying about different front and backend layers.  &lt;/p&gt;

&lt;p&gt;Grails allows you to build apps fast, but with the benefit of sitting on top of the most robust Java-based libraries in existence, Spring, Hibernate, etc. etc.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll see how to build a simple CRM backed by a H2 in-memory database, prepopulating itself with 1000 fictitious records.&lt;/p&gt;

&lt;p&gt;The user is provided with basic CRUD screens,  create, edit, and a rich Datatables based list screen to allow filtering, sorting and ajax driven paging of the customer records.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tucanoo/crm_grails" rel="noopener noreferrer"&gt;Download full source on github&lt;/a&gt; Download the full source on github &lt;/p&gt;

&lt;p&gt;and &lt;a href="https://www.tucanoo.com/how-to-build-a-simple-crm-with-grails-4/" rel="noopener noreferrer"&gt;Read the full tutorial&lt;/a&gt;&lt;/p&gt;

</description>
      <category>grails</category>
      <category>tutorial</category>
      <category>groovy</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
