Menu

Custom error page in spring boot web application

Spring provide an out-of-the-box "Whitelabel Error Page". When any error occurs in our Spring application this default error page will appear.

Which look like as below:

Spring default error page

How to disable the OOTB or whitelabel error page in Spring?

We can disable the default whitelabel error page, which is OOTB error page of Spring application by setting a property 'server.error.whitelabel.enabled' to false in application.properties property file.

server.error.whitelabel.enabled=false

How to create custom error page in Spring?

Spring provide a functional interface ErrorController to handle the errors. We need to create a controller class by implementing this interface ErrorController to handle the custom error and show different error message and pages to end users.

Since ErrorController is a functional interface, hence this interface contains only one method 'getErrorPath()'. In Spring 2.3.0 this method has been deprecated and since 2.3.0 we may use property 'server.error.path' to specify the error path. 

This(server.error.path) property we can set in our application.properties file.

server.error.path=/error

Now create a CustomErrorHandlerController class which will implement ErrorController interface. In this class we will create a @RequestMapping for path /error and render the request to our custom error page. Below is the sample code, here we have created customErrorPage() method which is mapped with /error path.

CustomErrorHandlerController.java

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CustomErrorHandlerController implements ErrorController{

	@Override
	public String getErrorPath() {
		return null;
	}
	
	@RequestMapping("/error")
    public String customErrorPage() {
        return "views/error";
    }
}

You may wondering why we have use the default method in this class which is returning null. This is because we have to provide the definition of all the method of an interface otherwise it will generate compile time error.

Now create a error.html page under views, which will appear when any error occur in the Spring application. 

error.html

<html>
  <title>Spring custom error page</title> 
 <body>
  <h1>Ooops!!</h1>
  <div>
  <h3>Something unexpected happened</h3>
  <p>If you are seeing this message frequently then, please report us. </p>

  <br />
  </div>
 </body>
</html>

We have done with changes now run the application and validate the error page functionality. Next time when system will generate any error then you will see this custom error page instead of whitelabel error page. You may also render to different error pages based on errors and their definition 

e.g. error code 404 render to 404-error.html page and 

error 400 render to 400-error.html page.

These all we can handle in customErrorPage method. We need to create an object of HttpServletRequest and check the status using if-else condition and return the respective error page. 


Hope this helps you!

References:

https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-customize-the-whitelabel-error-page

https://docs.spring.io/spring-boot/docs/current/api/index.html?org/springframework/boot/web/servlet/error/ErrorController.html 

responsive iframe

When we create an iframe in our site or page, the layout of iframe is always challenging for our site if our site is responsive and device friendly. I faced this issue many time when I try to embed any other site of doc in my blog post.

But then I found a solution for this, which is simple and easy. With the help of few line of simple css code we could make our iframe responsive. Without any delay lets see an example.

I have created an iframe here and embed my blog in this. This is fully responsive you may browse this page on different resolution and size of screen(like mobile, tablet, netbook, and PC). 





Here is the CSS style code snippet which we need to include in head or body section of html code.

<style>
.iframe-container { 
  /* this class will make the div container based on the size of the screen.
     we can adjust the padding-top to give a fixed height to div. 
 */
  position: relative;
  width: 100%;
  overflow: hidden;
  padding-top: 100%; 
}

.responsive-iframe {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  width: 100%;
  height: 100%;
  border: none;
}

Below is the code to create iframe using html iframe tag. In this code you just have to update the src. src (source) attrubute will hold the source url which you want to show in this iframe.



</style>
<!--responsive iframe section -->
<div class="iframe-container"> 
  <iframe class="responsive-iframe" src="https://rashidjorvee.blogspot.com/"></iframe>
</div>


Hope this helps you! Thank You!


package javax.annotation does not exist

Error package javax.annotation does not exist; this means that configured JDK is not working properly or there is some conflict in installed JDK version.

If you are using any IDE tool for development and experienced this error, then go to project build path and check the right JDK is configured in the build path.[Please refer our post How to configure build path and JDK for project]. We may also face this error when we have multiple JDK installed in our machine. So add the correct JDK library for project, then clean the project and build again.

Hope this will help you and fix your issue.

Setup local dispatcher server | AEM as cloud service

In this article we are going to learn how to setup AEM cloud service dispatcher server on local machine.

Prerequisite:

1. Download the docker from Docker official site for our operating system. >> https://www.docker.com/products/docker-desktop and install the docker. Note: We need administrator privileged to run this installer, since this docker installer will change some BIOS settings in operating system.

2. Download latest AEM-SDK from Adobe software distribution libraryhttps://experience.adobe.com/#/downloads/content/software-distribution/en/aemcloud.html


Lets start the local dispatcher setup now:

Step 1: Start docker, make sure our docker is active and running.

Active docker


Step 2: Create a  folder "C:\Users\<user>\aem-sdk\dispatcher". Then extract the file "aem-sdk-dispatcher-tools-<version>-windows.zip" here. This will extract three folders: 

  1. bin
  2. src
  3. docs

Note: These all folder should direct child of dispatcher folder.

Step 3: Open the CLI (cmd) at open directory "C:\Users\<user>\aem-sdk\dispatcher"

Now run the command bin\validator full -d out src
If everything will be good with our setup then following message will get printed on your CLI.
C:\Users\<user_name>\aem-sdk\dispatcher>bin\validator full -d out src
Cloud manager validator 2.0.21
2020/08/07 18:31:20 No issues found
Step 4: Now run the docker to link our AEM publisher instance and tune dispatcher server on a port. Default port for dispatcher is 8080, but we may tune on different port based on availability. To start and link the dispatcher execute the below command.
bin\docker_run out host.docker.internal:4503 8080
Here in above command we just need to change the port numbers as per our configurations, rest all command will be remain same. This command will download the required image from docker server. Below are the entries of successful download on command line interface.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
C:\Users\rashidjorvee\aem-sdk\dispatcher>bin\docker_run out host.docker.internal:4503 8080
Required image not found, trying to load from archive...
d9ff549177a9: Loading layer [==================================================>] 4.671MB/4.671MB 
14c93ed9ebdc: Loading layer [==================================================>] 7.123MB/7.123MB 
cf0d60dcd2e9: Loading layer [==================================================>]  1.848MB/1.848MB 
214f54e148db: Loading layer [==================================================>] 109.1kB/109.1kB 
5931f9345e57: Loading layer [==================================================>]  3.584kB/3.584kB 
5ad19feebed3: Loading layer [==================================================>] 5.12kB/5.12kB 
21a29c76732d: Loading layer [==================================================>]  4.096kB/4.096kB 
860d3c46b038: Loading layer [==================================================>] 3.584kB/3.584kB 
Loaded image: adobe/aem-ethos/dispatcher-publish:2.0.23

Running script /docker_entrypoint.d/10-check-environment.sh
Running script /docker_entrypoint.d/20-create-docroots.sh
Running script /docker_entrypoint.d/30-wait-for-backend.sh
Waiting until host.docker.internal is available
host.docker.internal resolves to 192.168.65.2
Running script /docker_entrypoint.d/40-generate-allowed-clients.sh
Running script /docker_entrypoint.d/50-check-expiration.sh
Running script /docker_entrypoint.d/60-check-loglevel.sh
Running script /docker_entrypoint.d/70-check-forwarded-host-secret.sh
Starting httpd server
[Fri Aug 07 13:12:16.706522 2020] [:notice] [pid 1:tid 140172533533576] ModSecurity for Apache/2.9.2 (http://www.modsecurity.org/) configured.
[Fri Aug 07 13:12:16.706805 2020] [:notice] [pid 1:tid 140172533533576] ModSecurity: APR compiled version="1.6.3"; loaded version="1.6.3"
[Fri Aug 07 13:12:16.706827 2020] [:notice] [pid 1:tid 140172533533576] ModSecurity: PCRE compiled version="8.42 "; loaded version="8.42 2018-03-20"
[Fri Aug 07 13:12:16.706837 2020] [:notice] [pid 1:tid 140172533533576] ModSecurity: LIBXML compiled version="2.9.8"
[Fri Aug 07 13:12:16.706844 2020] [:notice] [pid 1:tid 140172533533576] ModSecurity: Status engine is currently disabled, enable it by set SecStatusEngine to On.
[Fri Aug 07 13:12:16.875893 2020] [mpm_worker:notice] [pid 1:tid 140172533533576] AH00292: Apache/2.4.43 (Unix) Communique/4.3.4-20200624 mod_qos/11.63 configured -- resuming normal operations
[Fri Aug 07 13:12:16.876090 2020] [core:notice] [pid 1:tid 140172533533576] AH00094: Command line: 'httpd -d /etc/httpd -f /etc/httpd/conf/httpd.conf -D FOREGROUND -D ENVIRONMENT_DEV'
172.17.0.1 "localhost:8585" - [07/Aug/2020:13:12:42 +0000] "GET / HTTP/1.1" 302 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
[07/Aug/2020:13:12:42 +0000] "GET /index.html HTTP/1.1" 302 none [publishfarm/0] 24ms "localhost:8585"
172.17.0.1 "localhost:8585" - [07/Aug/2020:13:12:42 +0000] "GET /content.html HTTP/1.1" 404 196 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
[07/Aug/2020:13:12:42 +0000] "GET /content.html HTTP/1.1" - blocked [publishfarm/-] 1ms "localhost:8585"
[07/Aug/2020:13:12:43 +0000] "GET /favicon.ico HTTP/1.1" 404 none [publishfarm/0] 39ms "localhost:8585"
172.17.0.1 "localhost:8585" - [07/Aug/2020:13:12:43 +0000] "GET /favicon.ico HTTP/1.1" 404 235 "http://localhost:8585/content.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
[Fri Aug 07 13:13:28.608851 2020] [mpm_worker:notice] [pid 1:tid 140172533533576] AH00296: caught SIGWINCH, shutting down gracefully
172.17.0.1 "-" - [07/Aug/2020:13:13:34 +0000] "-" 408 - "-" "-"

Step 5: Our dispatcher is now active. We can now browse http://localhost:8080.
Step 6: Now we need to install our customized dispatcher configuration files in our local dispatcher server. To install the dispatcher files run the below mentioned command at same dispatcher directory. 
del -/Q out && bin\validator full -d out <path of the dispatcher source files in your project>

e.g. del -/Q out && bin\validator full -d out E:\aem\aemcloudmanager\aem-cloud-manager-set-up\dispatcher\src


Hope this helps you to understand the setup of dispatcher in local machine. Feel free to share your inputs and issues with us, we will happy to help you. Thank You!

References:


Pause option in AEM replication agent queue

At some point we need to stop the replication from AEM author to publisher for sometime or few minutes, so that no content get published from author to publisher instance. This may we need to handle the maintenance window or stop accepting new content from authors. So question here is how we can do this without disabling the AEM replication queue. 

How to pause the replication agent queue?

Out of the box AEM replication agent queue have an option "pause", using that pause option we could stop the replication. When you will pause the queue then all content which will get published by authors during that time frame will be enlist in the queue but those will not get processed. Pause option will only pause your queue but your replication queue will be still enabled and active.

Active AEM replication queue:

Active AEM replication queue

Paused AEM replication queue:

Paused AEM replication queue


Points to be remember:

  • When we will restart our instance then this paused status will be override and we will find queue is active.
  • By default it will pause for an hour.

Hope this help you to understand the pause option and its role in AEM replication queue.


References:

  1. Troubleshoot AEM replication queue


Babri Masjid - Ram Janam Bhumi judgement file

Supreme court of India finally given the judgement in long running Muslim-Hindu case on Ayodhya disputeted site(Babri Masjid). The complete judgement of supreme court can be read here.


French Revolution - A Turning Point in History

The French Revolution stands as one of the most influential and tumultuous events in history, leaving an indelible mark on the world's political, social, and cultural landscape. Spanning from 1789 to 1799, this epochal movement forever changed the course of French society and inspired revolutionary fervor across the globe. In this blog, we delve into the causes, key events, and far-reaching impact of the French Revolution.

1. The Seeds of Discontent:
The roots of the French Revolution can be traced back to a combination of political, economic, and social factors. A deeply entrenched feudal system, severe financial crises, soaring food prices, and widespread poverty fueled public discontent, while an absolute monarchy and absolute power of the nobility further exacerbated the grievances of the common people.

2. The Storming of the Bastille:
The spark that ignited the revolution occurred on July 14, 1789, with the storming of the Bastille, a symbol of royal oppression. This pivotal event symbolized the overthrow of tyranny and the people's determination to claim their rights and liberty.

3. Declaration of the Rights of Man and of the Citizen:
In August 1789, the National Assembly proclaimed the Declaration of the Rights of Man and of the Citizen. This landmark document asserted the principles of liberty, equality, and fraternity, laying the groundwork for a more just and egalitarian society.

4. The Reign of Terror:
As the revolution progressed, radical factions gained control, and the Reign of Terror ensued from 1793 to 1794. Led by the Committee of Public Safety and Maximilien Robespierre, this dark phase witnessed mass executions of perceived enemies of the revolution, including King Louis XVI and Queen Marie Antoinette.

5. Rise of Napoleon Bonaparte:
Amidst the chaos, Napoleon Bonaparte, a brilliant military strategist, emerged as a prominent figure. He eventually seized power and established himself as the First Consul of France, effectively ending the revolution. Napoleon's rule would leave a lasting impact on European history.

6. Impact on France and Beyond:
The French Revolution's impact transcended national boundaries, influencing political ideologies and inspiring revolutionary movements worldwide. The ideals of liberty, equality, and fraternity reverberated beyond France, sparking calls for independence and democratic reforms in various nations.

7. The Legacy of the French Revolution:
The French Revolution's legacy endures through the foundational principles it championed. Its ideals of human rights, democracy, and the abolition of feudal privileges paved the way for modern constitutional systems and the recognition of individual freedoms.

8. Lessons for Today:
The French Revolution serves as a poignant reminder of the power of the people to challenge oppressive systems and demand change. It also underscores the importance of balance and restraint in times of upheaval, as excessive radicalism can lead to unintended consequences.


The French Revolution stands as an extraordinary chapter in human history, symbolizing the triumph of the human spirit over oppression and the pursuit of liberty, equality, and fraternity. Its far-reaching impact continues to shape the world's political landscape and inspire generations to stand up for their rights and the betterment of society. As we reflect on this monumental event, let us draw lessons from the past to build a more just and equitable world for the future.