Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
149616 stories
·
33 followers

Scaling Kotlin Adoption Across Your Organization

1 Share

Guest post by Urs Peter, Senior Software Engineer and JetBrains-certified Kotlin Trainer. For readers who’d like a more structured way to build Kotlin skills, Urs also leads the Kotlin Upskill Program at Xebia Academy.

This is the fifth post in The Ultimate Guide to Successfully Adopting Kotlin in a Java-Dominated Environment, a series that follows how Kotlin adoption grows among real teams, from a single developer’s curiosity to company-wide transformation.

All parts in the series:

  1. Getting Started With Kotlin for Java Developers
  2. Evaluating Kotlin in Real Projects
  3. Growing Kotlin Adoption in Your Company
  4. Helping Decision-Makers Say Yes to Kotlin
  5. Scaling Kotlin Adoption Across Your Organization

Success Factors for Large-Scale Kotlin Adoption

Gaining developer buy-in and management support for Kotlin is a significant milestone, but it’s not the finish line. The real challenge begins when you’re faced with existing Java codebases that need to coexist with or transition to Kotlin. How do you navigate this hybrid world effectively?

The key to managing legacy codebases is developing a strategy that aligns with your organizational goals and operational realities. Here’s a proven approach that has worked out well in practice.

Application lifecycle strategy

Different applications require different approaches based on their lifecycle phase. Let’s examine three distinct categories:

End-of-life applications

Strategy: Leave them alone.

If an application is scheduled for retirement, there’s no business case for migration. Keep these systems in Java and focus your energy where it matters most. The cost of migration will never be justified by the remaining lifespan of the application.

New systems

Strategy: Default to Kotlin.

In organizations where Kotlin adoption is complete, greenfield projects naturally start with Kotlin. If the adoption process is in progress, teams often get the choice between Java and Kotlin. Choose wisely ;-).

Active applications

Strategy: Pragmatic, feature-driven migration.

Active applications are the ones that require careful consideration: Rewriting for the sake of rewriting is a tough sell to your Product Owner. Instead, combine migration efforts with new feature development. This approach provides tangible business value while modernizing your codebase. The different attack angles we already discussed in the section: Extend/Convert an existing Java application.

Java-to-Kotlin conversion approaches

When converting Java to Kotlin, you have several options, each with distinct trade-offs:

1. Complete rewrite

Best for: Small codebases 

Challenge: Time-intensive for larger systems

Rewriting a codebase from scratch gives you the cleanest, most idiomatic Kotlin code. This approach is suitable for small codebases, like a MicroService. For large codebases, this approach generally tends to be prohibitively expensive.

2. IDE auto-conversion with manual refinement

Best for: Medium codebases with dedicated refactoring time

Challenge: Manual refinements are mandatory 

IntelliJ IDEA’s Convert Java to Kotlin feature provides a literal translation that’s far from idiomatic. Consider this example:

Take 1: 

Java

record Developer(
       String name,
       List<String> languages,
       String name,
) {}

Raw auto-conversion result:

Kotlin

@JvmRecord
data class Developer(
   val name: String?,
   val languages: MutableList<String?>?
)

This conversion has several issues:

  • Everything becomes nullable (overly defensive).
  • Java Collections become Kotlin’s MutableList instead of  Kotlin’s default read-only List.

Improving the conversion with jspecify annotations:

Luckily, for the conversion of all Java types to Nullable types in Kotlin, there is a remedy in the form of @NonNull/@Nullable annotations. Different options are available; the most modern one is jspecify, which has recently also been officially supported by Spring:

<dependency>
   <groupId>org.jspecify</groupId>
   <artifactId>jspecify</artifactId>
   <version>1.0.0</version>
</dependency>

implementation("org.jspecify:jspecify:1.0.0")

With jspecify, we can annotate the Java code with @Nullable and @NonNull.

Take 2: 

Java

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;

record Developer(
       @NonNull String name, 
       @NonNull List<@NonNull String> languages,
       @Nullable String email
) {}

Now the auto-conversion produces much better results:

Kotlin

@JvmRecord
data class Developer(
   //😃 non-null as requested
   val name: String, 
   //😃 both, collection and type are non-null
  val languages: MutableList<String>,
   //😃 nullable as requested
  val email: String?, 
)

Limitations of the auto conversion approach:

Even with jspecify annotations, complex Java patterns don’t translate well. Consider this auto-converted code example shown in section: 3. No more checked Exceptions, yet safer code in Kotlin:

Kotlin

fun downloadAndGetLargestFile(urls: MutableList<String>): String? {
     //🤨 using Stream, instead of Kotlin Collections
     val contents = urls.stream().map { urlStr: String? ->
     //🤨 still using Optional, rather than Nullable types
     //🤨 var but we want val!
     var optional: Optional<URL>
     //🤨 useless try-catch, no need to catch in Kotlin
     try {
         optional = Optional.of(URI(urlStr).toURL())
     } catch (e: URISyntaxException) {
           optional = Optional.empty<URL>()
     } catch (e: MalformedURLException) {
           optional = Optional.empty<URL>()
     }
     optional
   }.filter { it!!.isPresent() }//🤨 discouraged !! to force conversion to non-null
    .map {it.get() }
    .map { url: URL ->
      //🤨 useless try-catch, no need to catch in Kotlin
      try {
        url.openStream().use { `is` -> 
           String(`is`.readAllBytes(), StandardCharsets.UTF_8)
        }
      } catch (e: IOException) {
         throw IllegalArgumentException(e)
       }
    }.toList()
   //🤨 usage of Java collections…
   return Collections.max(contents)
}

The autoconversion is far away from the desired, idiomatic result:

Kotlin

fun downloadAndGetLargestFile(urls: List<String>): String? =
   urls.mapNotNull {
       runCatching { URI(it).toURL() }.getOrNull()
   }.maxOfOrNull{ it.openStream().use{ it.reader().readText() } }

The auto-conversion provides a starting point, but significant manual refinement and knowledge of idiomatic Kotlin is required to achieve truly idiomatic Kotlin.

3. AI-assisted conversion

Best for: Larger codebases with robust testing infrastructure

Challenge: Manual review required

AI can potentially produce more idiomatic results than basic auto-conversion, but success requires careful preparation:

Prerequisites:

  1. Comprehensive testing coverage: Since LLMs are unpredictable, you need reliable tests to catch AI hallucinations.
  2. Well-crafted system prompts: Create detailed instructions for idiomatic Kotlin conversions that are aligned with your standards. You can use this system prompt as a starting point.
  3. Extensive code review: AI output requires a thorough review for logical and idiomatic correctness, which can be mentally taxing for large codebases.

Using the proposed system prompt to guide the conversion, the result is quite satisfying, yet not perfect:

Kotlin

fun downloadAndGetLargestFile(urls: List<String>): String? {
   val contents = urls
      .mapNotNull { 
            urlStr -> runCatching { URI(urlStr).toURL() }.getOrNull() 
      }.mapNotNull { url -> runCatching { 
            url.openStream().use { it.readAllBytes().toString(UTF_8)
         } 
      }.getOrNull() }

   return contents.maxOrNull()
}

4. Auto-conversion at scale

Best for: Massive codebases requiring systematic transformation

Currently, there’s no official tooling for converting Java codebases to idiomatic Kotlin at scale. However, both Meta and Uber have successfully tackled this challenge for their Android codebases using approaches that work equally well for backend applications. The following documentation and talks provide insights into how Meta and Uber approach this quest:

Meta’s approach:

Meta

Uber’s approach:

Uber

  • Strategy: Rule-based, deterministic transformation using AI to generate conversion rules
  • Resource: KotlinConf presentation

Both companies succeeded by creating systematic, repeatable processes rather than relying on manual conversion or simple automation. Their rule-based approaches ensure consistency and quality across millions of lines of code.

Important: Converting Java to Kotlin at scale introduces a challenge on the social level: to be reliable, you still want ‘the human in the loop’ reviewing the generated code. However, if not planned carefully, Engineers can easily be overwhelmed by the flood of pull requests resulting from the automated conversion. Therefore, the social impact needs to be considered carefully. 

Remember, successful large-scale Kotlin adoption isn’t just about converting code – it’s about building team expertise, establishing coding standards, and creating sustainable processes that deliver long-term value to your organization.

Short recap on when to use which approach:

  • Small application or being rewritten anyway?
    Rewrite in Kotlin (1)
  • Medium codebases with dedicated refactoring time or team learning Kotlin?
    Intellij IDEA Auto-Conversion + refine (start with tests first) (2)
  • Mid/large code with repeated patterns and good tests?
    AI-assisted approach (3)
  • Org-level migration to Kotlin across many services?
    Auto-Conversion at scale with concrete plan (platform-led) (4)

Unlock Kotlin’s full potential

Kotlin makes developers productive fast. Its concise syntax, safety features, and rich standard library help many developers write better code within weeks – often through self-study or on-the-job learning. But without guidance, many fall into the trap of using Kotlin in a Java-like way: sticking to mutable structures, verbose patterns, and missing out on idiomatic features.

Reaching the next level

Reaching the next level – embracing immutability, expression-oriented code, DSLs, and structured concurrency with Coroutines (with or without Virtual Threads) – is where many developers get stuck.

At this stage, I’ve found that external training makes a far greater difference than self-study. Even developers with years of Kotlin experience often benefit from focused coaching to adopt idiomatic patterns and unlock the language’s full potential.

Kotlin Heroes

To Kotlin or Not to Kotlin: What Kind of Company Do You Want to Be?

Ultimately, the decision to adopt Kotlin reflects your engineering culture. Do you value the:

  • Traditional approach (Java): Conservative, ceremonial, stable.
  • Progressive approach (Kotlin): Pragmatic, modern, adaptive.

Both have their merits. Java will get the job done. Kotlin will likely get it done better, with happier developers and fewer bugs. The question isn’t whether Kotlin is better – it’s whether your organization is ready to invest in being better.

The journey from that first Kotlin test to organization-wide adoption isn’t always smooth, but with the right approach, it’s remarkably predictable. Start small, prove value, build community, and scale thoughtfully.

Your developers – current and future – will thank you.

Urs Peter

Urs is a seasoned software engineer, solution architect, conference speaker, and trainer with over 20 years of experience in building resilient, scalable, and mission-critical systems, mostly involving Kotlin and Scala.

Besides his job as a consultant, he is also a passionate trainer and author of a great variety of courses ranging from language courses for Kotlin and Scala to architectural trainings such as Microservices and Event-Driven Architectures.

As a people person by nature, he loves to share knowledge and inspire and get inspired by peers on meetups and conferences. Urs is a JetBrains certified Kotlin trainer.

Read the whole story
alvinashcraft
18 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Episode 502 - How to Find a Job on LinkedIn - Solo Show

1 Share

if you want to check out all the things ⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠torc.dev⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠ has going on head to ⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠linktr.ee/taylordesseyn⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠ for more information on how to get plugged in!





Download audio: https://anchor.fm/s/ce6260/podcast/play/111435569/https%3A%2F%2Fd3ctxlq1ktw2nl.cloudfront.net%2Fstaging%2F2025-10-20%2F930511e6-4a49-98f5-223d-83272fabb105.mp3
Read the whole story
alvinashcraft
18 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

AI Assisted Coding: From Designer to Solo Developer - Building Production Apps with AI With Elina Patjas

1 Share

AI Assisted Coding: From Designer to Solo Developer - Building Production Apps with AI

In this special episode, Elina Patjas shares her remarkable journey from designer to solo developer, building LexieLearn—an AI-powered study tool with 1,500+ users and paying customers—entirely through AI-assisted coding. She reveals the practical workflow, anti-patterns to avoid, and why the future of software might not need permanent apps at all.

The Two-Week Transformation: From Idea to App Store

"I did that, and I launched it to App Store, and I was like, okay, so… If I can do THIS! So, what else can I do? And this all happened within 2 weeks."

 

Elina's transformation happened fast. As a designer frustrated with traditional software development where maybe 10% of your original vision gets executed, she discovered Cursor and everything changed. Within two weeks, she went from her first AI-assisted experiment to launching a complete app in the App Store. The moment that shifted everything was realizing that AI had fundamentally changed the paradigm from "writing code" to "building the product." This wasn't about learning to code—it was about finally being able to execute her vision 100% the way she wanted it, with immediate feedback through testing.

Building LexieLearn: Solving Real Problems for Real Users

"I got this request from a girl who was studying, and she said she would really appreciate to be able to iterate the study set... and I thought: "That's a brilliant idea! And I can execute that!" And the next morning, it was 9.15, I sent her a screen capture."

 

Lexie emerged from Elina's frustration with ineffective study routines and gamified edtech that didn't actually help kids learn. She built an AI-powered study tool for kids aged 10-15 that turns handwritten notes into adaptive quizzes revealing knowledge gaps—private, ad-free, and subscription-based. What makes Lexie remarkable isn't just the technology, but the speed of iteration. When a user requested a feature, Elina designed and implemented it overnight, sending a screen capture by 9:15 AM the next morning. This kind of responsiveness—from customer feedback to working feature in hours—represents a fundamental shift in how software can be built. Today, Lexie has over 1,500 users with paying customers, proving that AI-assisted development isn't just for prototypes anymore.

The Workflow: It's Not Just "Vibing"

"I spend 30 minutes designing the whole workflow inside my head... all the UX interactions, the data flow, and the overall architectural decisions... so I spent a lot of time writing a really, really good spec. And then I gave that to Claude Code."

 

Elina has mixed feelings about the term "vibecoding" because it suggests carelessness. Her actual workflow is highly disciplined. She spends significant time designing the complete workflow mentally—all UX interactions, data flow, and architectural decisions—then writes detailed specifications. She often collaborates with Claude to write these specs, treating the AI as a thinking partner. Once the spec is clear, she gives it to Claude Code and enters a dialogue mode: splitting work into smaller tasks, maintaining constant checkpoints, and validating every suggestion. She reads all the code Claude generates (32,000 lines client-side, 8,000 server-side) but doesn't write code herself anymore. This isn't lazy—it's a new kind of discipline focused on design, architecture, and clear communication rather than syntax.

Reading Code vs. Writing Code: A New Skill Set

"AI is able to write really good code, if you just know how to read it... But I do not write any code. I haven't written a single line of code in a long time."

 

Elina's approach reveals an important insight: the skill shifts from writing code to reading and validating it. She treats Claude Code as a highly skilled companion that she needs to communicate with extremely well. This requires knowing "what good looks like"—her 15 years of experience as a designer gives her the judgment to evaluate what the AI produces. She maintains dialogue throughout development, using checkpoints to verify direction and clarify requirements. The fast feedback loop means when she fails to explain something clearly, she gets immediate feedback and can course-correct instantly. This is fundamentally different from traditional development where miscommunication might not surface until weeks later.

The Anti-Pattern: Letting AI Run Rampant

"You need to be really specific about what you want to do, and how you want to do it, and treat the AI as this highly skilled companion that you need to be able with."

 

The biggest mistake Elina sees is treating AI like magic—giving vague instructions and expecting it to "just figure it out." This leads to chaos. Instead, developers need to be incredibly specific about requirements and approach, treating AI as a skilled partner who needs clear communication. The advantage is that the iteration loop is so fast that when you fail to explain something properly, you get feedback immediately and can clarify. This makes the learning curve steep but short. The key is understanding that AI amplifies your skills—if you don't know what good architecture looks like, AI won't magically create it for you.

Breaking the Gatekeeping: One Person, Ten Jobs

"I think that I can say that I am a walking example of what you can do, if you have the proper background, and you know what good looks like. You can do several things at a time. What used to require 10 people, at least, to build before."

 

Elina sees herself as living proof that the gatekeeping around software development is breaking down. Someone with the right background and judgment can now do what previously required a team of ten people. She's passionate about others experiencing this same freedom—the ability to execute their vision without compromise, to respond to user feedback overnight, to build production-quality software solo. This isn't about replacing developers; it's about expanding who can build software and what's possible for small teams. For Elina, working with a traditional team would actually slow her down now—she'd spend more time explaining her vision than the team would save through parallel work.

The Future: Intent-Based Software That Emerges and Disappears

"The software gets built in an instance... it's going to this intent-based mode when we actually don't even need apps or software as we know them."

 

Elina's vision for the future is radical: software that emerges when you need it and disappears when you don't. Instead of permanent apps, you'd have intent-based systems that generate solutions in the moment. This shifts software from a product you download and learn to a service that materializes around your needs. We're not there yet, but Elina sees the trajectory clearly. The speed at which she can now build and modify Lexie—overnight feature implementations, instant bug fixes, continuous evolution—hints at a future where software becomes fluid rather than fixed.

Getting Started: Just Do It

"I think that the best resource is just your own frustration with some existing tools... Just open whatever tool you're using, is it Claude or ChatGPT and start interacting and discussing, getting into this mindset that you're exploring what you can do, and then just start doing."

 

When asked about resources, Elina's advice is refreshingly direct: don't look for tutorials, just start. Let your frustration with existing tools drive you. Open Claude or ChatGPT and start exploring, treating it as a dialogue partner. Start building something you actually need. The learning happens through doing, not through courses. Her own journey proves this—she went from experimenting with Cursor to shipping Lexie to the App Store in two weeks, not because she found the perfect tutorial, but because she just started building. The tools are good enough now that the biggest barrier isn't technical knowledge—it's having the courage to start and the judgment to evaluate what you're building.

 

About Elina Patjas

 

Elina is building Lexie, an AI-powered study tool for kids aged 10–15. Frustrated by ineffective "read for exams" routines and gamified edtech fluff, she designed Lexie to turn handwritten notes into adaptive quizzes that reveal knowledge gaps—private, ad-free, and subscription-based. Lexie is learning, simplified.

 

You can link with Elina Patjas on LinkedIn.





Download audio: https://traffic.libsyn.com/secure/scrummastertoolbox/20251124_Elina_Patjas_M.mp3?dest-id=246429
Read the whole story
alvinashcraft
19 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Dan Clarke: Personal Productivity - Episode 377

1 Share

Dan Clarke is a seasoned software consultant, Microsoft MVP, and founder of Everstack Ltd. Dan is widely known for his contributions to the .NET ecosystem and hosts the Unhandled Exception Podcast.  With a background in DevOps, Azure, and developer tooling, Dan brings a thoughtful, systems-level perspective to software craftsmanship. His work spans technical education, community leadership, and content creation—from blog posts and newsletters to YouTube tutorials and conference talks. 

Dan resides in the UK and when he isn't programming, he enjoys daily weightlifting, playing the guitar, and a past life of skydiving and motorcycling.


Mentioned in this Episode:

Clear Measure Way

Architect Forum

Software Engineer Forum

Dan Clarke Website 

Dan's Podcast 

Dan's Newsletter 

Dan's Youtube

Dan's Blog 

Dan's Linkedin 

Want to Learn More?

Visit AzureDevOps.Show for show notes and additional episodes.





Download audio: https://traffic.libsyn.com/clean/secure/azuredevops/Episode_377.mp3?dest-id=768873
Read the whole story
alvinashcraft
19 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

🎉Announcing the HL7 connector for Azure Logic Apps Standard and Hybrid (Public Preview)

1 Share

We’re excited to announce the Public Preview of the HL7 connector for Azure Logic Apps, empowering healthcare organizations to seamlessly integrate clinical applications and automate data exchange using industry-standard HL7 protocols.

Why HL7 Integration Matters

Healthcare organizations are complex ecosystems, with departments such as admissions, laboratories, nursing stations, and billing all generating and consuming critical patient data. Efficient, secure, and standardized data exchange is essential for delivering quality care and streamlining operations.

HL7 Connector: Key Capabilities

  • Simplified healthcare application integration with HL7-specific adapters and schemas.
  • Standardized clinical data interchange between diverse medical applications.
  • Automated communication processes to minimize manual intervention.
  • End-to-end business process support for scenarios like admissions, discharge, and transfer, using publisher/subscriber patterns.

Typical Scenarios

  1. End-to-End Integration: Publishers (e.g., Admissions Discharge and Transfer systems) send HL7 messages to subscribers (Hospital Information System, Pharmacy System). Azure Logic Apps processes, validates, reformats, and routes these messages, with acknowledgments sent back to publishers.
  2. Interrogative (Query/Response): Line-of-business applications can query other systems (e.g., requesting lab results from the Hospital Information System), with Azure Logic Apps managing routing and responses.

HL7 Encode/Decode actions

The HL7 connector provides native parsing and serialization of HL7 messages. It provides a Decode action that receives an HL7 message to decode in flat file format to produce an XML file, and an Encode action that receives a message to encode, with a header to encode to produce a Flat file. 

 

Decode

  • Input: Flat file HL7 message.
  • Output: Decoded XML message content and XML header content.

 

 

Encode

  • Input: XML message and header content.
  • Output: Encoded HL7 flat file message.

Important Considerations

  • HL7 Message Schemas: Supports HL7 v2.X flat-file and XML schemas.
  • Schema Management: Upload BizTalk schemas directly into integration accounts for seamless migration.
  • Hybrid Deployment: Integration accounts connect to Azure.
  • Message Processing: Logic Apps currently supports single message processing, with batching planned for future updates.
  • Multipart Handling: Logic Apps exposes header, body, and custom segments as first-class outputs, simplifying orchestration compared to BizTalk’s multipart pipelines.
  • Connector Availability: HL7 is available for both hybrid and Logic App Standard.
  • Integration accounts: Currently we only support uploading schemas in Integration accounts.

Announcing MLLP Private Preview

We’re pleased to announce that MLLP support is now available as a private preview. MLLP Adapter: Enables HL7 messaging over the Minimal Lower Layer Protocol (MLLP). MLLP is available only in hybrid due to port restrictions in app services.

Customers interested in early access and providing feedback can sign up via this survey: Private bundle for MLLP request

Get Started

To learn more about the HL7 connector and how it can transform your healthcare integration workflows, visit our documentation at Integrate Healthcare Systems with HL7 in Standard Workflows | Microsoft Learn.

 

Video explaining the features of the new HL7 connector

 

 

Read the whole story
alvinashcraft
19 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Mastering Kestrel: From Configuration to Cloud

1 Share


Read the whole story
alvinashcraft
19 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories