<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://afanasev.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://afanasev.net/" rel="alternate" type="text/html" /><updated>2025-07-22T05:37:43+00:00</updated><id>https://afanasev.net/feed.xml</id><title type="html">afanasev.net</title><subtitle>Boring coding</subtitle><author><name>Anatolii Afanasev</name></author><entry><title type="html">Implement your own in-house Crashlytics for Android</title><link href="https://afanasev.net/android/crashlytics/2020/04/23/in-house-crashlytics.html" rel="alternate" type="text/html" title="Implement your own in-house Crashlytics for Android" /><published>2020-04-23T16:18:12+00:00</published><updated>2020-04-23T16:18:12+00:00</updated><id>https://afanasev.net/android/crashlytics/2020/04/23/in-house-crashlytics</id><content type="html" xml:base="https://afanasev.net/android/crashlytics/2020/04/23/in-house-crashlytics.html"><![CDATA[<h2 id="why">Why</h2>
      <p>We’ve been using Crashlytics by Fabric for many years in our company. When Google have acquired Fabric and asked Crashlytics users to migrate to Firebase, we started thinking what can happen with Crashlytics: will it require Play Services as other Firebase tools do (e.g. Firebase App Distribution), will it work in China (huge market for us), etc.</p>
      <p>Actually, above situation was one of many reasons why we decided to implement our own crash catcher system. Having crash information in your own database opens a lot of opportunities. We do a lot of A/B testing, all new features are covered by feature flags, remote configurations, etc. Using the crash info such as a filename, line number we can identify which feature/experiment causes this crash and automatically &amp; remotely turn it off. This is just one use case. We can identify what team or developer this file or change belongs to using <code class="language-plaintext highlighter-rouge">git blame</code> and automatically <del>fire</del> notify them. Or even train ML models using all collected crashes. Let’s just imagine, you got a crash and in a minite you received an email with PR that fixes the crash. Infinite opportunities.</p>
      <p>To be fair, we can acrhieve all things we imagined using Google’s BigQuery to export data from Firebase Crashlytics. But it’s not real-time and not free. Other libraries we didn’t like for one reason or another. We’d like to have 100% control.</p>
      <h2 id="how">How</h2>
      <p>Android (excluding JNI) is the easiest part of this huge system. Backend will be deobfuscating (proguard, R8), saving, analyzing, showing, notifying, etc. On client side, we should just catch exceptions and send them to the backend side. In order to do that, we must use <code class="language-plaintext highlighter-rouge">setDefaultUncaughtExceptionHandler</code> method of <code class="language-plaintext highlighter-rouge">Thread</code> class. Do not forget to “save” previously set handler and pass caught data to it once we’re done. Otherwise, Android won’t kill the process.</p>
      <div class="language-kotlin highlighter-rouge">
        <div class="highlight">
          <pre class="highlight"><code><span class="kd">val</span> <span class="py">defaultHandler</span> <span class="p">=</span> <span class="nc">Thread</span><span class="p">.</span><span class="nf">getDefaultUncaughtExceptionHandler</span><span class="p">()</span>

<span class="nc">Thread</span><span class="p">.</span><span class="nf">setDefaultUncaughtExceptionHandler</span> <span class="p">{</span> <span class="n">thread</span><span class="p">,</span> <span class="n">throwable</span> <span class="p">-&gt;</span>
    <span class="k">try</span> <span class="p">{</span>
        <span class="n">crashLogger</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="n">thread</span><span class="p">,</span> <span class="n">throwable</span><span class="p">)</span>
    <span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
        <span class="n">defaultHandler</span><span class="p">.</span><span class="nf">uncaughtHandler</span><span class="p">(</span><span class="n">thread</span><span class="p">,</span> <span class="n">throwable</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
        </div>
      </div>
      <p>This code can be called from <code class="language-plaintext highlighter-rouge">Application#onCreate()</code> or <code class="language-plaintext highlighter-rouge">ContentProvider</code> which is called even earlier.</p>
      <p><code class="language-plaintext highlighter-rouge">CrashLogger</code> interface might look like this. We have to save stacktrace somewhere locally and next app launch it’s need to be sent to the server. We can’t immediatelly make network call once we caught a crash because it will be too slow.</p>
      <div class="language-kotlin highlighter-rouge">
        <div class="highlight">
          <pre class="highlight"><code><span class="kd">interface</span> <span class="nc">CrashLogger</span> <span class="p">{</span>
    <span class="k">fun</span> <span class="nf">log</span><span class="p">(</span><span class="n">thread</span><span class="p">:</span> <span class="nc">Thread</span><span class="p">,</span> <span class="n">throwable</span><span class="p">:</span> <span class="nc">Throwable</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">FileCrashLogger</span> <span class="p">:</span> <span class="nc">CrashLogger</span> <span class="p">{</span> <span class="o">..</span><span class="p">.</span> <span class="p">}</span>
<span class="kd">class</span> <span class="nc">SqliteCrashLogger</span> <span class="p">:</span> <span class="nc">CrashLogger</span> <span class="p">{</span> <span class="o">..</span><span class="p">.</span> <span class="p">}</span>
</code></pre>
        </div>
      </div>
      <p>Easy way of converting throwable stacktrace to string:</p>
      <div class="language-kotlin highlighter-rouge">
        <div class="highlight">
          <pre class="highlight"><code><span class="kd">val</span> <span class="py">sw</span> <span class="p">=</span> <span class="nc">StringWriter</span><span class="p">()</span>
<span class="n">throwable</span><span class="p">.</span><span class="nf">printStackTrace</span><span class="p">(</span><span class="nc">PrintWriter</span><span class="p">(</span><span class="n">sw</span><span class="p">))</span>
<span class="kd">val</span> <span class="py">str</span> <span class="p">=</span> <span class="n">sw</span><span class="p">.</span><span class="nf">toString</span><span class="p">()</span>
</code></pre>
        </div>
      </div>
      <p>If you want to get all stacktraces from all threads:</p>
      <div class="language-kotlin highlighter-rouge">
        <div class="highlight">
          <pre class="highlight"><code><span class="kd">val</span> <span class="py">stackTraces</span> <span class="p">=</span> <span class="n">mutableMapOf</span><span class="p">&lt;</span><span class="nc">String</span><span class="p">,</span> <span class="nc">String</span><span class="p">&gt;()</span>

<span class="nc">Thread</span><span class="p">.</span><span class="nf">getAllStackTraces</span><span class="p">().</span><span class="nf">forEach</span> <span class="p">{</span> <span class="p">(</span><span class="n">thread</span><span class="p">,</span> <span class="n">stackTrace</span><span class="p">)</span> <span class="p">-&gt;</span>
    <span class="kd">val</span> <span class="py">stringBuilder</span> <span class="p">=</span> <span class="nc">StringBuilder</span><span class="p">(</span><span class="n">thread</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>

    <span class="n">stackTrace</span><span class="p">.</span><span class="nf">forEach</span> <span class="p">{</span> <span class="n">element</span> <span class="p">-&gt;</span>
        <span class="n">stringBuilder</span>
            <span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="s">"\n\tat "</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">element</span><span class="p">.</span><span class="n">className</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="sc">'.'</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">element</span><span class="p">.</span><span class="n">methodName</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="sc">'('</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">element</span><span class="p">.</span><span class="n">fileName</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="sc">':'</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">element</span><span class="p">.</span><span class="n">lineNumber</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="sc">')'</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="n">stackTraces</span><span class="p">[</span><span class="n">thread</span><span class="p">.</span><span class="n">name</span><span class="p">]</span> <span class="p">=</span> <span class="n">stringBuilder</span><span class="p">.</span><span class="nf">toString</span><span class="p">()</span>
<span class="p">}</span>
</code></pre>
        </div>
      </div>
      <p>If you’d like to know only minimum information you can use the code below:</p>
      <div class="language-kotlin highlighter-rouge">
        <div class="highlight">
          <pre class="highlight"><code><span class="n">throwable</span><span class="p">.</span><span class="n">stackTrace</span><span class="o">?.</span><span class="nf">firstOrNull</span><span class="p">()</span><span class="o">?.</span><span class="nf">let</span> <span class="p">{</span> <span class="n">crash</span> <span class="p">-&gt;</span>
    <span class="n">crash</span><span class="p">.</span><span class="n">fileName</span> <span class="c1">// sample.kt</span>
    <span class="n">crash</span><span class="p">.</span><span class="n">lineNumber</span> <span class="c1">// 42</span>
    <span class="n">crash</span><span class="p">.</span><span class="n">className</span> <span class="c1">// Sample</span>
<span class="p">}</span>
</code></pre>
        </div>
      </div>
      <p>Remember, <code class="language-plaintext highlighter-rouge">Throwable#getStackTrace()</code> method can return an empty array if <code class="language-plaintext highlighter-rouge">writableStackTrace</code> flag is false (e.g. <code class="language-plaintext highlighter-rouge">ArithmeticException</code>).</p>
      <p><em>NOTE: This code is just a sample. If you really want to create your own Crashlytics and make it production ready there are many things to keep in mind, at least Multi processes, JNI (if you use it).</em></p>
      ]]></content><author><name>Anatolii Afanasev</name></author><category term="android" /><category term="crashlytics" /><summary type="html"><![CDATA[Why]]></summary></entry><entry><title type="html">Filter out classes from JaCoCo report using annotaitons</title><link href="https://afanasev.net/kotlin/jacoco/2020/04/10/jacoco-ignore-annotation.html" rel="alternate" type="text/html" title="Filter out classes from JaCoCo report using annotaitons" /><published>2020-04-10T09:26:00+00:00</published><updated>2020-04-10T09:26:00+00:00</updated><id>https://afanasev.net/kotlin/jacoco/2020/04/10/jacoco-ignore-annotation</id><content type="html" xml:base="https://afanasev.net/kotlin/jacoco/2020/04/10/jacoco-ignore-annotation.html"><![CDATA[<p style="text-align: center;"><img src="/assets/img/jacoco-code-coverage.png" alt="JaCoCo code coverate report with Generated annotation" /></p>
    <h2 id="story">Story</h2>
    <p>(can be skipped)</p>
    <p>Long time ago in our company, we decided to use code coverage level as one of the must requirements to merge PR into <code class="language-plaintext highlighter-rouge">develop</code> branch. We have automated merge bot which automatically merges if the branch meets all requirements. We came up with magic number <code class="language-plaintext highlighter-rouge">80%</code>, so every new/modified class must be covered by Unit tests as minimum 80%.</p>
    <p><em>There are many discussions about code coverage, 80%, JaCoCo, etc. This article is not about that.</em></p>
    <p>We were happy with this requirement. Teams started to write more testable code, think about architecture, app stability went up, etc. We understood it’s impossible to cover all classes in our project, there are many reasons: legacy code (lots of LOC need to be refactored; Business just won’t give time for that; “if it works don’t touch!”), auto-generated code (why we need to test 3rd party libs, etc), some code frankly does not need to be tested. Therefore, we need a way to filter out specific classes from JaCoCo report and allow devs/tools to merge branches.</p>
    <p>Even more problems started to appear after moving to Kotlin from Java. JaCoCo, as you may know, works as java-agent with java bytecode only. Kotlin is a great language which reduced boilerplate code a lot but underhood the hood (in case of JVM) it generates a lot of helper methods, lines of code. For example, data class becomes a class with auto-generated methods such as <code class="language-plaintext highlighter-rouge">equals</code>, <code class="language-plaintext highlighter-rouge">hashCode</code>, <code class="language-plaintext highlighter-rouge">component1</code>, etc; even one line of code like <code class="language-plaintext highlighter-rouge">s?.foo()</code> or just <code class="language-plaintext highlighter-rouge">s.foo()</code> (where <code class="language-plaintext highlighter-rouge">s</code> defined as <code class="language-plaintext highlighter-rouge">lateinit</code>) will have 1 <code class="language-plaintext highlighter-rouge">if</code> in the generated code. Obviuosly, we do not have to test the generated code. All this generated stuff dramatically decreased our code coverage numbers. Keep in mind, those numbers can be KPI for some teams (yeah, bloody enterprise…).</p>
    <h2 id="ideas">Ideas</h2>
    <h4 id="1-custom-gradle-task-with-filter">1. Custom Gradle task with filter</h4>
    <p>This way is suitable for most teams. Create a task using <code class="language-plaintext highlighter-rouge">JacocoReport</code> and make it depend on <code class="language-plaintext highlighter-rouge">test</code> &amp; <code class="language-plaintext highlighter-rouge">generate report</code> tasks. Then define an array of classes that you want to ignore and pass it as <code class="language-plaintext highlighter-rouge">excludes</code> parameter of <code class="language-plaintext highlighter-rouge">fileTree</code> method.</p>
    <div class="language-groovy highlighter-rouge">
      <div class="highlight">
        <pre class="highlight"><code><span class="n">task</span> <span class="nf">jacocoTestReport</span><span class="o">(</span><span class="nl">type:</span> <span class="n">JacocoReport</span><span class="o">,</span> <span class="nl">dependsOn:</span> <span class="o">[...])</span> <span class="o">{</span>
    <span class="c1">// filter rules</span>
    <span class="kt">def</span> <span class="n">fileFilter</span> <span class="o">=</span> <span class="o">[</span>
        <span class="s1">'**/R.class'</span><span class="o">,</span>
        <span class="s1">'**/R$*.class'</span><span class="o">,</span>
    <span class="o">]</span>

    <span class="kt">def</span> <span class="n">debugTree</span> <span class="o">=</span> <span class="n">fileTree</span><span class="o">(</span>
        <span class="nl">dir:</span> <span class="s2">"${buildDir}/intermediates/classes/debug"</span><span class="o">,</span> 
        <span class="nl">excludes:</span> <span class="n">fileFilter</span> <span class="c1">// &lt;-- exclude listed classes</span>
    <span class="o">)</span>

    <span class="n">classDirectories</span> <span class="o">=</span> <span class="n">files</span><span class="o">([</span><span class="n">debugTree</span><span class="o">])</span>

    <span class="c1">// some code...</span>
<span class="o">}</span>
</code></pre>
      </div>
    </div>
    <p>Pros:</p>
    <ul>
      <li>All ignored classes in 1 place</li>
    </ul>
    <p>Cons:</p>
    <ul>
      <li>Easy to make a mistake. One day we have found a rule <code class="language-plaintext highlighter-rouge">**/R*.class</code> which supposed to filter out <code class="language-plaintext highlighter-rouge">R</code> class &amp; nested classes (known by every Android developer) but JaCoCo was ignoring all classes started with <code class="language-plaintext highlighter-rouge">R</code> :)</li>
    </ul>
    <h4 id="2-annotation-processor">2. Annotation processor</h4>
    <p>Since all developers are lazy and we rather spend 1 day on automating routine job, my colleague came up with Annotation processor approach. He has created <code class="language-plaintext highlighter-rouge">NoCoverage</code> annotation and a processor which saves all annotated classes into a file. Later on the file was used by <code class="language-plaintext highlighter-rouge">jacocoTestReport</code> instead of <code class="language-plaintext highlighter-rouge">fileFilter</code> array. Genius!</p>
    <p>Pros:</p>
    <ul>
      <li>Automation!</li>
      <li>Less manual work</li>
    </ul>
    <p>Cons:</p>
    <ul>
      <li>APT is not suitable for this kind of jobs. Especially, if it doesn’t support incremental processing and you have many modules.</li>
    </ul>
    <h4 id="3-forked-kotlin-compiler">3. Forked Kotlin compiler</h4>
    <p>We found out that JaCoCo team in order to support Lombok added a filter which doesn’t count coverage of <code class="language-plaintext highlighter-rouge">@Generated</code> annotated classes/methods. Without thinking twice, another colleague has forked Kotlin compiler (!) and modified so it started adding <code class="language-plaintext highlighter-rouge">Generated</code> annotation to every generated method. Of course, we haven’t used this approach in prod code. Later, JaCoCo added <code class="language-plaintext highlighter-rouge">@kotlin.Metadata</code> filter too.</p>
    <p>… and finally!</p>
    <h2 id="solution-annotation--kotlin-typealias">Solution: Annotation + Kotlin typealias</h2>
    <p>While investigating JaCoCo code I found that they changed <code class="language-plaintext highlighter-rouge">AnnotationGeneratedFilter</code> behaviour. Now instead of checking exact match of annotation name it just should <a href="https://github.com/jacoco/jacoco/blob/6bcce6972b8939d7925c4b4d3df785d9a7b00007/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilter.java#L51">contain</a> <code class="language-plaintext highlighter-rouge">Generated</code> word. It means we can create any annotation with proper name and JaCoCo will automatically ignore all annotated classes and methods.</p>
    <p>In case of Kotlin you can use <code class="language-plaintext highlighter-rouge">typealias</code> to make your code more readable:</p>
    <div class="language-kotlin highlighter-rouge">
      <div class="highlight">
        <pre class="highlight"><code><span class="nd">@Retention</span><span class="p">(</span><span class="nc">AnnotationRetention</span><span class="p">.</span><span class="nc">BINARY</span><span class="p">)</span>
<span class="k">annotation</span> <span class="kd">class</span> <span class="nc">NoCoverageGenerated</span>

<span class="k">typealias</span> <span class="nc">NoCoverage</span> <span class="p">=</span> <span class="nc">NoCoverageGenerated</span>

<span class="c1">// or just</span>

<span class="k">typealias</span> <span class="nc">NoCoverage</span> <span class="p">=</span> <span class="nc">Generated</span> <span class="c1">// from javax.annotations package</span>
</code></pre>
      </div>
    </div>
    <p>Pros:</p>
    <ul>
      <li>Easy to use</li>
      <li>No code generation</li>
    </ul>
    <p>Cons:</p>
    <ul>
      <li>Workaround. From JaCoCo Wiki:
        <blockquote>
          <p>Remark: A Generated annotation should only be used for code actually generated by compilers or tools, never for manual exclusion.</p>
        </blockquote>
      </li>
      <li>Useless annotation in prod code. But if you use code obfuscator such as Proguard/Dexguard/R8 (Android) that annotation will be cut out.</li>
    </ul>
    ]]></content><author><name>Anatolii Afanasev</name></author><category term="kotlin" /><category term="jacoco" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Exclude properties from toString() of Kotlin data class (Sekret appx.)</title><link href="https://afanasev.net/kotlin/data-class/2019/08/13/kotlin-data-class-tostirng-hide.html" rel="alternate" type="text/html" title="Exclude properties from toString() of Kotlin data class (Sekret appx.)" /><published>2019-08-13T08:00:00+00:00</published><updated>2019-08-13T08:00:00+00:00</updated><id>https://afanasev.net/kotlin/data-class/2019/08/13/kotlin-data-class-tostirng-hide</id><content type="html" xml:base="https://afanasev.net/kotlin/data-class/2019/08/13/kotlin-data-class-tostirng-hide.html"><![CDATA[<p><em>This post describes how to remove class properties from <code class="language-plaintext highlighter-rouge">toString()</code> method manually if you don’t want to use <a href="/kotlin-library/2019/08/13/sekret.html">Sekret</a> library.</em></p>
  <h3 id="1-override-tostring-by-yourself">1. Override toString() by yourself</h3>
  <p>The simplest way how you can hide sensitive information is overriding <code class="language-plaintext highlighter-rouge">toString</code>. 
    But it always needs an additional work in every class. What if you want to show other properties? You will have to concatenate strings by yourself.</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="kd">data class</span> <span class="nc">Data</span><span class="p">(</span>
    <span class="kd">val</span> <span class="py">login</span><span class="p">:</span> <span class="nc">String</span><span class="p">,</span>
    <span class="kd">val</span> <span class="py">password</span><span class="p">:</span> <span class="nc">String</span> 
<span class="p">)</span> <span class="p">{</span>
    <span class="k">override</span> <span class="k">fun</span> <span class="nf">toString</span><span class="p">()</span> <span class="p">=</span> <span class="s">""</span>
<span class="p">}</span>
</code></pre>
    </div>
  </div>
  <h3 id="2-define-variable-out-of-data-class">2. Define variable out of Data class</h3>
  <p>In this case the property won’t be included to any of autogenerated functions of data classes (toString, hashCode, equals, components, etc)</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="kd">data class</span> <span class="nc">Data</span><span class="p">(</span>
    <span class="kd">val</span> <span class="py">login</span><span class="p">:</span> <span class="nc">String</span>
<span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="py">password</span><span class="p">:</span> <span class="nc">String</span>
<span class="p">}</span>

<span class="c1">// Usage - instantiate and set</span>
<span class="kd">val</span> <span class="py">data</span> <span class="p">=</span> <span class="nc">Data</span><span class="p">(</span><span class="s">"login"</span><span class="p">)</span>
<span class="n">data</span><span class="p">.</span><span class="n">password</span> <span class="p">=</span> <span class="s">"password"</span>
</code></pre>
    </div>
  </div>
  <h3 id="3-use-a-wrapper-class">3. Use a wrapper class</h3>
  <p>This one is more elegant solution but when you create/read a data you will have 1 more level of abstraction.</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="c1">// Wrapper</span>
<span class="kd">class</span> <span class="nc">Secret</span><span class="p">&lt;</span><span class="nc">T</span><span class="p">&gt;(</span><span class="kd">val</span> <span class="py">data</span><span class="p">:</span> <span class="nc">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">override</span> <span class="k">fun</span> <span class="nf">toString</span><span class="p">()</span> <span class="p">=</span> <span class="s">""</span>
<span class="p">}</span>

<span class="kd">data class</span> <span class="nc">Data</span><span class="p">(</span>
    <span class="kd">val</span> <span class="py">login</span><span class="p">:</span> <span class="nc">String</span><span class="p">,</span>
    <span class="kd">val</span> <span class="py">password</span><span class="p">:</span> <span class="nc">Secret</span><span class="p">&lt;</span><span class="nc">String</span><span class="p">&gt;</span>
<span class="p">)</span>

<span class="c1">// Usage - create / read</span>
<span class="kd">val</span> <span class="py">data</span> <span class="p">=</span> <span class="nc">Data</span><span class="p">(</span><span class="s">"login"</span><span class="p">,</span> <span class="nc">Secret</span><span class="p">(</span><span class="s">"password"</span><span class="p">))</span>
<span class="n">data</span><span class="p">.</span><span class="n">password</span><span class="p">.</span><span class="n">data</span>
</code></pre>
    </div>
  </div>
  <h3 id="4-do-not-use-data-classes-_ツ_">4. Do not use Data classes ¯\_(ツ)_/¯</h3>
  <p>In this case you will not have all advantages of data classes.</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="kd">class</span> <span class="nc">Data</span><span class="p">(</span>
    <span class="kd">val</span> <span class="py">login</span><span class="p">:</span> <span class="nc">String</span><span class="p">,</span>
    <span class="kd">val</span> <span class="py">password</span><span class="p">:</span> <span class="nc">String</span>
<span class="p">)</span>
</code></pre>
    </div>
  </div>
  ]]></content><author><name>Anatolii Afanasev</name></author><category term="kotlin" /><category term="data-class" /><summary type="html"><![CDATA[This post describes how to remove class properties from toString() method manually if you don’t want to use Sekret library.]]></summary></entry><entry><title type="html">Sekret — risk-free toString() of Kotlin data class?</title><link href="https://afanasev.net/kotlin-library/2019/08/13/sekret.html" rel="alternate" type="text/html" title="Sekret — risk-free toString() of Kotlin data class?" /><published>2019-08-13T07:18:12+00:00</published><updated>2019-08-13T07:18:12+00:00</updated><id>https://afanasev.net/kotlin-library/2019/08/13/sekret</id><content type="html" xml:base="https://afanasev.net/kotlin-library/2019/08/13/sekret.html"><![CDATA[<h2 id="problem">Problem</h2>
  <p>Kotlin compiler automatically generates equals, hashCode, componentN, copy and <strong>toString</strong> functions for Data classes. It’s super useful because you as a developer don’t have to spend time on writing boilerplate code and testing. But there is one problem (at least for me) — a result of toString() will contain all properties of Data class.</p>
  <p>Let me explain why it can be a problem. For example in Android development, if you use MVI pattern, Views tend to have a single render() that accepts a state to render on the screen:</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="kd">data class</span> <span class="nc">ViewState</span><span class="p">(</span>
    <span class="kd">val</span> <span class="py">username</span><span class="p">:</span> <span class="nc">String</span><span class="p">,</span>
    <span class="kd">val</span> <span class="py">password</span><span class="p">:</span> <span class="nc">String</span><span class="p">,</span>
    <span class="kd">val</span> <span class="py">isButtonEnabled</span><span class="p">:</span> <span class="nc">Boolean</span>
<span class="p">)</span>

<span class="c1">// PS: never keep passwords in String</span>
</code></pre>
    </div>
  </div>
  <p>Great, now you may want to add some logging system to able to understand what your customer’s behavior or what they have seen before a crash or for just debugging purpose:</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="k">fun</span> <span class="nf">render</span><span class="p">(</span><span class="n">viewState</span><span class="p">:</span> <span class="nc">ViewState</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">logger</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="s">"render $viewState"</span><span class="p">)</span>
    <span class="o">..</span><span class="p">.</span>
<span class="p">}</span>
</code></pre>
    </div>
  </div>
  <p>Logger class can use Log.d() internally and just prints on *logcat. *Or it can be your own analytics system which sends data to web or just saves in files. It can even be Google Analytics, Crashlytics.log or any other 3rd party vendor. Your application can be a reason for PII, passwords, credit card info or any other sensitive data leakage. I agree that the logging system should be much smarter than just saving everything and everywhere.</p>
  <p>It’s not only about Android, but it can also be an issue everywhere especially on microservices architecture where every component is independent and logs all in / out data. It can happen in Repository with sealed class results + data classes, Actions from View to Presenter, State of StateMachine, etc…</p>
  <h2 id="solution">Solution</h2>
  <p>There are <a href="/kotlin/data-class/2019/08/13/kotlin-data-class-tostirng-hide.html">many ways</a> how we can exclude our properties from toString() result. But all of them needs manual work. Since developers are lazy I’ve implemented a tool which helps with this. <strong>Sekret</strong> is Kotlin compiler plugin which changes generated Java bytecode of toString() method during the compilation process. You just need to annotate your property with a special annotation and that’s it!</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="kd">data class</span> <span class="nc">Data</span><span class="p">(</span>
    <span class="kd">val</span> <span class="py">username</span><span class="p">:</span> <span class="nc">String</span><span class="p">,</span>
    <span class="nd">@Secret</span> <span class="kd">val</span> <span class="py">password</span><span class="p">:</span> <span class="nc">String</span>
<span class="p">)</span>

<span class="nf">print</span><span class="p">(</span><span class="nc">Data</span><span class="p">(</span><span class="s">"james.bond"</span><span class="p">,</span> <span class="s">"123456"</span><span class="p">))</span>

<span class="c1">// prints out</span>
<span class="c1">// Data(username=james.bond, password=■■■)</span>
</code></pre>
    </div>
  </div>
  <p>More info on Github: <a href="https://github.com/aafanasev/sekret">https://github.com/aafanasev/sekret</a></p>
  <p>Perhaps JetBrains will allow changing toString() body with an out-of-box solution like Transient annotation for serialization.</p>
  <p><em>This article was originally posted on <a href="https://medium.com/@jokuskay/how-to-exclude-properties-from-tostring-of-kotlin-data-classes-f8dc04b8c45e">Medium</a>.</em></p>
  ]]></content><author><name>Anatolii Afanasev</name></author><category term="kotlin-library" /><summary type="html"><![CDATA[Problem]]></summary></entry><entry><title type="html">KSON — auto-generate GSON adapters for Kotlin data classes</title><link href="https://afanasev.net/kotlin-library/2019/08/12/kson.html" rel="alternate" type="text/html" title="KSON — auto-generate GSON adapters for Kotlin data classes" /><published>2019-08-12T07:18:12+00:00</published><updated>2019-08-12T07:18:12+00:00</updated><id>https://afanasev.net/kotlin-library/2019/08/12/kson</id><content type="html" xml:base="https://afanasev.net/kotlin-library/2019/08/12/kson.html"><![CDATA[<p>Kotlin data classes are super suitable as API entities. And it’s very easy to use them with GSON. But always keep in mind GSON uses ReflectiveTypeAdapterFactory by default which is not only slower, also it’s dangerous. Reflection doesn’t care about nullability of your properties. For example, this code will throw NullPointerException when you try to use <strong>entity.id</strong> in your code though it should throw it earlier during parsing JSON:</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="kd">data class</span> <span class="nc">Entity</span><span class="p">(</span><span class="kd">val</span> <span class="py">id</span><span class="p">:</span> <span class="nc">Int</span><span class="p">)</span>
<span class="kd">val</span> <span class="py">json</span> <span class="p">=</span> <span class="s">"""{ "id": null }"""</span>
<span class="kd">val</span> <span class="py">entity</span> <span class="p">=</span> <span class="n">gson</span><span class="p">.</span><span class="nf">fromJson</span><span class="p">(</span><span class="n">json</span><span class="p">,</span> <span class="nc">Entity</span><span class="o">::</span><span class="k">class</span><span class="p">.</span><span class="n">java</span><span class="p">)</span>
<span class="n">entity</span><span class="p">.</span><span class="n">id</span> <span class="c1">// &lt;- Throws NPE</span>
</code></pre>
    </div>
  </div>
  <p>In order to solve this issue in Java, I used to use AutoValue with AutoGson extension but didn’t find any library for Kotlin (at that time). So I’ve decided to implement my own library and called it <strong>KSON</strong>.</p>
  <p>Simply annotate your data class with Kson annotation and annotation processor will generate null-safe GSON type adapter for your entity class:</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="nd">@Kson</span>
<span class="kd">data class</span> <span class="nc">Entity</span><span class="p">(</span><span class="kd">val</span> <span class="py">id</span><span class="p">:</span> <span class="nc">Int</span><span class="p">)</span>
</code></pre>
    </div>
  </div>
  <p>Also, you can use KsonFactory annotation and register auto-generated type adapter factory which contains all generated adapters:</p>
  <div class="language-kotlin highlighter-rouge">
    <div class="highlight">
      <pre class="highlight"><code><span class="nd">@KsonFactory</span>
<span class="kd">object</span> <span class="nc">FactoryProvider</span> <span class="p">{</span>
    <span class="k">get</span><span class="p">()</span> <span class="p">=</span> <span class="nc">KsonFactoryProvider</span><span class="p">()</span> <span class="c1">// generated class</span>
<span class="p">}</span>

<span class="kd">val</span> <span class="py">gson</span> <span class="p">=</span> <span class="nc">GsonBuilder</span><span class="p">()</span>
    <span class="p">.</span><span class="nf">registerTypeAdapterFactory</span><span class="p">(</span><span class="nc">FactoryProvider</span><span class="p">.</span><span class="k">get</span><span class="p">())</span>
    <span class="p">.</span><span class="nf">create</span><span class="p">()</span>
</code></pre>
    </div>
  </div>
  <p>As you see, KSON doesn’t need any extra work, just need to add 1 annotation to your class and that’s it! If you don’t want to use for some reason you can simply delete 1 line of code.</p>
  <p>More info on Github: <a href="https://github.com/aafanasev/kson">https://github.com/aafanasev/kson</a></p>
  <p><em>This article was originally posted on <a href="https://medium.com/@jokuskay/kson-auto-generate-gson-adapters-for-kotlin-data-classes-17af43b6c267">Medium</a>.</em></p>
  ]]></content><author><name>Anatolii Afanasev</name></author><category term="kotlin-library" /><summary type="html"><![CDATA[Kotlin data classes are super suitable as API entities. And it’s very easy to use them with GSON. But always keep in mind GSON uses ReflectiveTypeAdapterFactory by default which is not only slower, also it’s dangerous. Reflection doesn’t care about nullability of your properties. For example, this code will throw NullPointerException when you try to use entity.id in your code though it should throw it earlier during parsing JSON:]]></summary></entry></feed>