Normal view

There are new articles available, click to refresh the page.
Today — 4 July 2025IRC mates

Emacs - hyperdrive

2 July 2025 at 00:00

Last Updated: 02nd July 2025

While I was looking into past EmacsConf talks (just to explore Emacs…), I found this talk about hyperdrive.el: Peer-to-peer filesystem in Emacs in EmacsConf 2023, where Prot and Joseph explained about this decentralized drive and how to use it from Emacs.

This seemed to be a nice way to share files without any third party online services and also embraces privacy too (We can even stream audio/video as well !). So I just want to give it a try and explore this and so I’m going to share what I’ve done so far.

First I followed the manual to install it. There are two parts to it. One to install hyperdrive.el from NonGNU ELPA and after that install the gateway (hyperdrive-gateway-ushin) that helps in connecting with the network.

After the installation and using the default config, when I tried to start the gateway, I wasn’t able to and had following error,

Error running timer: (hyperdrive-error "Gateway failed to start (see #<buffer *hyperdrive-start*> for errors)")

in my Emacs 30.1. This persisted even if I installed the gateway manually.

I tried searching the web but coudn’t find a way to solve this (I think my searching skills aren’t good enough…), so I asked Joseph in XMPP chat room and he asked me to show the error that is being thrown out when run directly in command-line based on which we found that the gateway binaries being distributed has a dependency issue with cryptography library libsodium and a packaging problem as well.

So then I tried building the gateway myself from source and then it worked but not through Emacs and then Joseph pointed me to set these two path variables: hyperdrive-gateway-program & hyperdrive-gateway-directory and then it worked from Emacs itself and was able to access Prot and USHIN’s hyperdrives.

Still I get this error message when I access any hyperdrive: Error running timer ‘plz--respond’: (void-variable node) but able to access them.

In future, I plan to use this, whenever I want to share some large files or misc ones which I can’t share or post through my blog. Here’s the link to my public hyperdrive:

hyper://3y3fx1k4ifbw6uw7wzxhzkm5azp5gkbet53r6tc7a5qzsxeabeoo

Next, I wanted to delve more for e.g. on latest features like peer graph, hyperdrive-org-transclution, etc and it seems that we can also use it from mobile as well. Also explore how this hyperdrive works in contrast to IPFS and Torrent.

I will update those here when I complete them. Thanks for reading. Share me your thought about me or my blog to any of my social media handles.

PS: I also learnt about this keybinding C-x C-j (dired-jump) which opens the dired buffer of current file’s directory !.

More Emacs explorations to come… :)

The 2025 Books List

24 May 2025 at 00:00

Last Updated 24th Jun 2025

Here’s the list of books that I’ve read so far and about to…

Read

  • 7.83 ஹெர்ட்ஸ்

a science fiction novel in tamil by K Sudhakar dealing with wolves, remote mind control and a whole deal of terror behind all those. An interesting, page turning read stuffed with a load of info on bio-chemistry, wild life etc.

  • The American Trap

written by Frederic Pierucci, a senior executive in Alstom, who unfortunalely got held as a hostage for FCPA violations of Alstom, shares the struggles he faced to overcome it. Got shocked to know about these hostage based diplomacy and corporate practices.

  • Bulls, Bears and other Beasts - A story of Indian Stock Market

written by Santosh Nair, former editor of moneycontrol and many other finance journals. Tells the history of our Indian Stock Market From 80s to pre-COVID from a trader’s perspective, covering everything from cartels, reliance, harshad mehta to bubbles, formation of NSE, SEBI and so on. Must book to know about the history so far in a story fashion.

  • Learn Javascript in Tamil

written by Nithya long time back in Kaniyam. Had a glance over it, to learn about JS basics which I needed inorder to understand the JS in my dashboard and as well as for XSS payloads as well (I’d been learning about some basics of Web Security, from Cyber Adam as I got interested to know about common vulnerabilities found in webapps and how to check for that in my dashboard which I’d vibed). It’s a good book to get some idea about JS and JQuery.

Current

  • அசிமவ்வின் தோழர்கள்

    an another tamil science fiction short story collection written by Ayesha Era. Natarasan. Usually used to read all his science fiction and popular science books. The book setting is in a “fantasy science fiction world” where popular sci-fi solves current sociological problems or expresses humor, etc.

  • Bottle of Lies - Ranbaxy and the Darkside of Indian Pharma

    written by investigative journalist Katherine Eban, exposing quality issues found in Ranbaxy, the generic drug manufacturer and why it had happened.

  • 100$ Startup - Reinvent the way you make a living
  • Crypto Confidential

Next

  • Heart of Darkness

  • Selected stories by Anton Chekov

  • Bed of Procrustes

    • as a precursor to enter into Taleb’s world.

கவிச்சோலை

11 May 2025 at 00:00

பீரங்கிகளைத் தகர்த்த பேனா !!

எழுத்தாளனின்    ஓர்     பேனா      முனை
சிந்தனைகளை கொண்டுச் செல்லும் ஏவுகணை 
அது    மனதை    தாக்கும்    ரசாயனவினை
இது    எழுப்பும்     பல      எழுச்சியினை !


இது  மனங்களில்   செய்யும்  யுத்தகாண்டம் !
பிற   உயிர்களைக்  கொல்லா       பலிபீடம்
நகரங்களைத்    தகர்க்காத    சக்தி     பீடம்
அதனால் பீரங்கிகள் தகரும் பேனாமுனையிடம்

NITT-ன் “NITTFEST’25” கலைத்திருவிழாவில், கவிச்சோலை போட்டியில், “பீரங்கிகளைத் தகர்த்த பேனா” என்ற தலைப்பிற்காக எழுதப்பட்டது. என்னுடைய முதல் கவிதை :) அதனால் பரிசு எதுவும் பெறவில்லை.

Beej’s GDB guide in Tamil

5 November 2024 at 00:00

GDB க்கான பீஜின் விரைவான வழிகாட்டி (Beej’s Quick Guide to GDB)

I’ve translated the Beej’s Guide on GDB to tamil. It is based on this project idea put forth by Thanga Ayyanar aka Gold Ayan in Kaniyam Foundation’s Project Ideas. Initially I planned to do it as a part of Hacktoberfest but It took time and in the meanwhile I also got busy with other works. Finally the translation is out. If you found any mistakes you can raise a issue in the repo where it has been hosted. shrini said after some review it will be made as a series of few posts in Kaniyam website.

This is my First Open Source Contribution, so I feel happy that I’ve started to give back something to FOSS, Tamil community. It was also discussed by Thanga Ayyanar in Nov 3 - Kanchi LUG Weekly News. Hoping to contribute more in future!

Learning Baremetal Programming in Cortex M4 (STM32 F4) - 1

17 September 2024 at 00:00

I am following this Baremetal Programming Series (Low Byte Productions Channel), inorder to learn about ARM microcontrollers, writing drivers (I've a goal to write a driver for a Serial Communication Protocol maybe CAN or Q-SPI, etc.) and learning some C constructs as well which I will then emulate in Renode.

Some notes,

  • MACROS{.verbatim} are instructions that asks the C preprocessor to do text replacements.

  • Behind the Scenes of libopencm3{.verbatim}

    • The memory mapped address of a pin is calculated in the pre-processing stage itself using macros.
  • SYS_TICK{.verbatim} is like a Wall Clock.

  • weak functions{.verbatim} are functions whose implementation can be redefined.

For Renode implementation, I just loaded the ELF of program used in the episode as like for the Hello World, Intro to Renode from Interrupt and I did used the same Makefiles and Linker scripts once again. (Those 2 seems to be a huge mess ? Is it ?)

I shouldn't be lazy enough to tinker them in future.

Then Looked the state of Pin A5 (External LED) and I could see that the state toggles. I think I could even log the data or check this working using Robot Framework.

Next, I need to look at Renode docs to discover more functionalities and then continue with Episode 3 on PWM and Timers!

KLUG and Life Update

1 September 2024 at 00:00
  • After a long time, I am writing this blog as I had an hectic semester (Semester 6) with acads, Spider R&D, BMS (Battery Management Systems) project and participating in TOP-IMSD'24 (Will write one about this in future!) (Ah Placement Exams too :|).

  • Then I had went for an Internship to a company as a Hardware Research Intern but I was told to automate some testing instruments like DSO, Load Analyzer, Logic Analyzer etc.

  • Finally after all these I entered into my final year and having some peace i.e time to work on some other exciting projects and improve myself!. So I'm planning to be a little regular in blogging which implies that I do will spend some time exploring new.

Notes from KLUG session

  • Today I attended the Kanchipuram Linux Users Group's (KLUG) Weekly Meet for a while and I got to know about,
    • dotenvx and sujo

dotenvx

  • To manage env, config management for whatever software, programs you develop in whichever language and also solving all problems previously was with dotenv !

soju

  • It is a IRC Bouncer that can be used for logging data from IRC channels. Need to explore on how to use and configure it.

  • Also got to know about how to generate PDFs of websites using headless chromium.

TIL (22/12/2023)

22 December 2023 at 00:00

I was thinking about what I can do next with ESP32 and micro-ROS and so I thought to learn RTOS first as it is also used and then dwelve into microROS.

For learning RTOS(gonna a start with FreeRTOS itself), I came across this tutorial which looks good.

Then I learned about Policy Gradient methods to solve MDPs from Deep RL course I’m doing from HF. Really the math is little involved which I have to dwelve step by step. While going across Policy Gradient Theorem derivation, I came across few tricks and assumptions used, for e.g.

  • Reinforce Trick: \(\frac{\nabla_{\theta}P(\tau)}{P(\tau)} = \nabla_{\theta}\\log(P(\tau))\)

  • State Distribution is independent of parameters($\theta$) of policy (I think this implies that the choice of action from action distribution given by the policy isn’t covered by the policy i.e its not a part of policy I guess).

  • Sampling m trajectories from the trajectory($\tau$) distribution

Next I have too do the hands-on and refer more about it.

RTOS

  • We can use RTOS when we have to run many tasks concurrently or if it’s time demanding, which can’t be done in general Super loop configurations(I mean the usual setup and loop parts).

  • ESP32 uses a modified version of FreeRTOS which supports its SMP (Symmetric MultiProcessing) architecture to schedule tasks by using both cores! (but this tutorials is only for multi-tasking in single core)

Task Scheduling

  • Context Switching : How are tasks are switched from one to another.

  • Task pre-emption

TIL (21/12/23)

21 December 2023 at 00:00

Reproducability

  • From this blog, I got aware of this reproducibility issue in RL i.e execution of same alogrithm in same enironment gives different results each time. It might be due different initial conditions, seeds etc for e.g. issues faced when reproducing a deep RL paper by Matthew Rahtz.

  • For which the author proposes some statistical tests and he has a written a paper about this.

May be I have to have a look on it later.

micro-ROS

Today I did a hello world in micro-ROS. micro-ROS is used for interfacing ROS with resource constrained embedded devices. I had bought an ESP32-WROOM board since micro-ROS supports ESP, I thought of trying it and followed this post. In which I did,

  • I had compiled the int32_publisher example using idf.py(provided by ESP) and flashed it to my ESP board.

  • Then ran a micro-ROS agent(docker container) on my laptop and which recieved messages from ESP.

Messages Published

Basically we have to write a C code using ESP,micro-ROS and RTOS(FreeRTOS) libraries which then can be compiled & flashed into ESP and then it works accordingly. I had this issue with specifying the port for the agent.

Have to go through the rclc API.

I am gonna work on some project like with FreeRTOS & micro-ROS ?

TIL (20/12/2023)

20 December 2023 at 00:00

Bayesian Optimization

Bayesian optimization is a powerful strategy for finding the extrema of objective functions that are expensive to evaluate. It is particularly useful when these evaluations are costly, when one does not have access to derivatives, or when the problem at hand is non-convex.

The Bayesian Optimization algorithm can be summarized as follows:

1. Select a Sample by Optimizing the Acquisition Function.
2. Evaluate the Sample With the Objective Function.
3. Update the Data and, in turn, the Surrogate Function.
4. Go To 1.
  • It uses a
    • Surrogate function - that approximates the relationship between I/O data of the sample. There are many ways to model, one of the ways is to use Random Forest/Gaussian Process (GP, with many different kernels) i.e here we’re kind of approximating the objective function such that it can be easily sampled.
    • Acquisition function - It gives a sample that is to evaluated by the objective function. It is found by optimizing this function by various methods and it balances exploitation and exploration (E&E)[1].
  • It is highly used in Tuning of Hyperparameters e.g. Optuna,HyperOpt.

Optuna

I am trying to use it for HPO of lunar lander environment, initally results weren’t that good. I think it’s because of not giving a proper intreval i.e a large intreval that won’t result in a good choice of HP. May be I have to give try other ways to make it work.

Paper Reading

References

  1. https://machinelearningmastery.com/what-is-bayesian-optimization/

Hello World !

14 January 2023 at 00:00

Hi,

This is my first blog post. My main intention to have a blog is that,

  • It will help me to think about what I wish to write up such that it is understandable by others which implies that I should have understood it at first.
  • It will enhance my writing skills.
  • Mainly, It will be a kind of “Journal”ing and that it would be nicer to look about what you have done/thought in the past.
Before yesterdayIRC mates

Convert List into Paging results using java 8

In this tutorial, we show the list of result in paging concepts. Like page 1 and no. of results 10.

Page 1 has 1-10 results, page 2 has 11-20 results, page 3 has 21-30 results.

Like page 2 and no. of results 20.

Page 2 has 31-40 results, page 3 has 3-30 results.

	List<Owner> ownerList = ownerRepo.findAll();
    int pageNumber =1, pageSize=5;
	List<Owner> pagingResult =ownerList.stream() 
			.skip((long) (pageNumber -1) * pageSize) 
			.limit(pageSize) 
			.toList(); 	

Explaination:

In above code, ownerList have list of Owner Objects.

  • Convert the list into steam by steam().
  • Skip the first results .
    • like page 2 and results 5 means skip the 1-5 then start from 6 – 10.
    • so we multiple (2-1) * 5 to result is 5 => we get result start from 6.
  • limt the pages .
    • we got the result so we limit the result to pageSize.
    • limit(pageSize).
  • Convert the result into list.

Reference

https://www.digitalocean.com/community/tutorials/java-stream-collect-method-examples

https://www.youtube.com/watch?v=J2pxQFmQsN0

Spring boot annotation used in entity class

Class based Annotation:

  • @Entity – used to indicates the class is below to JPA entites.
  • @Table – is used to indicates the table name.
  • @MappedSuperClass – is used to parent entity, which can be inherited by many entities, but it won’t be mapped to its own table. we cannot use @Entity annotation on this class.
@MappedSuperclass
public abstract class BaseEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // Getters and setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

@Entity
@Table(name = "employees")
public class Employee extends BaseEntity {

    private String firstName;
    private String lastName;
    
    // Constructors, getters, setters, other fields...
}
  1. In this example, the BaseEntity class is annotated with @MappedSuperclass. It contains the common fields that you want to share across multiple entity classes.
  2. The Employee class inherits from BaseEntity, effectively inheriting the id field from the superclass.
  3. By using @MappedSuperclass, you’re able to create a common base class for your entity hierarchy while allowing each subclass to include additional fields and annotations specific to their needs.
  4. This promotes code reusability and maintains a clean and structured entity hierarchy.

Primary Keys

  • Define a primary key using @Id.
  • Use @GeneratedValue with appropriate strategy for generating primary key values (e.g., GenerationType.IDENTITY, GenerationType.SEQUENCE)
@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // other fields, getters, setters
}

Associations

It says the relationship between two entity class.

  1. Use @OneToOne, @OneToMany, @ManyToOne, and @ManyToMany to define relationships between entities.
  2. Use fetch attribute to control loading behavior (e.g., LAZY or EAGER).
  3. Utilize mappedBy to define the owning side of bidirectional relationships.
@Entity
public class Department {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "department",cascade=CascadeType.ALL)
    private List<Employee> employees;

    // Constructors, getters, setters, other fields...
}

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;

    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;

    // Constructors, getters, setters, other fields...
}

Cascading Operations

  • Use cascade attribute to specify cascading operations (e.g., CascadeType.ALL, CascadeType.PERSIST).
  • Be cautious with cascading DELETE to avoid unintentional data loss.
import javax.persistence.*;
import java.util.List;

@Entity
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Book> books;

    // Constructors, getters, setters, other fields...
}

@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;

    @ManyToOne
    @JoinColumn(name = "author_id")
    private Author author;

    // Constructors, getters, setters, other fields...
}
  1. CascadeType.ALL: This option specifies that all operations (e.g., persist, merge, remove) should be cascaded from the parent entity (Author) to the child entity (Book).
  2. orphanRemoval = true: This option specifies that when an Author entity’s reference to a Book entity is removed from the books collection, the orphaned Book entity should also be removed from the database

When you perform a cascading operation on the Author entity, the corresponding operation will cascade to the associated Book entities. For instance.

Author author = new Author();
author.setName("J.K. Rowling");

Book book1 = new Book();
book1.setTitle("Harry Potter and the Sorcerer's Stone");
book1.setAuthor(author);

Book book2 = new Book();
book2.setTitle("Harry Potter and the Chamber of Secrets");
book2.setAuthor(author);

author.setBooks(Arrays.asList(book1, book2));

// Cascading persist: Saving the author will also save both associated books.
entityManager.persist(author);

Likewise, cascading operations work for merge, remove, and other entity operations, reducing the need for explicitly managing related entities persistence.

Validation

Use validation annotations (@NotNull, @Size, etc.) to enforce data integrity constraints directly in the entity class.
Combine JPA validation with Spring’s @Valid annotation to automatically validate incoming data.

@Entity
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "Title is required")
    @Size(max = 100, message = "Title must be at most 100 characters")
    private String title;

    @OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
    private List<Comment> comments;

    // Constructors, getters, setters, other fields...
}

@Entity
public class Comment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "Text is required")
    @Size(max = 500, message = "Text must be at most 500 characters")
    private String text;

    @ManyToOne
    @JoinColumn(name = "post_id")
    private Post post;

    // Constructors, getters, setters, other fields...
}

Auditing

  • Implement entity auditing by adding fields like @CreatedBy, @CreatedDate, @LastModifiedBy, and @LastModifiedDate for tracking who created or modified an entity and when.
  • Utilize Spring’s @EntityListeners to manage the auditing behavior.
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class Auditable {
    @CreatedBy
    protected String createdBy;

    @CreatedDate
    @Column(nullable = false, updatable = false)
    protected LocalDateTime createdDate;

    @LastModifiedBy
    protected String lastModifiedBy;

    @LastModifiedDate
    protected LocalDateTime lastModifiedDate;

    // Getters and setters...
}
  1. @EntityListeners(AuditingEntityListener.class): This annotation specifies that this entity should be audited using the provided entity listener class. Spring Data JPA will automatically update the auditing fields before persisting or updating the entity.
  2. @MappedSuperclass: This annotation indicates that this class is not an entity itself but serves as a base class for other entities. It allows attributes and behaviors to be inherited by other entities.
  3. @CreatedBy: This annotation specifies the field to store the username of the user who created the entity.
  4. @CreatedDate: This annotation marks the field to store the timestamp when the entity was created. The nullable and updatable properties are set to false to ensure that this field is populated during creation and not updated afterwards.
  5. @LastModifiedBy: This annotation specifies the field to store the username of the user who last modified the entity.
  6. @LastModifiedDate: This annotation marks the field to store the timestamp when the entity was last modified.

By implementing auditing, you can track who created or modified entities and when those actions occurred. This information can be invaluable for monitoring and maintaining your application’s data.

Enums and Enumerated Types

  • Use Java enums for fields with predefined values.
  • Annotate enum fields with @Enumerated(EnumType.STRING) to store enum values as strings in the database.
@Entity
public class Task {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Enumerated(EnumType.STRING)
    private TaskStatus status;
    // other fields, getters, setters
}

public enum TaskStatus {
    TODO, IN_PROGRESS, DONE
}

Reference:

To-Do Application on Spring boot

I am going to create To-do list.

Spring boot dependencies.

  1. spring boot web
  2. jdbc postgreSQl driver
  3. spring- JPA
  4. Thyme-leaf

Entities

I am going to create two entities. They are task and Todo. It has one to many, It means todo has many task. Create the field and getter and setter methods.

TodoList class

It has id, name and List<Task>. Create getter and setter method.

Then we create bidirectional relationship between todo have task. so we create mappedBy the todo object on task. so task can create foreign key for todo list.

@Entity
public class TodoList {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	private String name;
	
	@OneToMany(mappedBy = "todoList", cascade = CascadeType.ALL, orphanRemoval = true,fetch = FetchType.EAGER)
	private List<Task> taskList= new ArrayList<>();
	
	@ManyToOne
	@JoinColumn(name = "user_idn")
	private Users users;
	// no-arg constructor and getter and setter
}

Task class

It has id and name and todo object. Then we create getter and setter method.

The foreign key create in this table, because we mapped this todo object is mapped on that class. joinColumn name is the foreign key name.

@Entity
public class Task {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	private String name;
	private boolean status;
//	private Locale locale; // date and time

	@ManyToOne
	@JoinColumn(name = "todo_list_id")
	private TodoList todoList;
}

Repository Interface

Simple that create two interface one for task and todo which can extend the JPARepository.

public interface TaskRepository extends JpaRepository<Task, Long> {
     }

     public interface TaskRepository extends JpaRepository<Task, Long> {
     }

DB and JPA configuations

 spring.datasource.url=jdbc:postgresql://localhost:5432/login
spring.datasource.username=progres
spring.datasource.password=1234
spring.datasource.driver-class-name=org.postgresql.Driver

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform= org.hibernate.dialect.PostgreSQLDialect

Controller class with html

We are going to create 7 task with frontend html with thyme leaf. Map the class with “/todos” using @RequestMapping.

Click the arrow or triange (|>) to see full details.

1. show all todo list

It method is used to default page of /todos page. It have List of Todo and newlist which can return to html page.

@GetMapping
    public String listTodoLists(Model model) {
        model.addAttribute("todoLists", todoListRepository.findAll());
        model.addAttribute("newTodoList", new TodoList());
        return "todo-lists";
    }
2. create the todo list

Then we press create list button on html. we got newlist from getMapping that List pass through @modelAttribute. That list can save in repository.

  @PostMapping
    public String createTodoList(@ModelAttribute TodoList todoList) {
        todoListRepository.save(todoList);
        return "redirect:/todos";
    }
3. show tasks from todo list

Then we enter into the a list, it have many task. That can be shown by this method. we get the list by id and we pass that list of task and new task to html.

     @GetMapping("/{listId}")
    public String viewTodoList(@PathVariable Long listId, Model model) {
        TodoList todoList = todoListRepository.findById(listId)
            .orElseThrow(() -> new IllegalArgumentException("Invalid list id"));
        
        model.addAttribute("todoList", todoList);
        model.addAttribute("newTask", new Task());
        return "tasks";
    }
4. create the task from todo list

Then we press create task button on html. we got new task from getMapping that task pass through @modelAttribute. That list can save in repository.

  // Add task to a todo list
    @PostMapping("/{listId}/tasks")
    public String addTask(@PathVariable Long listId, @ModelAttribute Task task) {
        TodoList todoList = todoListRepository.findById(listId)
            .orElseThrow(() -> new IllegalArgumentException("Invalid list id"));
        
        task.setTodoList(todoList);
        taskRepository.save(task);
        return "redirect:/todos/" + listId;
    }
5. Toggle the task or not

Then we press todo checkbox it can be tick. Same find the task by taskId. That task setCompleted and save it again in task. Return redirect://todos/+listId, it redirect to getMapping or this Todo List.

     // Toggle task completion status
    @PostMapping("/{listId}/tasks/{taskId}/toggle")
    public String toggleTask(@PathVariable Long listId, @PathVariable Long taskId) {
        Task task = taskRepository.findById(taskId)
            .orElseThrow(() -> new IllegalArgumentException("Invalid task id"));
        
        task.setCompleted(!task.isCompleted());
        taskRepository.save(task);
        return "redirect:/todos/" + listId;
    }
6. delete the todo list

Then we press delete button from list on html. we remove from repository. Return the getMapping of current list.

     @PostMapping("/{listId}/delete")
    public String deleteTask(@PathVariable Long listId) {
        taskRepository.deleteById(taskId);
        return "redirect:/todos/" + listId;
    }
7. delete the task from task list

Then we press delete button on html. We delete task from task repository. We return and redirect to getmapping of current task list.

  @PostMapping("/{listId}/delete")
    public String deleteTodoList(@PathVariable Long listId) {
        todoListRepository.deleteById(listId);
        return "redirect:/todos";
    }

Controller full code

  @Controller
@RequestMapping("/todos")
public class TodoController {

    @Autowired
    private TodoListRepository todoListRepository;
    
    @Autowired
    private TaskRepository taskRepository;

    // Show all todo lists
    @GetMapping
    public String listTodoLists(Model model) {
        model.addAttribute("todoLists", todoListRepository.findAll());
        model.addAttribute("newTodoList", new TodoList());
        return "todo-lists";
    }

    // Create new todo list
    @PostMapping
    public String createTodoList(@ModelAttribute TodoList todoList) {
        todoListRepository.save(todoList);
        return "redirect:/todos";
    }

    // Show tasks from todo list
    @GetMapping("/{listId}")
    public String viewTodoList(@PathVariable Long listId, Model model) {
        TodoList todoList = todoListRepository.findById(listId)
            .orElseThrow(() -> new IllegalArgumentException("Invalid list id"));
        
        model.addAttribute("todoList", todoList);
        model.addAttribute("newTask", new Task());
        return "tasks";
    }

    // Add task to a todo list
    @PostMapping("/{listId}/tasks")
    public String addTask(@PathVariable Long listId, @ModelAttribute Task task) {
        TodoList todoList = todoListRepository.findById(listId)
            .orElseThrow(() -> new IllegalArgumentException("Invalid list id"));
        
        task.setTodoList(todoList);
        taskRepository.save(task);
        return "redirect:/todos/" + listId;
    }

    // Toggle task completion status
    @PostMapping("/{listId}/tasks/{taskId}/toggle")
    public String toggleTask(@PathVariable Long listId, @PathVariable Long taskId) {
        Task task = taskRepository.findById(taskId)
            .orElseThrow(() -> new IllegalArgumentException("Invalid task id"));
        
        task.setCompleted(!task.isCompleted());
        taskRepository.save(task);
        return "redirect:/todos/" + listId;
    }

    // Delete a task
    @PostMapping("/{listId}/tasks/{taskId}/delete")
    public String deleteTask(@PathVariable Long listId, @PathVariable Long taskId) {
        taskRepository.deleteById(taskId);
        return "redirect:/todos/" + listId;
    }

    // Delete a todo list
    @PostMapping("/{listId}/delete")
    public String deleteTodoList(@PathVariable Long listId) {
        todoListRepository.deleteById(listId);
        return "redirect:/todos";
    }
}

Html code

Html has two page one for todo list and another for task list.

Todo list.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Todo Lists</title>
	<link rel="icon" type="image/x-icon" href="/aaeranLogo.ico" />
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-4">
    <h1>My Todo Lists</h1>
	    <!-- Form to create new todo list -->
    <form th:action="@{/todos}" th:object="${newTodoList}" method="post" class="mb-4">
        <div class="input-group">
            <input type="text" th:field="*{name}" class="form-control" placeholder="New list name" required>
            <button type="submit" class="btn btn-primary">Create List</button>
        </div>
    </form>

	<!-- display the todo list -->
    <div th:each="todoList : ${todoLists}" class="card mb-3">
        <div class="card-body">
			
		   <h2 class="card-title">
                <a th:href="@{/todos/{id}(id=${todoList.id})}" th:text="${todoList.name}">List Name</a>
                <span class="badge bg-secondary" th:text="${todoList.taskList.size()}">0</span>
            </h2>
            
            <form th:action="@{/todos/{id}/delete(id=${todoList.id})}" method="post" class="d-inline">
                <button type="submit" class="btn btn-sm btn-danger">Delete List</button>
            </form>
        </div>
    </div>
</div>
</body>
</html>

Task.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Tasks</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-4">
    <h1>Tasks for <span th:text="${todoList.name}">List Name</span></h1>
    <a href="/todos" class="btn btn-secondary mb-3">Back to Lists</a>
    
    <!-- Form to add new task -->
    <form th:action="@{/todos/{id}/tasks(id=${todoList.id})}" th:object="${newTask}" method="post" class="mb-4">
        <div class="input-group">
            <input type="text" th:field="*{name}" class="form-control" placeholder="New task description" required>
            <button type="submit" class="btn btn-primary">Add Task</button>
        </div>
    </form>
    
    <div th:each="task : ${todoList.taskList}" class="card mb-2">
        <div class="card-body d-flex align-items-center">
            <form th:action="@{/todos/{listId}/tasks/{taskId}/toggle(listId=${todoList.id}, taskId=${task.id})}" 
                  method="post" class="me-3">
                <input type="checkbox" 
                       th:checked="${task.status}" 
                       onChange="this.form.submit()"
                       class="form-check-input" 
                       style="transform: scale(1.5);">
            </form>
            
            <span th:class="${task.status} ? 'text-decoration-line-through text-muted' : ''" 
                  th:text="${task.name}" 
                  class="flex-grow-1">Task description</span>
            
            <form th:action="@{/todos/{listId}/tasks/{taskId}/delete(listId=${todoList.id}, taskId=${task.id})}" 
                  method="post" class="ms-2">
                <button type="submit" class="btn btn-sm btn-danger">Delete</button>
            </form>
        </div>
    </div>
</div>
</body>
</html>

Reference :

Deploy our Spring boot application for free.

In this blog, we are going to deploy out spring boot application with PostgreSQL using to

  • Web site on render.com
  • PostgreSQl on neon.com

Create an Application

We can create application that can interact with html and controller layer of our application. Then, service layer that can interact with Repository layer.

Frontent (Thyme Leaf)

I am going to create html that can integrate with thyme leaf.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
	<title> first page </title>	
</head>
<body>
	<div>
		<h1>Heading name</h1>
		<p><span th:text="${word}"></span></p> 
	</div>	
	
	<div>
			<h1>list</h1>
			<p><span th:text="${word}"></span></p> 
	</div>
</body>
		
</html>

Create a html in spring boot

Go to template and create our html pages and Go to static from create js and CSS files. I paste above code on the index.html.

Spring boot Controller layer

I create controller class which can map the html with java class.

@Controller
public class ControllerClass {
	
	@GetMapping
	public String getInitialisePage(Model model) {
		String p = "ravana";
		model.addAttribute("word",p);
		return "index";
	}
}

Create a Repository Interface

we are going to do dataBase configuaration and spring JPA here.

Configuration of Database and JPA

Configure the Database and JPA on Application.Properties.

spring.datasource.url =  ${DATASOURCE_URL}
spring.datasource.username= ${DATASOURCE_USERNAME}
spring.datasource.password= ${DATASOURCE_PASSWORD}
spring.datasource.driver-class-name=org.postgresql.Driver

spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform= org.hibernate.dialect.PostgreSQLDialect

Now, the database url, userName, password are assigned as Environment variables. So, now we want to assign as in different approach by IDE.

Using Eclipse or Spring tool suit IDE

  • Right click on our project.
  • Run as -> run configurations
  • click the environment and set the name and value.
  • Eg. name = DATASOURCE_URL and value = our jbdc url
  • Eg. name = DATASOURCE_USERNAME and value = our username
  • Eg. name = DATASOURCE_PASSWORD and value = our Password

Create jar file from our project

When we create Spring boot project we have .mvn file. Delete the test related dependency and class.

    ./mvnw clean package
If not work copy this below code. This is work on linux only
      export SPRING_DATASOURCE_URL="jdbc:postgresql://localhost:5432/login"
      export SPRING_USERNAME="postgres"
      export DATASOURCE_PASSWORD="1234"

      //don't be panic as run again to run ./mvnw clean package
      // else give this command
      // remove the test depandancy and delete src/main/test.
      // ./mvnw clean package

Create a docker file

Download docker and docker desktop on our system. Create a file on our project, named as Dockerfile.

     # Use an official Maven image to build the Spring Boot app
     FROM maven:3.8.4-openjdk-17 AS build
    
    # Set the working working directory
    WORKDIR /app
    
    # Copy the pom.xml and install dependencies
    COPY pom.xml .
    RUN mvn dependency:go-offline

    # Copy the source code and build the application
    COPY src ./src
    RUN mvn clean package -DskipTests # This will download the all depandencies
    
    # Use an official OpenJDK image to run the application
    FROM openjdk:17-jdk-slim

    #Set the working directory
    WORKDIR /app

    # Copy the built JAR file from the build stage
    COPY --from=build /app/target/file-name.jar .
      # my fileName is demo-0.0.1-SNAPSHOT so COPY --from=build /app/target/demo-0.0.1-SNAPSHOT.jar
    
    # Expose port 8080
    EXPOSE 8080

    # Specify the command to run the application
    ENTRYPOINT ["java", "-jar", "/app/notes-0.0.1-SNAPSHOT.jar"]
      # change the notes-0.0.1-SNAPSHOT.jar into fileName demo-0.0.1-SNAPSHOT
      # ENTRYPOINT ["java", "-jar", "/app/demo-0.0.1-SNAPSHOT.jar"]
 

Create Docker image

After create docker file. Then run the below command on terminal. It will generate a docker image. Check the image on your docker or not.

  docker build -t demo_deployment .

  docker tag demo-deployment kalaiarasan23/demo-deployment:latest

  docker push kalaiarasan23/demo-deployment:latest

Host our Database

Go to neon.tech, create account we got free 500MB space DB. Now create project and add.

Important is to get the configutation because we will use in application part.

 postgresql://username:password2@ep-shiny-butterfly-a1el75x8-pooler.ap-southeast-1.aws.neon.tech/DB?sslmode=require

    Select the environmental variable on render.com
    DATASOURCE_URL=jdbc:postgresql://ep-shiny-butterfly-a1el75x8-pooler.ap-southeast-1.aws.neon.tech/DB?sslmode=require
    DATASOURCE_USERNAME=username
    DATASOURCE_PASSWORD=password

Host the Web application

Go to render.com and open dashboard -> Click new web services ->click image. Enter the environment variable at last. Deploy our web site and verify the server online or not.

Reference :

Place button on wiki Page.

I got a task, that to add a cody in wiktionary side. For do this we have knowledge of Wiki Gadget.

Create an Account on wiki page:

  • If we want to change in wiki page. First we want to create account in wiki.
  • Then we create a own javascript page for make change.
  • The changes can be seen in our page only.
  • If we want to change globally, i have a knowledge of Gadget_kitchen in wiki.

Find the place that have to change

  • Go to wiktionary site and seach any word it.
  • open F12 to view inspect and find the place heading usi.
  • I found in
    • body -> div(mw-page-container) -> div(mw-page-container-inner) -> div(mw-content-container) ->main -> header.
    • header contains nav, h1, div(title-shortlink-container), div(vector-dropdown.
    • h1 must be copy and button place near to h1 or div(title-shortlink-container).

Create common.js page and paste the code

Code:
const observer = new MutationObserver(() => {
    const heading = document.querySelector(".title-shortlink-container");
    if (heading) {
        // Create the button element
        const button = document.createElement("button");
        button.textContent = "Copy Text";
        button.style.marginLeft = "10px"; // Add some spacing from the container

        // Insert the button next to the .title-shortlink-container
        heading.insertAdjacentElement("afterend", button);

        // Add an event listener to copy the text
        button.addEventListener("click", () => {
            const textToCopy = heading.textContent.trim(); // Get only the container's text
            navigator.clipboard.writeText(textToCopy).then(() => {
                alert("Text copied: " + textToCopy);
            }).catch(err => {
                console.error("Failed to copy text: ", err);
            });
        });

        observer.disconnect(); // Stop observing once the element is found
    }
});

// Observe the document for dynamic changes
observer.observe(document.body, { childList: true, subtree: true });

Code Explanation :

  1. Use Document. querySelector for get the element of the .title-shortlink-container class. This class is for shortURL className and assign to variable Heading.
  2. If the Heading is not null. Then we create the button and styles.
  3. The Button is placed next to link. Use heading.insertAdjacentElement(“afterend”, button);
  4. Button action create a function in addEventListener.
  5. Get the link by heading.textContent and store in textToCopy
  6. For copy the text use navigator.clipboard.writeText(textToCopy)
  7. Then pop alert for the event.
  8. if error catch throw error message.
Problem faced (dynamically loaded content)
  1. First i use DOMContentLoaded. It cannot work in wiki.
  2. Then i use Polling (Setintervel for a Certain time). It works partcially.
  3. Then i use MutationObserver. I works perfectly to all pages.

Reference:

https://ta.wikipedia.org/wiki/Special:MyPage/common.js

https://stackoverflow.com/questions/24344022/how-to-use-mutationobserver

https://stackoverflow.com/questions/7707074/creating-dynamic-button-with-click-event-in-javascript

❌
❌