<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: JICA98</title>
    <description>The latest articles on DEV Community by JICA98 (@rude).</description>
    <link>https://dev.to/rude</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F810385%2F90bfe8c5-955b-4f38-bec7-d923c314c0bf.jpeg</url>
      <title>DEV Community: JICA98</title>
      <link>https://dev.to/rude</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rude"/>
    <language>en</language>
    <item>
      <title>I tried making DynamoDB Streams easier to use in Java</title>
      <dc:creator>JICA98</dc:creator>
      <pubDate>Sat, 05 Aug 2023 04:33:28 +0000</pubDate>
      <link>https://dev.to/rude/i-tried-making-dynamodb-streams-easier-to-use-in-java-10di</link>
      <guid>https://dev.to/rude/i-tried-making-dynamodb-streams-easier-to-use-in-java-10di</guid>
      <description>&lt;p&gt;DynamoDB offers DynamoDB Streams, which provides a way to capture changes to items in a table. Although DynamoDB Streams offer valuable insights into data changes, managing and processing these streams can be challenging (when your are not using lambda or kinesis). &lt;br&gt;
Anyways, I just wanted to use DynamoDB Streams along with Flux in Java and that's what inspired me to write this wrapper around DynamoDB Stream's low level api (which you can find &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.LowLevel.Walkthrough.html"&gt;here&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;First of all, what's diffifult with the existing api, you ask? Well here are a few things you need to do, to listen to the changes of your DynamoDB:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Well first you need to call &lt;code&gt;DescribeStream&lt;/code&gt; API which takes your StreamARN as input and returns you a couple of &lt;code&gt;Shards&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;After which you need to get the &lt;code&gt;ShardIterator&lt;/code&gt; for each these &lt;code&gt;Shards&lt;/code&gt; using the &lt;code&gt;GetShardIterator&lt;/code&gt; API.&lt;/li&gt;
&lt;li&gt;And now, since you have an iterator, you can call the &lt;code&gt;GetRecords&lt;/code&gt; API to get the actual DynamoDB Records (which has new and old images)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On the top of all of these, you need to take care of the expired shards as well as poll these steps since the api does not provide a stream.&lt;/p&gt;

&lt;p&gt;And so I created &lt;a href="https://github.com/JICA98/aws-java-dynamo-streams"&gt;dynamo-streams&lt;/a&gt; which will take care of all of these steps for you and you just need to listen to these changes. These changes will come through a Flux.&lt;/p&gt;

&lt;p&gt;So, where to we get started?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
First add the maven or gradle dependency for the &lt;code&gt;dynamo-streams&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;dependency&amp;gt;
     &amp;lt;groupId&amp;gt;io.github.jica98&amp;lt;/groupId&amp;gt;
     &amp;lt;artifactId&amp;gt;aws-java-dynamo-streams&amp;lt;/artifactId&amp;gt;
     &amp;lt;version&amp;gt;0.0.5&amp;lt;/version&amp;gt;
 &amp;lt;/dependency&amp;gt;   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation group: 'io.github.jica98', name: 'aws-java-dynamo-streams', version: '0.0.5'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
If you are using &lt;code&gt;Spring&lt;/code&gt;, then you can declare a bean for the DynamoStreams in one your config classes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
   private static final String STREAM_ARN = "arn:aws:dynamodb:us-east-1:your-dynamo-db-stream";

    @Bean(destroyMethod = "shutdown")
    protected AmazonDynamoDBStreams streamsClient() {
        return AmazonDynamoDBStreamsClientBuilder
                .standard()
                .withRegion(Regions.US_EAST_1)
                .withCredentials(new DefaultAWSCredentialsProviderChain())
                .build();
    }

    @Bean(destroyMethod = "shutdown")
    protected DynamoStreams&amp;lt;DataRoot&amp;gt; dynamoStreams(AmazonDynamoDBStreams dynamoDBStreams) {
        return new DynamoStreams&amp;lt;&amp;gt;(
                StreamConfig.&amp;lt;DataRoot&amp;gt;builder()
                        .clazz(DataRoot.class)
                        .dynamoDBStreams(dynamoDBStreams)
                        .streamARN(STREAM_ARN)
                .build());
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Finally in your controller, autowire it and subscribe to the changes using a Flux. There are a couple of utility methods such as &lt;code&gt;newImages&lt;/code&gt; or &lt;code&gt;oldImages&lt;/code&gt; which will return flux of only the &lt;code&gt;newImages&lt;/code&gt; or &lt;code&gt;oldImages&lt;/code&gt; respectively.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Autowired
    private DynamoStreams&amp;lt;DataRoot&amp;gt; dynamoStreams;

    @PostConstruct
    void postConstruct() {
        // Initialize here to start streaming events
        dynamoStreams.initialize();
    }

    @GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux&amp;lt;ServerSentEvent&amp;lt;DataRoot&amp;gt;&amp;gt; streamData() {
        return dynamoStreams.stream()
                .newImages()
                .map(data -&amp;gt; ServerSentEvent.&amp;lt;DataRoot&amp;gt;builder()
                        .data(data)
                        .id(UUID.randomUUID().toString())
                        .build());
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope this makes the DynamoDB Streams easier to use in your code and I acknowledge the fact that the correct way of subscribing to the events will always be through a lambda.&lt;/p&gt;

&lt;p&gt;You can find the project over &lt;a href="https://github.com/JICA98/aws-java-dynamo-streams"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Changes I wish to do in the future:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Polling is only active when there is atleast one subscriber. (Right now it polls at a configurable interval irrespective of the subscriber count)&lt;/li&gt;
&lt;li&gt;Add more utility methods.&lt;/li&gt;
&lt;li&gt;Add support for something other than flux.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>aws</category>
      <category>dynamodb</category>
      <category>java</category>
      <category>springboot</category>
    </item>
  </channel>
</rss>
