<?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: Raja</title>
    <description>The latest articles on DEV Community by Raja (@ksvraja).</description>
    <link>https://dev.to/ksvraja</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%2F676724%2F56526ddc-8ebb-43cb-8804-2857a0457e20.jpeg</url>
      <title>DEV Community: Raja</title>
      <link>https://dev.to/ksvraja</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ksvraja"/>
    <language>en</language>
    <item>
      <title>Palmyra-FlexiQuery</title>
      <dc:creator>Raja</dc:creator>
      <pubDate>Thu, 13 Feb 2025 18:24:50 +0000</pubDate>
      <link>https://dev.to/ksvraja/palmyra-flexiquery-19l0</link>
      <guid>https://dev.to/ksvraja/palmyra-flexiquery-19l0</guid>
      <description>&lt;p&gt;An alternative to CriteriaBuilders for SpringBoot/JPA developers.&lt;/p&gt;

&lt;p&gt;As part of our roadmap on SpringBoot integration, we are introducing Flexi Query feature into Standard Springboot Controller.&lt;br&gt;
Now you can query N number of tables with criteria and order by -- all driven by Annotations.&lt;/p&gt;

&lt;p&gt;Sample project here -- &lt;a href="https://github.com/palmyralabs/springboot-query" rel="noopener noreferrer"&gt;https://github.com/palmyralabs/springboot-query&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RestController
@RequiredArgsConstructor
@RequestMapping("supplier")
public class SupplierController {
    private final ModelQueryService queryService;

    @GetMapping("")
    public void querySuppliers(@RequestParam Map&amp;lt;String, String&amp;gt; paramsMap) {
        RequestParams params = queryService.getRequestParams(SupplierModel.class, 
                paramsMap);     
        queryService.executeAndSendListResponse(params);
    }
}
&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;@PalmyraType(type = "Supplier")
public class SupplierModel {
    private Integer id;
    private String name;
    private String email;
    private String phoneNumber;
    private String address;
}

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

&lt;/div&gt;



&lt;p&gt;The above model is a simple example show-casing to query single table. More examples on multi-table model will be posted soon.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>restapi</category>
    </item>
    <item>
      <title>Annotation/Handler driven REST API</title>
      <dc:creator>Raja</dc:creator>
      <pubDate>Sat, 14 Oct 2023 15:27:52 +0000</pubDate>
      <link>https://dev.to/ksvraja/-1j1f</link>
      <guid>https://dev.to/ksvraja/-1j1f</guid>
      <description>&lt;p&gt;Just a few lines of Annotation, would provide full fledged SQL Query Capabilities for your spring boot application.. &lt;br&gt;
Query capabilities to include - filter, order on any field (or limited fields) and pagination. &lt;/p&gt;

&lt;p&gt;Would you like to explore / validate the palmyra framework and influence the development..  please let us know in the comments. &lt;/p&gt;

</description>
      <category>lowcode</category>
      <category>springboot</category>
      <category>restapi</category>
    </item>
    <item>
      <title>Simplifying CRUD Operations with Generics: Abstract CRUD Service</title>
      <dc:creator>Raja</dc:creator>
      <pubDate>Thu, 15 Jun 2023 00:46:58 +0000</pubDate>
      <link>https://dev.to/ksvraja/simplifying-crud-operations-with-generics-abstract-crud-service-3b8o</link>
      <guid>https://dev.to/ksvraja/simplifying-crud-operations-with-generics-abstract-crud-service-3b8o</guid>
      <description>&lt;p&gt;Let us explore how the intelligent use of generics can help us avoid writing repetitive boilerplate code. We'll demonstrate this by creating an abstract CRUD (Create, Read, Update, Delete) service that allows developers to enhance their productivity and concentrate more on the essential business logic. Let's get started!&lt;/p&gt;

&lt;p&gt;Step 1: Understanding the Problem&lt;br&gt;
When developing software, it's common to encounter repetitive code patterns, particularly when implementing CRUD operations. These operations often involve similar structures and functionalities that can be generalized. To address this issue, we can leverage the power of generics to create an abstract CRUD service that eliminates the need for redundant code.&lt;/p&gt;

&lt;p&gt;This helps us to write a simplified service class to focus on business logic only. example as below..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@Service
@RequiredArgsConstructor
public class MyService extends AbstractCrudService&amp;lt;Employee, EmployeeEntity, Integer&amp;gt;{
    private final EmployeeRepository employeeRepository;
    @Override
    protected JpaRepository&amp;lt;EmployeeEntity, Integer&amp;gt; getJpaRepository() {
        return employeeRepository;
    }

    @Override
    protected Optional&amp;lt;EmployeeEntity&amp;gt; findUnique(Employee model) {
        return employeeRepository.findByRegistrationNumber(model.getRegistrationNumber());
    }

    @Override
    public Employee preCreate(Employee model) {
        // Generate and assign registration number here
        model.setRegistrationNumber(generate(16));
        return model;
    }
}

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

&lt;/div&gt;



&lt;p&gt;How to achieve this?&lt;br&gt;&lt;br&gt;
let us define an abstract class with the following properties and initialization. This is required to determine the model and entity classes in the runtime.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
public abstract class AbstractCrudService&amp;lt;Model, Entity, ID&amp;gt; implements CrudService&amp;lt;Model, Entity, ID&amp;gt;, 
        CrudExtnService&amp;lt;Model, Entity, ID&amp;gt;{

    @Autowired
    private ModelMapper modelMapper;
    private Class&amp;lt;Model&amp;gt; modelClass;
    private Class&amp;lt;Entity&amp;gt; entityClass;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public AbstractCrudService() {
        ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
        Type[] typeArgs = type.getActualTypeArguments();

        this.modelClass = ((Class) typeArgs[0]);
        this.entityClass = ((Class) typeArgs[1]);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now let us define some abstract methods that must be implemented by the services. this is required get the jparepository and finding the unique records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    protected abstract JpaRepository&amp;lt;Entity, ID&amp;gt; getJpaRepository();

    protected abstract Optional&amp;lt;Entity&amp;gt; findUnique(Model model);

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

&lt;/div&gt;



&lt;p&gt;the below generic methods would provide All the CRUD operations..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Override
    public List&amp;lt;Model&amp;gt; findAll() {
        return getJpaRepository().findAll().stream().map(e -&amp;gt; onList(toDto(e), e)).toList();
    }

    @Override
    public Optional&amp;lt;Model&amp;gt; getById(ID id) {
        return toDto(getJpaRepository().findById(id));
    }

    @Override
    public Model save(Model model) {
        Optional&amp;lt;Entity&amp;gt; dbInstance = findUnique(model);
        if (dbInstance.isPresent()) {
            return update(model, dbInstance.get());
        } else {
            return create(model);
        }
    }

    @Override
    public void delete(ID id) {
        getJpaRepository().deleteById(id);
    }

    private Optional&amp;lt;Model&amp;gt; toDto(Optional&amp;lt;Entity&amp;gt; entity) {
        if (entity.isPresent()) {
            Entity e = entity.get();
            return Optional.of(onGet(modelMapper.map(e, getModelClass()), e));
        } else
            return Optional.empty();
    }

    private Model toDto(Entity entity) {
        return modelMapper.map(entity, getModelClass());
    }

    private Model create(Model model) {
        model = preCreate(model);
        Entity entity = modelMapper.map(model, getEntityClass());
        getJpaRepository().save(entity);
        return postCreate(toDto(entity), entity);
    }

    private Model update(Model model, Entity entity) {
        model = preUpdate(model);
        modelMapper.map(model, entity);
        getJpaRepository().save(entity);
        return postUpdate(toDto(entity), entity);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can define an interface with the default methods (as hooks) of preUpdate, preCreate methods etc and use this methods to perform custom operations before saving, querying the data etc.,&lt;/p&gt;

&lt;p&gt;By following this tutorial, you've learned how to harness the power of generics to create an abstract CRUD service. This approach allows you to eliminate repetitive boilerplate code and focus more on implementing the core business logic of your application. As a result, your development process becomes more efficient and maintainable. Experiment with generics in your future projects and unlock the potential for increased productivity!&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>jpa</category>
    </item>
    <item>
      <title>Generics and Functional Interfaces - A practical example</title>
      <dc:creator>Raja</dc:creator>
      <pubDate>Wed, 24 May 2023 06:29:02 +0000</pubDate>
      <link>https://dev.to/ksvraja/generics-and-functional-interfaces-a-practical-example-d6l</link>
      <guid>https://dev.to/ksvraja/generics-and-functional-interfaces-a-practical-example-d6l</guid>
      <description>&lt;p&gt;Problem Statement: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On an multi-threaded environment a record shall be created in the database by one thread and another thread may be interested to fetch the record. Due to the multi threading nature, the second thread may need to wait or retry couple of times before getting hold of the record. &lt;/li&gt;
&lt;li&gt;After performing an action in remoete web service, we might need to poll the service for the updated status. (though this is inefficient than using the message or event based communication). &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both of the above problem statements have a common theme of "getting the latest data by polling". A simple implementation would be put an for loop for the number of retries to fetch the data. if the data is fetched, the value is immediately returned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SneakyThrows&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getRecord&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++){&lt;/span&gt;
      &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;employeeRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isPresent&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us consider the scenario, where we would need to write the similar code block to retrieve the data from an external web serivces, a similar implementation needs to be written as well. &lt;/p&gt;

&lt;p&gt;The above-retry logic can be implemented using Generics and functional interfaces as below. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generic function&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Utils&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
 &lt;span class="nd"&gt;@SneakyThrows&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getWithRetry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;Supplier&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;supplier&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++){&lt;/span&gt;
            &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;supplier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isPresent&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Invoking the function&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getRecord&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWithRetry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;employeeRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other data fetching functions can be defined as Supplier interfaces or lambda expressions and invoked using the 'getWithRetry' function. By implementing the Generic function, the retry logic can be reused across as needed.&lt;/p&gt;

</description>
      <category>java</category>
      <category>generic</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
