Monday, December 16, 2024

Inversion of control(IOC) and Dependency Injection(DI) in Spring Framework

In this tutorial, we will learn the basic concept of Inversion of control and Dependency Injection.

The core of the spring framework is based on the IOC principle. IOC and DI are closely related concepts. They describe the different aspects of how the spring manages the objects and their interaction. Let's look into each concept.

Inversion of Control(IOC)

IOC is a design principle where the control of object creation, lifecycle and its management is transferred to a spring. Let's see the example of creating two services i.e DatabaseService and UserService

In non-IOC applications, the application code is responsible for creating and managing the DI

DatabaseService dbService = new DatabaseService();
UserService userService = new UserService(dbService);

Here, first, we create the database service object and inject it into user service as a DI resulting in a tight coupling

public class UserService {
    private final DatabaseService dbService;

    public UserService() {
        this.dbService = new DatabaseService(); // Tight coupling
    }
}

With IOC approach

@Component
public class UserService {
    private final DatabaseService dbService;

    @Autowired
    public UserService(DatabaseService dbService) {
        this.dbService = dbService;
    }
}

Here, With IoC, the spring framework itself is responsible for creating and injecting dependencies. Here our application code is not responsible for creating both the object rather spring does. We only provide the metadata @Component and @Autowired to the spring container. UserService doesn't create the DatabaseService but Spring provides it with the help of annotation provided

Dependency Injection(DI)

DI is a design pattern that implements IoC by injecting an object's dependencies at runtime. That simply means it's a mechanism used to achieve IoC. It simply provide the instances of your application classes with all the dependencies they need.

Here are some advantages of using DI

- Loose coupling

DI allows components to be loosely coupled. This makes it easier to modify or replace dependencies without affecting other components.

- Simplify application configuration

DI uses configuration files, such as XML, annotations, or Java-based configuration, to define the dependencies, making it easier to switch configurations without changing the code.

- Improve code maintenance

DI reduces the amount of code to write to wire the components of the application together. As dependencies are managed externally via a Spring's IoC container; it centralizes configuration and makes the application more modular

- Testability

With DI, it's easier to write unit tests for components. Since dependencies can be injected as mock or stub objects.

- Easier Integration with Frameworks and Libraries

Spring's IoC container can manage their dependencies alongside with application's components, enabling cleaner integration and easier management of external resources.

Share:

Thursday, November 14, 2024

How to install oracle database on Ubuntu system with Docker

In this tutorial, we are going to learn how to install the Oracle database on the Ubuntu system.

- Prerequisites

Docker needs to be installed on the system to verify it use the following command

docker --version

This will list the docker version installed

elint@elint:~$ docker --version
Docker version 27.0.2, build 912c1dd

- Download the Oracle docker image

Next, download or clone the oracle docker image from the repo oracle/docker-image Unzip it.

Navigate to the Oracle database docker files; in our case, it's inside /opt/oracle/docker-images/OracleDatabase/SingleInstance/dockerfiles. Here, you can see all the dockerfiles version. Select and navigate the desired version to install

- Download the Oracle database binary file

Download the database zip file from the Oracle website This will require the Oracle login so, create the account login and download the file. Once downloaded copy that file under the Oracle database selected dockerfile version. In our case, we are using docker file version 19.3.0

The overall folder structure looks like below

- Build the Oracle docker image

Note: You need to have at least 8-15Gb storage space on your system

Navigate to the folder

cd /opt/oracle/docker-images/OracleDatabase/SingleInstance/dockerfiles/19.3.0

Using the following command to build

docker build -t oracle/database:19.3.0-ee --build-arg DB_EDITION=ee .

Here oracle/database:19.3.0-ee is the image name, you can give any name

or you can use the following command

../buildContainerImage.sh -v 19.3.0 -e

-v specifies the docker image version and -e for the enterprise edition

Note: this will take some time to build the image

- Run the Oracle container

docker run --name oracle19.3c --network host -p 1521:1521 -p 5500:5500 -v /opt/oracle:/home/oracle oracle/database:19.3.0-ee

This will take some time to complete according to your system's RAM and CPU. Once completed the output looks similar as below

You can close the terminal after this.

- Start the container

To start the container run the below command

docker start oracle19.3c

oracle19.3c is the container name; you can find it using the command: docker ps -a

elint@elint:/opt/oracle/docker-images/OracleDatabase/SingleInstance/dockerfiles/19.3.0$ docker ps -a 
CONTAINER ID   IMAGE                       COMMAND                  CREATED       STATUS                 PORTS     NAMES
767c0a92e087   oracle/database:19.3.0-ee   "/bin/bash -c 'exec …"   11 days ago   Up 11 days (healthy)             oracle19.3c

This process will set the default username and password for the system user to change it, use the command

docker exec oracle19.3c ./setPassword.sh yourPassword

Where oracle19.3c is the container name

Now, login into the container

docker exec -it oracle19.3c bash

To connect to the database use the below command

sqlplus system/yourPassword@orclpdb1

Here orclpdb1 is the default database SID created

If you are having trouble running queries with sqlplus might be due to the export path issue that can resolved by exporting the environment variable. Note: enter into the container first with the command: docker exec -it oracle19.3c bash

export ORACLE_HOME=/opt/oracle/product/19c/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH

Verify the path for sqlplus

bash-4.2$ cd /opt/oracle/product/19c/dbhome_1 
bash-4.2$ ls
OPatch	 addnode     cfgtoollogs  css  data    deinstall    drdaas   has      instantclient  jdbc  ldap  md	  nls	opmn	     ord  owm	 precomp  relnotes     root.sh.old.1  runInstaller   slax      sqlplus	utl
QOpatch  assistants  clone	  ctx  dbjava  demo	    dv	     hs       inventory      jdk   lib	 mgw	  odbc	oraInst.loc  oss  perl	 racg	  root.sh      root.sh.old.2  schagent.conf  sqlj      srvm	wwg
R	 bin	     crs	  cv   dbs     diagnostics  env.ora  install  javavm	     jlib  log	 network  olap	oracore      oui  plsql  rdbms	  root.sh.old  root.sh.old.3  sdk	     sqlpatch  usm	xdk

Now you can create a new sid/database and connect to the users.

With suitable database connector; you can connect the database using the url: jdbc:oracle:thin:@127.0.0.1:1521/orclpdb1

Share:

Wednesday, November 13, 2024

How to remove docker containers and images

In this tutorial, we are going to learn how to remove the docker containers and images

Initially, list all the containers that use the docker images. To see all the running containers on your machine use the following command

docker ps -a

This will show all the running containers on your machine. The sample output looks like as below:

Here, we do have one running container with container ID: 767c0a92e087 and container name: oracle19.3c

Stop a running container

docker stop <container_id>

Use your own container ID in our case it is 767c0a92e087 to stop it

Now, let's delete the container

docker rm <container_id>

To force to remove the running container in one command use the following command

docker rm -f <container_id>

If you want to remove all the containers(not recommended)

docker container prune

Let's look into deleting the docker images

List all the available docker images

docker image ls

The sample output looks like

elint@elint:~$ docker image ls
REPOSITORY        TAG         IMAGE ID       CREATED       SIZE
oracle/database   19.3.0-ee   dd6c130762a3   11 days ago   6.54GB

To delete the specific image

docker rmi <image_id>

Use your own docker image ID in our case it is dd6c130762a3

To remove the docker image forcefully

docker rmi -f <image_id>

To remove unused images. The unused or dangling images are those images which are not associated with docker images

docker image prune

Note: the deleted images need to re-download if we need it later

These are the overall commands to clean up the docker containers and images.

Share:

Tuesday, November 12, 2024

How to install and start Redis server for Ubuntu system

If the Redis server is not installed on the system install it. For the Ubuntu system use the following command

sudo apt-get update
sudo apt-get install redis-server

Once the Redis server is installed, open the terminal and start it using the following command

redis-server

This will start the Redis server. Note: with this redis server will start on default port 6379.

To customize the configuration create a custom file redis.conf add the proper configuration and start the server

redis-server /etc/redis/redis.conf

The above command to run the server will require the terminal to open so to run in the background use the following command

redis-server --daemonize yes

To test whether the Redis is running successfully ping using the Redis cli command

redis-cli ping

This will return the response PONG if it's running successfully

Share:

Monday, August 28, 2023

Caused by java.io.IOException: CreateProcess error=206, The filename or extension is too long

While working on Java gradle project sometimes we might get the following error in Windows system:

Caused by: java.io.IOException: CreateProcess error=206, The filename or extension is too long

This is due to when classpath for a Gradle JavaExec or Test task is long, Windows command executions give an error because of the limitation to command line length greater than 32K

With a number of classpath dependencies in a large project, typically JavaExec Gradle task fails with error "The filename or extension is too long" and this would be a stopping error. To solve this issue, we can use the following gradle plugin. Use the plugin inside build.gradle file

apply plugin: "com.virgo47.ClasspathJar"

Or we can use inside build.gradle file under buildscript {} >> dependencies {} section as below:

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "gradle.plugin.com.virgo47.gradle:ClasspathJar:1.0.0"
  }
}

For Kotlin project, use it inside build.gradle.kts file as below:

apply(plugin = "com.virgo47.ClasspathJar")

Or we can use it in the build.gradle.kts kotlin file under buildscript {} >> dependencies {}

buildscript {
  repositories {
    maven {
      url = uri("https://plugins.gradle.org/m2/")
    }
  }
  dependencies {
    classpath("gradle.plugin.com.virgo47.gradle:ClasspathJar:1.0.0")
  }
}

ClasspathJar plugin creates a classpath jar for jar files in the classpath and sets the classpath with classpath jar. This includes JavaExec, Test and other similar tasks.

Build the application and run it.

Reference: ClasspathJar

Share:

Tuesday, August 23, 2022

How to setup auto renewable free SSL certificate using Lets Encrypt and Nginx on Ubuntu machine

In this tutorial, we are going to set up free SSL auto-renewable Let's Encrypt along with Nginx.

Prerequisites:

Before we start setup, first make sure your domain e.g. example.com is pointed to the server's public IP address. You can set up and point this configuration from the dashboard of your domain service provider.

Connect to the remote server:

First SSH into the remote server where we want to set up the SSL.

If you are using a server password to connect, use the following command

sudo ssh server_username@ip_address

Here use your server username and server IP address to connect. For example ubuntu@34.344.56

If you are using a .pem file or other private keys to connect to a server then use the following command

sudo ssh -i path_to_pem_file server_username@ip_address

Install Nginx:

First, let's install Nginx on the server using the following commands.

sudo apt-get update
sudo apt-get install nginx

If nginx got successfully installed, then use the following command to verify.

nginx -v
nginx version: nginx/1.18.0 (Ubuntu)

Or we can verify by checking the status

sudo systemctl status nginx

Setup Nginx Configuration:

Now let's configure the Nginx for our domain. For this navigate to the Nginx directory

cd /etc/nginx/sites-available

Here, if we use the ls command we can see the default file for configuration. We will create a new file for our domain to configure for e.g 360learntocode.com, you can create using your domain name.

sudo vim 360learntocode.com

Now the new empty file is open lets edit and inserts the configuration by entering Shift + i

server {
      server_name 360learntocode.com;

      location / {
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
        proxy_pass              http://568.19.34.63:8080;
      }
}

Make sure to replace 360learntocode.com with your domain name and http://568.19.34.63:8080 with your IP address and the port in which your application is running.

Now save the configuration. Enter Esc and type :wq and hit Enter.

Now, symlink this file with the directory “sites-available” in our Nginx for this navigate to sites-available

cd /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/360learntocode.com /etc/nginx/sites-enabled/

To check the Nginx configuration use the following command

sudo nginx -t

We are supposed to see the output as below

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Reload the Nginx to reflect the changes:

sudo systemctl reload nginx

If we try to open our domain, we can see the Nginx 502 Bad Gateway if our application is not running otherwise we will see the running application.

Setup SSL Certificate:

For the SSL certificate, we are using the let's encrypt and certbot client. For more detail check let's Encrypt and Certbot

- Install Certbot client

Use the following commands to install certbot client

sudo apt-get update
 sudo apt-get install python3-certbot-nginx

Now, the certbot is successfully installed on our server. Let's create an SSL certificate for our domain

sudo certbot --nginx -d 360learntocode.com

Note: use your own domain name. Follow the steps asked afterward.

Here are some sample examples screens.

Now, let's reload the Nginx so that our configuration changes will reflect.

sudo systemctl reload nginx

If we load our domain URL then it will open over HTTPS.

If you want to see the overall configuration setup, please open the file that we created previously i.e 360learntocode.com inside /etc/nginx/sites-available/, there we can see all the setup done. The sample file looks like as below.

server {
      server_name 360learntocode.com;

      location / {
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
        proxy_pass              http://568.19.34.63:8080;
      }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/360learntocode.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/360learntocode.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = 360learntocode.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


      server_name 360learntocode.com;
    listen 80;
    return 404; # managed by Certbot


}

Here, the auto-renew script is managed by certbot client so we don't have to worry about the SSL expiration. To verify the auto-renew scripts navigate to the script file.

cd /etc/cron.d/
sudo vi certbot

In the certbot file, we can see the auto-renew script as below added by cerbot client

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew

Thanks for following the tutorial, Happy coding !!

Share:

Mail Sending Issue in Java Application

Sometimes while sending the mail in the Java application we might get the following issue.

org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.gmail.com, 465; timeout -1;
  nested exception is:
	java.net.ConnectException: Connection timed out (Connection timed out). Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.gmail.com, 465; timeout -1;
  nested exception is:
	java.net.ConnectException: Connection timed out (Connection timed out)
	at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:432)
	at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:345)
	at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340)
	at org.springframework.mail.javamail.JavaMailSender$send$0.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at grails.plugins.mail.MailMessageBuilder.sendMessage(MailMessageBuilder.groovy:130)
	Caused by: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.gmail.com, 465; timeout -1
Caused by: java.net.ConnectException: Connection timed out (Connection timed out)

This might be due to a different reason.

Due to Firewall setup:

While sending mail we are using ports like 465 or 587 or other ports. So if you enable the firewall rules on your server then we might get this issue. So, enable the firewall rules for those TCP ports for outbound in your firewall settings.

The service provider disabled the port:

For security reasons, some server service providers disable those ports. For e.g:

For this, contact the service provider to allow the port or change the port on your configuration for your application. In the java application, for Gmail smtp.gmail.com we can use 587 instead of 465. The SMTP configuration looks as below:

["mail.smtp.host"           : "smtp.gmail.com",
				 "mail.smtp.starttls.enable": "true",
				 "mail.smtp.auth"           : "true",
				 "mail.smtp.port"           : "587",
		]
Share:

Tuesday, August 16, 2022

Convert Date to Pretty Time in Grails and Groovy

In this tutorial, we will learn how to convert Java Date to pretty time like moments ago, 1 hour ago, 1 week ago, 1 month ago, 1 year ago, and so on in grails application.

For this, we are using the prettytime plugin in our project.

Load PrettyTime in Grails Gradle project:

Add the following inside dependencies in the build.gradle file.

dependencies {
//other dependencies
 
compile 'org.grails.plugins:grails-pretty-time:4.0.0'
}

PrettyTime format Date:

Now let's create a method that formats the Java Date

import org.ocpsoft.prettytime.PrettyTime
import java.util.Date
public static String formatPrettyTime(Date date) {
        PrettyTime p = new PrettyTime()
        return p.format(date).trim()
    }

This will format the given date to a pretty time like moments ago.

Pretty Time Support Locale:

Prettytime supports different languages, for this use request to get the current locale and format it.

public static String formatPrettyTime(Date date, request) {
        Locale locale = RequestContextUtils.getLocale(request)
        PrettyTime prettyTime = new PrettyTime(locale)
        return prettyTime.format(date).trim()
    }

Here, we are using the locale from the request which gives the session locale for the current user

Current locale in grails application can also be achieved using LocaleContextHolder

import org.springframework.context.i18n.LocaleContextHolder
Locale locale = LocaleContextHolder.getLocale()

For pretty time supported language please follow prettyTime

Use in Gsp page:

If we are using the GSP pages HTML as server-side rendering, then we can use pretty time in GSP pages as below

<prettytime:display date="${someDate}" />
Share:

Monday, August 15, 2022

Convert Java Date to Pretty Time in Java

In this tutorial, we will learn how to convert Java Date to pretty time like moments ago, 1 hour ago, 1 week ago, 1 month ago, 1 year ago, and so on.

For this, we are using the prettytime dependency in our project.

If we are using a jar file download the desired jar file from the Maven repository and load the jar file in the application. Please follow How to add external jar or library on IntelliJ IDEA project

Loading PrettyTime in Gradle Project:

Add the following inside dependencies in the build.gradle file.

dependencies {
//other dependencies
 
implementation 'org.ocpsoft.prettytime:prettytime:5.0.3.Final'
}

Loading PrettyTime in Maven Project:

Add the following dependency inside the pom.xml file.

<dependency>
  <groupId>org.ocpsoft.prettytime</groupId>
  <artifactId>prettytime</artifactId>
  <version>5.0.3.Final</version>
  <type>bundle</type>
</dependency>

Pretty Time Format Date:

Now let's create a sample java class PrettyDateTime.java and create a converter method.

import org.ocpsoft.prettytime.PrettyTime;

import java.util.Date;

public class PrettyDateTime {

    public static void main(String[] args) {
        Date dateToConvert = new Date();
        System.out.println(convert(dateToConvert));
    }

    private static String convert(Date date) {
        PrettyTime p = new PrettyTime();
        return p.format(date);
    }
}

Here, we are creating the method convert which will convert the given Java Date to pretty time e.g moments ago.

Pretty Time format LocalDateTime:

import org.ocpsoft.prettytime.PrettyTime;

import java.time.LocalDateTime;

public class PrettyDateTime {

    public static void main(String[] args) {
        System.out.println(convert(LocalDateTime.now().minusSeconds(864000)));
    }

    private static String convert(LocalDateTime date) {
        PrettyTime p = new PrettyTime();
        return p.format(date);
    }
}

Pretty Time format in multiple languages:

Pretty time supports i18n and multiple languages.

import org.ocpsoft.prettytime.PrettyTime;

import java.util.Date;
import java.util.Locale;

public class PrettyDateTime {

    public static void main(String[] args) {
        Date dateToConvert = new Date();
        System.out.println(convert(dateToConvert, new Locale("de")));
    }

    private static String convert(Date date, Locale locale) {
        PrettyTime p = new PrettyTime(locale);
        return p.format(date);
    }
}

Here, we are using german support with "de" locale. For available language support follow prettyTime

Share:

Thursday, August 11, 2022

Java format date string to date and vice versa

This is a quick tutorial on formatting date in the string to java Date and Date to a date in string.

Let's create a sample Java class called DateTimeUtils.java.

Parse Date String to Date:

Let's look into the example that we want to parse the date string 2022-08-22 or 2022-08-22 04:22:100 to Date.

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateTimeUtils {

    public static void main(String[] args) throws ParseException {
        String format = "yyyy-MM-dd HH:mm:ss";
        String dateToFormat = "2022-08-22 04:22:100";
        Date formattedDate = parseDate(dateToFormat, format);
        System.out.println(formattedDate);
    }

    static Date parseDate(String date, String format) throws ParseException {
        if (date.isEmpty()) return null;
        return new SimpleDateFormat(format).parse(date);
    }
}

Here, we are using the SimpleDateFormat java class for parsing the date string to Date. We can provide any valid format as needed instead of yyyy-MM-dd HH:mm:ss For e.g if we want to format "2022-08-22" to Date then we need to use the format "yyyy-MM-dd"

Parse Date to Date in String:

Now let's look into another example where we want to parse the date into the date string. Here we are trying to parse the current date to the desired format like "yyyy-MM-dd HH:mm:ss"

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateTimeUtils {

    public static void main(String[] args) throws ParseException {
        String format = "yyyy-MM-dd HH:mm:ss";
        Date dateToFormat = new Date();
        String formattedDate = formatDate(dateToFormat, format);
        System.out.println(formattedDate);
    }

    static String formatDate(Date date, String format) {
        return new SimpleDateFormat(format).format(date);
    }
}

We are using SimpleDateFormat class to format the desired Date to date in string

The format will be the desired valid format that might be "yyyy-MM-dd" as well.

Share: