<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/i-let-ai-rebuild-a-dead-java-desktop-app-for-the-web-here-s-where-it-broke--rgv1bqrix" -->

---
title: I let AI rebuild a dead Java desktop app for the web....
description: A developer attempts to rebuild RSSOwl, a classic Java/SWT desktop RSS reader, as a multi-user web app using Vaadin 25 and Claude Code as the AI assistant. The...
canonical: https://daily.dev/posts/i-let-ai-rebuild-a-dead-java-desktop-app-for-the-web-here-s-where-it-broke--rgv1bqrix
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: I let AI rebuild a dead Java desktop app for the web. Here's where it broke. | daily.dev
og:description: A developer attempts to rebuild RSSOwl, a classic Java/SWT desktop RSS reader, as a multi-user web app using Vaadin 25 and Claude Code as the AI assistant. The...
og:url: https://daily.dev/posts/i-let-ai-rebuild-a-dead-java-desktop-app-for-the-web-here-s-where-it-broke--rgv1bqrix
og:image: https://api.daily.dev/og/posts/rgV1bQRIX.png
og:image:alt: I let AI rebuild a dead Java desktop app for the web. Here's where it broke.
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# I let AI rebuild a dead Java desktop app for the web. Here's where it broke.

**[Vaadin](https://daily.dev/sources/vaadin)** · 14 min read · 1 upvotes · 0 comments

## Summary

A developer attempts to rebuild RSSOwl, a classic Java/SWT desktop RSS reader, as a multi-user web app using Vaadin 25 and Claude Code as the AI assistant. The experiment reveals what AI handles well (table sorting, reactive Signals-based selection, context menus, dramatic code reduction) and where it fails (hallucinating APIs from pre-25 training data, silent styling bugs, subtle sorting edge cases, fabricated default values). Key lessons: always point the AI at live framework docs via an MCP server rather than relying on its stale training data, verify behavior by running the app not reading diffs, and expect the AI to nail structure while missing fidelity details that require human domain knowledge. Some desktop features (Eclipse plugin menus, embedded browser, Google Reader sync) have no web equivalent at all. The resulting app — with OIDC login via Keycloak, full-text search, and multi-user feed lists — ended up more complete than planned, but required constant human oversight to catch correctness gaps.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://blog.vaadin.com/i-let-ai-rebuild-a-dead-java-desktop-app-for-the-web.-heres-where-it-broke>

## Questions this post answers

### Why does an AI coding assistant write Vaadin code that doesn't compile against Vaadin 25?

The model's training data has a cutoff date earlier than the Vaadin 25 release, so it has never seen the real API and instead pattern-matches on older Vaadin 24-era knowledge, producing confident but wrong code such as deprecated constructors, moved methods, and pre-Signals listener patterns. The fix is querying Vaadin's MCP server, which feeds the model live, current documentation instead of relying on stale training data.

_Anyone pairing an AI assistant with a fast-moving framework like Vaadin can compare notes on live-docs workflows via daily.dev._

### How do I read a Vaadin Signal's value from a background thread or timer without it throwing an exception?

Calling signal.get() from a plain callback or background timer throws, because get() sets up reactive dependency tracking and is only legal inside an effect. Use signal.peek() instead when reading a Signal's current value outside of a Signal.effect() context, such as from a timer callback.

_Developers debugging Vaadin 25 Signals gotchas can track framework-specific fixes and discussions on daily.dev._

### Why doesn't the --vaadin-grid-cell-background CSS custom property change a Grid row's background color?

With Vaadin's current Aura theme, the cell background is painted separately from where that custom property applies, so setting --vaadin-grid-cell-background has no visible effect even though the documentation recommends it. The workaround is applying background-color with !important directly to the cell's ::part(...) selector, found by inspecting the live shadow DOM rather than trusting the documented approach.

_Developers styling Vaadin Grid rows can compare theme-specific CSS workarounds like this one on daily.dev._

## Similar posts on daily.dev

- [Java Software Development in an AI-First World](https://daily.dev/posts/java-software-development-in-an-ai-first-world-jiwkvejsp) · Vaadin · 0 upvotes · 0 comments
- [I Tried Vibing an RSS Reader and My Dreams Did Not Come True](https://daily.dev/posts/i-tried-vibing-an-rss-reader-and-my-dreams-did-not-come-true-nvqisthwm) · Lobsters · 0 upvotes · 0 comments
- [Spring AI 2.0 in Practice: Adding LLM Features to a Java Web App](https://daily.dev/posts/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app-kqfaxawkj) · Vaadin · 1 upvotes · 0 comments

---

Tags: [#java](https://daily.dev/tags/java), [#ai-coding](https://daily.dev/tags/ai-coding), [#vaadin](https://daily.dev/tags/vaadin)

[View this post on daily.dev](https://daily.dev/posts/i-let-ai-rebuild-a-dead-java-desktop-app-for-the-web-here-s-where-it-broke--rgv1bqrix)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"I let AI rebuild a dead Java desktop app for the web. Here's where it broke.","url":"https://daily.dev/posts/i-let-ai-rebuild-a-dead-java-desktop-app-for-the-web-here-s-where-it-broke--rgv1bqrix","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/i-let-ai-rebuild-a-dead-java-desktop-app-for-the-web-here-s-where-it-broke--rgv1bqrix"},"datePublished":"2026-07-16T08:43:18.132Z","dateModified":"2026-09-14T06:25:56.275Z","description":"A developer attempts to rebuild RSSOwl, a classic Java/SWT desktop RSS reader, as a multi-user web app using Vaadin 25 and Claude Code as the AI assistant. The...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/edc72773bfb2cfbc710be61a9c1630e7?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/edc72773bfb2cfbc710be61a9c1630e7?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Vaadin","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Vaadin","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/052f2fad97c542a19c754e60d6264e45","url":"https://daily.dev/sources/vaadin"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/i-let-ai-rebuild-a-dead-java-desktop-app-for-the-web-here-s-where-it-broke--rgv1bqrix","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"java,ai-coding,vaadin","timeRequired":"PT14M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Vaadin","item":"https://daily.dev/sources/vaadin"},{"@type":"ListItem","position":3,"name":"I let AI rebuild a dead Java desktop app for the web. Here's where it broke."}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/i-let-ai-rebuild-a-dead-java-desktop-app-for-the-web-here-s-where-it-broke--rgv1bqrix#faq","mainEntity":[{"@type":"Question","name":"Why does an AI coding assistant write Vaadin code that doesn't compile against Vaadin 25?","acceptedAnswer":{"@type":"Answer","text":"The model's training data has a cutoff date earlier than the Vaadin 25 release, so it has never seen the real API and instead pattern-matches on older Vaadin 24-era knowledge, producing confident but wrong code such as deprecated constructors, moved methods, and pre-Signals listener patterns. The fix is querying Vaadin's MCP server, which feeds the model live, current documentation instead of relying on stale training data. Anyone pairing an AI assistant with a fast-moving framework like Vaadin can compare notes on live-docs workflows via daily.dev."}},{"@type":"Question","name":"How do I read a Vaadin Signal's value from a background thread or timer without it throwing an exception?","acceptedAnswer":{"@type":"Answer","text":"Calling signal.get() from a plain callback or background timer throws, because get() sets up reactive dependency tracking and is only legal inside an effect. Use signal.peek() instead when reading a Signal's current value outside of a Signal.effect() context, such as from a timer callback. Developers debugging Vaadin 25 Signals gotchas can track framework-specific fixes and discussions on daily.dev."}},{"@type":"Question","name":"Why doesn't the --vaadin-grid-cell-background CSS custom property change a Grid row's background color?","acceptedAnswer":{"@type":"Answer","text":"With Vaadin's current Aura theme, the cell background is painted separately from where that custom property applies, so setting --vaadin-grid-cell-background has no visible effect even though the documentation recommends it. The workaround is applying background-color with !important directly to the cell's ::part(...) selector, found by inspecting the live shadow DOM rather than trusting the documented approach. Developers styling Vaadin Grid rows can compare theme-specific CSS workarounds like this one on daily.dev."}}]}
```

