[{"data":1,"prerenderedAt":560},["ShallowReactive",2],{"nav-categories":3,"post-\u002Fblog\u002F2026\u002Fkotlinconf-2026-day-2":8,"all-posts-nav":481,"all-tags":510},{"pinned":4,"overflow":7},[5,6],"Technology","Security",[],{"id":9,"title":10,"body":11,"category":5,"date":463,"description":464,"extension":465,"featured":466,"image":467,"imageCredit":468,"imageCreditUrl":468,"meta":469,"navigation":119,"path":470,"public":119,"publish":468,"seo":471,"stem":472,"tags":473,"__hash__":480},"posts\u002Fblog\u002F2026\u002Fkotlinconf-2026-day-2.md","KotlinConf 2026 - Day 2 Impressions",{"type":12,"value":13,"toc":450},"minimark",[14,18,21,26,32,35,38,42,47,50,53,56,59,62,66,71,79,150,165,168,171,174,177,201,204,209,213,218,231,234,237,241,246,252,259,262,266,271,274,281,284,287,290,294,299,302,306,312,316,322,325,389,392,399,410,419,422,426,430,433,436,439,446],[15,16,17],"p",{},"KotlinConf 2026 continued today at the ICM, Internationales Congress Center\nMesse München. Day two went deeper into language-level topics, covering\nexperimental features coming in future Kotlin releases, idiomatic server-side\npatterns with Spring Boot 4, and the accelerating conversation around AI and\nagents in the Kotlin ecosystem.",[15,19,20],{},"Day two was more outward-facing, a look at what the community is building and\nwhere JetBrains is taking the language.",[22,23,25],"h2",{"id":24},"idiomatic-kotlin-applications-with-spring-boot-4","Idiomatic Kotlin Applications With Spring Boot 4",[15,27,28],{},[29,30,31],"em",{},"Sébastien Deleuze, Spring Framework core committer",[15,33,34],{},"A practical tour of idiomatic Kotlin with Spring Boot 4, covering a wide surface\narea from null-safe APIs to observability and persistence. Dense with short\nexamples and actionable recipes.",[15,36,37],{},"Full disclosure, I'm not as well versed in Spring as other JVM based frameworks,\nso some specifics did not find their soft landing as well as other topics, which\nis a \"me\" problem more than a talk problem. Worth watching the recording if\nSpring is something in your tool belt.",[22,39,41],{"id":40},"eval-driven-development","Eval-Driven Development",[15,43,44],{},[29,45,46],{},"Urs Peter, Senior Software Engineer & JetBrains certified Kotlin trainer",[15,48,49],{},"Urs gives talks with real commitment, and it's been engaging content across both\nKotlinConf visits for me. This one was about bringing reliability to agentic\nsystems, and the central argument was straightforward: probabilistic systems\nneed their own version of test-driven development.",[15,51,52],{},"The talk introduced Eval-Driven Development as a systematic approach to testing\nAI agents at multiple layers. Schema validation, tool correctness, decision\nflows, and end-to-end goal completion, each treated as a first-class concern\nrather than an afterthought bolted on post-hoc.",[15,54,55],{},"The hook for me was the concept of using LLMs as \"judges\" within the evaluation\npipeline itself. Generating test cases, writing assertions, and acting as\nevaluators of synthetic agent traces.",[15,57,58],{},"It is a self-referential approach that raises obvious questions about trust, but\nUrs addressed these. The demos were built on Koog, which gave the abstractions\ngenuine purchase.",[15,60,61],{},"The broader point is one that the industry is still working through. Agentic\nsystems that impress in a demo and fall apart in production are not a model\ncapability problem but rather an engineering discipline problem. Urs made a\ncredible case that the discipline exists and is learnable, which is more than\nmost talks in this space manage.",[22,63,65],{"id":64},"context-parameters-api-design","Context Parameters & API Design",[15,67,68],{},[29,69,70],{},"Alejandro Serrano Mena, Researcher, Kotlin Language Evolution Team, JetBrains",[15,72,73,74,78],{},"Context parameters are an experimental Kotlin feature that arrived with some\nfanfare. A ",[75,76,77],"code",{},"context"," declaration on a function signature names a type that must\nbe present in the calling scope. The compiler resolves and threads it through\nautomatically, no manual passing, no ceremony at the call site.",[80,81,86],"pre",{"className":82,"code":83,"language":84,"meta":85,"style":85},"language-kotlin shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","context(users: UserService)\nfun getFriends(user: User) {\n  val friendIds = users.findFriendsById(user.id)\n}\n\ncontext(userService: UserService)\nfun summarize(user: User): String {\n  val friends = getFriends(user)\n  \u002F\u002F ...\n}\n","kotlin","",[75,87,88,96,102,108,114,121,127,133,139,145],{"__ignoreMap":85},[89,90,93],"span",{"class":91,"line":92},"line",1,[89,94,95],{},"context(users: UserService)\n",[89,97,99],{"class":91,"line":98},2,[89,100,101],{},"fun getFriends(user: User) {\n",[89,103,105],{"class":91,"line":104},3,[89,106,107],{},"  val friendIds = users.findFriendsById(user.id)\n",[89,109,111],{"class":91,"line":110},4,[89,112,113],{},"}\n",[89,115,117],{"class":91,"line":116},5,[89,118,120],{"emptyLinePlaceholder":119},true,"\n",[89,122,124],{"class":91,"line":123},6,[89,125,126],{},"context(userService: UserService)\n",[89,128,130],{"class":91,"line":129},7,[89,131,132],{},"fun summarize(user: User): String {\n",[89,134,136],{"class":91,"line":135},8,[89,137,138],{},"  val friends = getFriends(user)\n",[89,140,142],{"class":91,"line":141},9,[89,143,144],{},"  \u002F\u002F ...\n",[89,146,148],{"class":91,"line":147},10,[89,149,113],{},[15,151,152,153,156,157,160,161,164],{},"The ",[75,154,155],{},"UserService"," flows from ",[75,158,159],{},"summarize"," into ",[75,162,163],{},"getFriends"," without appearing in\neither function's explicit parameter list. Context parameters are parameters,\njust ones the compiler handles for you.",[15,166,167],{},"The more interesting part of the talk was the design guidance built around a\nconcept Alejandro called the spotlight principle. The framing is that reading\ncode is like watching a film. Each function is a scene, and within any scene\nthere are primary and secondary characters. Primary characters are front and\ncentre, named in the explicit signature, doing the visible work of the scene.\nSecondary characters move between scenes largely unnoticed, present when needed\nbut never demanding attention.",[15,169,170],{},"In film, too many characters derail the narrative entirely. The same trap awaits\nan overloaded function signature.",[15,172,173],{},"The spotlight principle gives you a concrete way to decide between a context\nparameter and a receiver. If a value is the subject of the function, the thing\nthe function is fundamentally about, it belongs in the explicit signature or as\na receiver. If it is supporting infrastructure that needs to be present but is\nnot what the function is about, a context parameter is the right fit.\nDependencies, loggers, and service locators are naturally secondary in nature.\nThe domain object you are operating on is almost always a primary.",[15,175,176],{},"The talk also addressed the question of multiple context parameters, which came\nwith an honest trade-off summary. You get explicit, surgical dependencies and\nthe ability to refine any one context independently. The cost is that\nintroducing a new context means touching a lot of function signatures. The\nrecommended pattern for managing this at scale is the holder approach, composing\ncontexts into a delegation tree rather than threading individual services\neverywhere.",[80,178,180],{"className":82,"code":179,"language":84,"meta":85,"style":85},"class DbDependencies(...) : UserServiceHolder, GroupServiceHolder\n\nclass Dependencies(val db: DbDependencies, ...) :\n  UserServiceHolder by db, GroupServiceHolder by db\n",[75,181,182,187,191,196],{"__ignoreMap":85},[89,183,184],{"class":91,"line":92},[89,185,186],{},"class DbDependencies(...) : UserServiceHolder, GroupServiceHolder\n",[89,188,189],{"class":91,"line":98},[89,190,120],{"emptyLinePlaceholder":119},[89,192,193],{"class":91,"line":104},[89,194,195],{},"class Dependencies(val db: DbDependencies, ...) :\n",[89,197,198],{"class":91,"line":110},[89,199,200],{},"  UserServiceHolder by db, GroupServiceHolder by db\n",[15,202,203],{},"Context parameters are still experimental, but the guidance here felt\nappropriately calibrated to that. The spotlight principle is a useful heuristic\nnow regardless of whether you adopt the feature today, because the underlying\nquestion of what belongs in a signature versus what belongs in the ambient\nenvironment is one you face with receivers, dependency injection, and\nthread-locals already.",[205,206],"related-post",{"path":207,"title":208},"https:\u002F\u002Fkotlinlang.org\u002Fdocs\u002Fcontext-parameters.html","Kotlin Context Parameters",[22,210,212],{"id":211},"lightning-talk-grpc-made-for-kotlin","Lightning Talk: gRPC Made for Kotlin",[15,214,215],{},[29,216,217],{},"Alexander Sysoev (Lightning Talk)",[15,219,220,221,230],{},"A quick overview of ",[222,223,227],"a",{"href":224,"rel":225},"https:\u002F\u002Fgithub.com\u002FKotlin\u002Fkotlinx-rpc",[226],"nofollow",[75,228,229],{},"kotlinx-rpc",", the\nJetBrains-maintained library bringing idiomatic Kotlin to remote procedure\ncalls.",[15,232,233],{},"The setup for anyone unfamiliar: RPC is the idea of calling a function on one\nmachine and having it execute on another. It's not itself a protocol.",[15,235,236],{},"Extending that, gRPC is Google's protocol-level implementation of that idea,\nbuilt on HTTP\u002F2 and Protocol Buffers, and now maintained by the CNCF. It is\ncross-platform and widely used in polyglot microservice environments.",[205,238],{"path":239,"title":240},"https:\u002F\u002Fwww.cncf.io\u002Fprojects\u002Fgrpc\u002F","CNCF gRPC Project",[242,243,245],"h3",{"id":244},"kmp-grpc","KMP & gRPC",[15,247,248,249,251],{},"The problem ",[75,250,229],{}," addresses is that standard gRPC has no Kotlin\nMultiplatform support, the generated code is verbose and hard to read, and\nentities are not shared across platforms. The library wraps gRPC with Kotlin\nidioms, bringing suspend functions and a clean API surface to a protocol that\nwas never designed with Kotlin in mind.",[15,253,254,255,258],{},"The talk was honest about where things stand. There are still open bugs, the\n",[75,256,257],{},"cinterop"," setup for native targets needs stabilisation (Apple Store rejections\nare a live issue), and full gRPC feature parity is still in progress. The\nlibrary is moving toward a 1.0 release with gRPC as the primary focus. Web\nsupport is an open question due to HTTP\u002F2 constraints in browser environments.",[15,260,261],{},"Worth revisiting if you are building Kotlin Multiplatform services that need\nstructured, typed cross-platform communication, or simply want to keep an ear to\nthe ground on the state of gRPC.",[22,263,265],{"id":264},"kotlinllm","KotlinLLM",[15,267,268],{},[29,269,270],{},"Stanislav Sandler, JetBrains Education Research",[15,272,273],{},"An honest research preview of something genuinely experimental. KotlinLLM is not\na language feature proposal or a production library. It is a research project\nexploring what it would look like to delegate runtime logic to an LLM from\nwithin Kotlin code.",[15,275,276,277,280],{},"The central feature is ",[75,278,279],{},"asLlm",", a construct that generates a parser at runtime\nrather than compile time. The idea is that rather than hand-writing parsing\nlogic for structured data, you describe the transformation and the LLM infers\nthe implementation.",[15,282,283],{},"The example that illustrated it best was an \"easy issue radar\": give it a GitHub\nrepository URL, and it returns the issues labelled as beginner-friendly. The\nparser infers from context what \"beginner-friendly\" means, which would be\npainful to hard-code reliably.",[15,285,286],{},"Runtime overhead is a factor and the approach is currently limited to JVM hot\nreload. There are open questions about whether the LLM can always correctly\ninfer intent, and security implications of executing LLM generated code have not\nbeen addressed.",[15,288,289],{},"The research framing was appropriate and the honesty about where the edges are\nmade the ideas more credible, not less. I came in not sure what to expect and\nleft with a modicum of curiosity.",[22,291,293],{"id":292},"koin-the-kotlin-compiler-plugin","Koin & The Kotlin Compiler Plugin",[15,295,296],{},[29,297,298],{},"Arnaud Giuliani, Koin project creator & co-founder of Kotzilla",[15,300,301],{},"Arnaud used this talk to mark a milestone and make an announcement: the Koin\nCompiler Plugin 1.0, a native Kotlin K2 compiler plugin that replaces the legacy\nKSP processor.",[242,303,305],{"id":304},"what-is-koin-you-say","What Is Koin, You Say?",[15,307,308],{},[309,310,311],"strong",{},"Personal disclaimer: Koin was new territory for me, so I retroactively needed\na brief detour to contextually ground myself for this topic.",[205,313],{"path":314,"title":315},"https:\u002F\u002Finsert-koin.io\u002Fdocs\u002Fintro\u002Fwhat-is-koin","What is Koin?",[317,318,319],"blockquote",{},[15,320,321],{},"Koin is a dependency injection framework for Kotlin, now approaching ten years\nold and used in roughly 40% of all Android apps. Its defining characteristic\nis that it avoids reflection and code generation in favour of a clean Kotlin\nDSL, or alternatively annotations, depending on preference.",[15,323,324],{},"Example:",[80,326,328],{"className":82,"code":327,"language":84,"meta":85,"style":85},"\u002F\u002F DSL approach\nmodule {\n  single\u003CMyService>()\n  factory\u003CMyPresenter>()\n}\n\n\u002F\u002F Annotation approach\n@Singleton\nclass MyService\n\n@Factory\nclass MyPresenter\n",[75,329,330,335,340,345,350,354,358,363,368,373,377,383],{"__ignoreMap":85},[89,331,332],{"class":91,"line":92},[89,333,334],{},"\u002F\u002F DSL approach\n",[89,336,337],{"class":91,"line":98},[89,338,339],{},"module {\n",[89,341,342],{"class":91,"line":104},[89,343,344],{},"  single\u003CMyService>()\n",[89,346,347],{"class":91,"line":110},[89,348,349],{},"  factory\u003CMyPresenter>()\n",[89,351,352],{"class":91,"line":116},[89,353,113],{},[89,355,356],{"class":91,"line":123},[89,357,120],{"emptyLinePlaceholder":119},[89,359,360],{"class":91,"line":129},[89,361,362],{},"\u002F\u002F Annotation approach\n",[89,364,365],{"class":91,"line":135},[89,366,367],{},"@Singleton\n",[89,369,370],{"class":91,"line":141},[89,371,372],{},"class MyService\n",[89,374,375],{"class":91,"line":147},[89,376,120],{"emptyLinePlaceholder":119},[89,378,380],{"class":91,"line":379},11,[89,381,382],{},"@Factory\n",[89,384,386],{"class":91,"line":385},12,[89,387,388],{},"class MyPresenter\n",[15,390,391],{},"Both approaches reach the same outcome. The framework handles the dependency\ngraph, scoping, and lifecycle. The DSL reads naturally to any Kotlin developer\nand the learning curve is shallow compared to alternatives like Dagger or Hilt.",[15,393,394,395,398],{},"The Compiler Plugin changes the safety story significantly. Where the classic\nDSL catches misconfigured dependencies at runtime, the plugin validates them at\ncompile time. It operates in two phases: during analysis (FIR), it validates\nmodule definitions and detects constructor parameters; during transformation\n(IR), it generates the appropriate ",[75,396,397],{},"get()"," calls. The result is that a broken\ndependency graph becomes a build failure rather than a production crash.",[15,400,401,402,405,406,409],{},"There are three safety levels available, from per-module validation up to full\ncall-site validation that checks every ",[75,403,404],{},"get\u003CT>()"," and ",[75,407,408],{},"inject\u003CT>()"," in the\ncodebase. The right level depends on how much compile-time overhead is\nacceptable for the project.",[15,411,412,413,418],{},"The talk also touched on ",[222,414,417],{"href":415,"rel":416},"https:\u002F\u002Fkotzilla.io\u002F",[226],"Kotzilla",", the observability\nplatform Arnaud's company builds on top of Koin's instrumentation. It captures\ncomponent resolution, timing, scope data, and lifecycle automatically, and\nconnects to AI coding assistants via an MCP server. A live demo showed it\nsurfacing slow startup causes and ANR patterns without any manual\ninstrumentation.",[15,420,421],{},"Nine years, ten thousand GitHub stars, and a 1.0 compiler plugin. A fitting\nplace to mark nine years of quiet ubiquity.",[205,423],{"path":424,"title":425},"https:\u002F\u002Finsert-koin.io\u002Fdocs\u002Fintro\u002Fkoin-compiler-plugin\u002F","Koin Compiler Plugin",[22,427,429],{"id":428},"closing","Closing",[15,431,432],{},"KotlinConf 2026 wrapped with a closing ceremony and an inaugural awards\nrecognising standout contributors across five categories in the Kotlin\ncommunity.",[15,434,435],{},"Two good days. The conference continues to find the balance between language\ninternals and the practical reality of building software with Kotlin in\nproduction.",[15,437,438],{},"The evening called for Tegernseer Helles. Naturally, Kodee agreed. 🍻",[15,440,441],{},[442,443],"img",{"alt":444,"src":445},"Kodee","\u002Fimages\u002Fblog\u002F2026\u002Fkodee.png",[447,448,449],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":85,"searchDepth":104,"depth":104,"links":451},[452,453,454,455,458,459,462],{"id":24,"depth":98,"text":25},{"id":40,"depth":98,"text":41},{"id":64,"depth":98,"text":65},{"id":211,"depth":98,"text":212,"children":456},[457],{"id":244,"depth":104,"text":245},{"id":264,"depth":98,"text":265},{"id":292,"depth":98,"text":293,"children":460},[461],{"id":304,"depth":104,"text":305},{"id":428,"depth":98,"text":429},"2026-05-22","Notes and reflections from the second day of KotlinConf 2026 in Munich. Spring Boot 4, Kotlin context parameters, and eval-driven development.","md",false,"\u002Fimages\u002Fblog\u002F2026\u002Fgoogle-kotlinconf-2026-koog-2.png",null,{},"\u002Fblog\u002F2026\u002Fkotlinconf-2026-day-2",{"title":10,"description":464},"blog\u002F2026\u002Fkotlinconf-2026-day-2",[84,474,475,476,477,478,479],"conference","spring","grpc","ai","koin","context-parameters","xGRZKYwvYC9YMfjke9MFfsgb4qj2yPajbKnT1w9s-ZU",[482,483,487,491,495,499,503,506],{"path":470,"title":10,"date":463},{"path":484,"title":485,"date":486},"\u002Fblog\u002F2026\u002Fkotlinconf-2026-day-1","KotlinConf 2026 - Day 1 Impressions","2026-05-21",{"path":488,"title":489,"date":490},"\u002Fblog\u002Fsecurity\u002Fself-hosted-container-registry-mtls","Self-hosting a private container registry with NGINX and mTLS","2026-05-19",{"path":492,"title":493,"date":494},"\u002Fblog\u002Fan-antidote-to-speed","An Antidote To Speed","2026-05-14",{"path":496,"title":497,"date":498},"\u002Fblog\u002Frsa-jwt-nodejs","Sign and verify JWT with RSA encryption with NodeJS","2023\u002F06\u002F05",{"path":500,"title":501,"date":502},"\u002Fblog\u002Fgenerating-tls-certificates-openssl","Generating TLS certificates for server HTTPS","2023\u002F05\u002F05",{"path":504,"title":505,"date":502},"\u002Fblog\u002Ftwo-years-with-nuxt","Framework Paralysis to NuxtJS",{"path":507,"title":508,"date":509},"\u002Fblog\u002Fan-ode-to-strange-javascript","An Ode To Strange JavaScript","2023-02-01",[511,512,513,514,516,518,520,522,524,525,526,527,528,530,532,534,536,538,540,542,544,546,548,550,552,554,556,558],{"name":477,"count":104},{"name":84,"count":98},{"name":474,"count":98},{"name":515,"count":98},"pki",{"name":517,"count":98},"security",{"name":519,"count":92},"android",{"name":521,"count":92},"compose",{"name":523,"count":92},"coroutines",{"name":475,"count":92},{"name":476,"count":92},{"name":478,"count":92},{"name":479,"count":92},{"name":529,"count":92},"productivity",{"name":531,"count":92},"learning",{"name":533,"count":92},"reflection",{"name":535,"count":92},"javascript",{"name":537,"count":92},"tls",{"name":539,"count":92},"rsa",{"name":541,"count":92},"technology",{"name":543,"count":92},"jwt",{"name":545,"count":92},"encryption",{"name":547,"count":92},"docker",{"name":549,"count":92},"nginx",{"name":551,"count":92},"mtls",{"name":553,"count":92},"nuxtjs",{"name":555,"count":92},"frontend",{"name":557,"count":92},"ui",{"name":559,"count":92},"client",1779492396130]