<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Curious Technoid</title>
	<atom:link href="https://thecurioustechnoid.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://thecurioustechnoid.com/</link>
	<description>technology made simple</description>
	<lastBuildDate>Fri, 16 Sep 2022 04:29:49 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://thecurioustechnoid.com/wp-content/uploads/2020/06/cropped-fav-1-32x32.png</url>
	<title>The Curious Technoid</title>
	<link>https://thecurioustechnoid.com/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WebSockets using Mojolicious</title>
		<link>https://thecurioustechnoid.com/websockets-using-mojolicious/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=websockets-using-mojolicious</link>
					<comments>https://thecurioustechnoid.com/websockets-using-mojolicious/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Sun, 09 May 2021 06:59:33 +0000</pubDate>
				<category><![CDATA[Perl / Mojolicious]]></category>
		<category><![CDATA[mojolicious]]></category>
		<category><![CDATA[mojolicious web sockets]]></category>
		<category><![CDATA[websockets]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=583</guid>

					<description><![CDATA[<p>Most of the websites you find on the web today are mostly built on the concept of request-response. User clicks a link / button on the webpage, browser sends a request to the server, server sends back the relevant content. This works just fine for most of the websites out there. But imagine a scenario&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/websockets-using-mojolicious/">WebSockets using Mojolicious</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[


<p class="has-drop-cap">Most of the websites you find on the web today are mostly built on the concept of request-response. User clicks a link / button on the webpage, browser sends a request to the server, server sends back the relevant content. This works just fine for most of the websites out there. But imagine a scenario where you are constantly showing stock prices in your website. User(Client) will not request(click on) anything however, the server should keep sending the latest stock prices. To achieve this, traditionally websites relied on techniques like HTTP long polling where in the server holds any request until new content is available and once available, it sends it to the client, client then immediately sends another request which is held by the server until new content is available, this is repeated practically forever or until the session ends. This, as you can see adds severe burden on the server.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/8Dt5bH4mZ0Q"><img decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<p>WebSockets overcomes the above problem by providing full-duplex bidirectional connection between client and server which enables servers to send data to client without the need for client to request for it. Few examples where WebSockets are useful are chat, website displaying stock market prices, website showing game scores etc.</p>



<p>In this article, let us try to implement a simple group chat application to demonstrate WebSockets. We will be using Mojolicious Web Framework here. Mojolicious has WebSockets support by default which makes it quite easy to implement this.</p>



<p>We will keep our chat application simple with the below features:</p>



<ul class="wp-block-list"><li>Users should be able provide their name and connect to the chat application</li><li>Messages sent by any user should be available to everyone connected to the chat application</li><li>Users inactive for 5 mins should be automatically disconnected from the chat application</li></ul>



<h2 class="wp-block-heading">Server-Side Logic</h2>



<p>For the purpose of this demonstration, I will use <em><a href="https://thecurioustechnoid.com/mojolicious-intro-hello-world/" target="_blank" rel="noreferrer noopener">Mojolicious lite app</a></em>. Let us go ahead and create our application using the below command:</p>



<pre class="wp-block-code"><code>mojo generate lite_app simpleChatApp</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img fetchpriority="high" decoding="async" width="638" height="203" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.23.34.png" alt="" class="wp-image-586"/></figure></div>



<p>Let us now write a route to handle any websocket requests. In Mojolicious you use the <em><strong>websocket</strong></em> request to do that. We will also set a timeout of 5mins so that any user not active for more than 5mins gets automatically disconnected. We will store all the connected user information in a hash(%users) so that we can broadcast any new message to everyone.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" width="706" height="217" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.24.42.png" alt="" class="wp-image-591"/><figcaption>Check out the complete source code <a href="https://github.com/curioustechnoid/MojoWebsockets/blob/main/simpleChatApp" target="_blank" rel="noreferrer noopener">here</a></figcaption></figure></div>



<p>Once the user is connected, any new message sent by any user needs to be broadcasted to all the users that are there in the %users hash. We will parse the pipe delimited message received from the user which will have the name and the message(we will add this logic in the HTML template in the next section). We will append the current time and send all the information in JSON format to all the connected users (%users).</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="782" height="467" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-11.00.44.png" alt="" class="wp-image-593" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-11.00.44.png 782w, https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-11.00.44-768x459.png 768w" sizes="auto, (max-width: 782px) 100vw, 782px" /><figcaption>Check out the complete source code <a href="https://github.com/curioustechnoid/MojoWebsockets/blob/main/simpleChatApp" target="_blank" rel="noreferrer noopener">here</a></figcaption></figure></div>



<p>If the users disconnects or time-out occurs, we will remove the user from our hash so that new messages are not sent to them.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="717" height="167" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.25.16.png" alt="" class="wp-image-594"/><figcaption>Check out the complete source code <a href="https://github.com/curioustechnoid/MojoWebsockets/blob/main/simpleChatApp" target="_blank" rel="noreferrer noopener">here</a></figcaption></figure></div>



<h2 class="wp-block-heading">Client-Side Logic</h2>



<p>Now that we have our server side logic in place, time to write client side logic. Javascript has APIs which can be used to connect to server via websockets. We will be using that here.</p>



<p>First, we will have to connect to server via websocket either when the page loads or on some user action. In our case, we will give a button to the user to connect to the server by providing his name; when that button is clicked, we call the below code to connect to the webserver and display a message saying <em>Client Connected</em>. We have HTML elements to display the messages and capture the user inputs. You can check the complete source code <a href="https://github.com/curioustechnoid/MojoWebsockets" target="_blank" rel="noreferrer noopener">here</a>.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="705" height="171" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.26.31.png" alt="" class="wp-image-595"/><figcaption>Check out the complete source code <a href="https://github.com/curioustechnoid/MojoWebsockets/blob/main/simpleChatApp" target="_blank" rel="noreferrer noopener">here</a></figcaption></figure></div>



<p>Once the connection is established, whenever the user sends a new message, we append his name with the message he has typed and send it to the server delimited by pipe(you should ideally be using JSON or something!).</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="883" height="62" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.27.15.png" alt="" class="wp-image-597" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.27.15.png 883w, https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.27.15-768x54.png 768w" sizes="auto, (max-width: 883px) 100vw, 883px" /><figcaption>Check out the complete source code <a href="https://github.com/curioustechnoid/MojoWebsockets/blob/main/simpleChatApp" target="_blank" rel="noreferrer noopener">here</a></figcaption></figure></div>



<p>When anyone sends a message (including the user himself), the message which is broadcasted by the server will be captured, parsed and displayed on the chat window. Chat window is a HTML text area, you can check the source code <a href="https://github.com/curioustechnoid/MojoWebsockets/blob/main/simpleChatApp" target="_blank" rel="noreferrer noopener">here</a>.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1021" height="189" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.26.50.png" alt="" class="wp-image-598" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.26.50.png 1021w, https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.26.50-768x142.png 768w" sizes="auto, (max-width: 1021px) 100vw, 1021px" /><figcaption>Check out the complete source code <a href="https://github.com/curioustechnoid/MojoWebsockets/blob/main/simpleChatApp" target="_blank" rel="noreferrer noopener">here</a></figcaption></figure></div>



<p>In case the user is inactive for 5mins or the server closes the connection, we pop-up a message to the user saying connection is closed:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="883" height="133" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.26.39.png" alt="" class="wp-image-599" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.26.39.png 883w, https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-07.26.39-768x116.png 768w" sizes="auto, (max-width: 883px) 100vw, 883px" /><figcaption>Check out the complete source code <a href="https://github.com/curioustechnoid/MojoWebsockets/blob/main/simpleChatApp" target="_blank" rel="noreferrer noopener">here</a></figcaption></figure></div>



<h2 class="wp-block-heading">Testing</h2>



<p>Would you believe if I told you, this is all you need to build a simple chat program? Well, that&#8217;s Mojolicious for you. Let us fire up the morbo server and check out our chat application.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="534" height="130" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.09.13.png" alt="" class="wp-image-600"/></figure></div>



<p>Let us try accessing our chat program using the url: <code>http://127.0.0.1:3000</code></p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="775" height="379" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.13.27.png" alt="" class="wp-image-601" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.13.27.png 775w, https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.13.27-768x376.png 768w" sizes="auto, (max-width: 775px) 100vw, 775px" /></figure></div>



<p>Give your name and click <em>Connect</em> button to connect to the chat session.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="794" height="405" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.13.49.png" alt="" class="wp-image-603" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.13.49.png 794w, https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.13.49-768x392.png 768w" sizes="auto, (max-width: 794px) 100vw, 794px" /></figure></div>



<p>A welcome message is displayed and it also shows that the user is connected to the server. Now go ahead, enter a message and hit send.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="756" height="389" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.14.17.png" alt="" class="wp-image-604"/></figure></div>



<p>You can see your message in the text area with a time stamp. The message is actually broadcasted by the server to all the connected users. Now let us access this chat program from our phone and send a message.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="769" height="394" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.15.19.png" alt="" class="wp-image-605"/></figure></div>



<p>You can see the messages sent by any user getting broadcasted to all the active users. If a time out occurs or if the server disconnects the connection, all the users will get a pop-up message like this:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="953" height="523" src="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.15.45.png" alt="" class="wp-image-606" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.15.45.png 953w, https://thecurioustechnoid.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-05-at-08.15.45-768x421.png 768w" sizes="auto, (max-width: 953px) 100vw, 953px" /></figure></div>



<p>That&#8217;s about it, we have successfully implemented a simple chat program in Mojolicious using websockets. You can find the complete <a href="https://github.com/curioustechnoid/MojoWebsockets" target="_blank" rel="noreferrer noopener">source code</a> of this program <a href="https://github.com/curioustechnoid/MojoWebsockets" target="_blank" rel="noreferrer noopener">here</a>. Below is the video demonstration of what we discussed in this article, if it interests you. Thank you for reading.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Websockets using Mojolicious" width="640" height="360" src="https://www.youtube.com/embed/8Dt5bH4mZ0Q?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://thecurioustechnoid.com/websockets-using-mojolicious/">WebSockets using Mojolicious</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/websockets-using-mojolicious/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mojolicious Minion &#8211; A High Performance Job Queue</title>
		<link>https://thecurioustechnoid.com/mojolicious-minion-a-high-performance-job-queue/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mojolicious-minion-a-high-performance-job-queue</link>
					<comments>https://thecurioustechnoid.com/mojolicious-minion-a-high-performance-job-queue/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Mon, 26 Apr 2021 14:55:28 +0000</pubDate>
				<category><![CDATA[Perl / Mojolicious]]></category>
		<category><![CDATA[minion]]></category>
		<category><![CDATA[minions]]></category>
		<category><![CDATA[mojolicious]]></category>
		<category><![CDATA[mojolicious minion]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=514</guid>

					<description><![CDATA[<p>Minion is a third party plugin for Mojolicious Web Framework which allows you to process time consuming tasks in the background. They are high performance job queue for Perl programming language and is not limited to just Mojolicious web framework. Minion is a high performance job queue for the Perl programming language, with support for&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-minion-a-high-performance-job-queue/">Mojolicious Minion &#8211; A High Performance Job Queue</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="has-drop-cap">Minion is a third party plugin for Mojolicious Web Framework which allows you to process time consuming tasks in the background. They are high performance job queue for Perl programming language and is not limited to just Mojolicious web framework.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/Icc9YOOF414" target="_blank" rel="noopener"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Minion is a high performance job queue for the Perl programming language, with support for multiple named queues, priorities, high priority fast lane, delayed jobs, job dependencies, job progress, job results, retries with backoff, rate limiting, unique jobs, expiring jobs, statistics, distributed workers, parallel processing, autoscaling, remote control, Mojolicious admin ui, resource leak protection and multiple backends (such as PostgreSQL).</p><cite>mojolicious.org</cite></blockquote>



<p>Minions doesn&#8217;t come pre-installed with Mojolicious installation so it needs to be installed separately.</p>



<pre class="wp-block-code"><code>cpanm Minion</code></pre>



<p>If you use docker, I have built an image which has Mojolicious and Minion together. You can get it here:</p>



<pre class="wp-block-code"><code>docker pull curioustechnoid/mojolicious</code></pre>



<p>Minion uses database backend to store and process the jobs. Most of the popular databases(like SQLite, PostgreSQL) are supported. Jobs can be added to the queue from different programs like Mojolicious, Perl Program, Command Line etc. The Minion worker will be monitoring your backend database and processes the jobs based on priority and availability.</p>



<p>There are 2 important components to Minions:</p>



<ul class="wp-block-list"><li>Minion Worker</li><li>Job Queues</li></ul>



<p>Let us see how we can configure and deploy Minion.</p>



<h2 class="wp-block-heading">Minion Worker</h2>



<p>Minion workers are the silent warriors that keeps monitoring the backend database and processes the jobs that gets added to the queue.</p>



<p>Let us go ahead and create a script to start the Minion worker. I am using Mojolicious lite app to create a worker. You can very well create a worker without using Mojolicious, read more about it <a href="https://docs.mojolicious.org/Minion/Guide#Custom-workers" target="_blank" rel="noreferrer noopener">here</a>. We will also add definition of our jobs inside this script. We will be adding a &#8216;<em>slow-running</em>&#8216; task and a &#8216;<em>high priority&#8217;</em> task to the script as an example. For the purpose of this demo, I am using SQLite as the backend.</p>



<pre class="wp-block-code"><code>#!/usr/bin/env perl
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# minion-worker.pl
#
# AUTHOR:  Curious Technoid
# DATE:  20-Apr-2021
# VERSION:  1.0
# PURPOSE:
#           This mojo app is to initiate the minion worker
#           which will process the jobs in the queue.
#
# USAGE: 
#       ./minion-worker.pl minion worker -m production
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# 
use Mojolicious::Lite -signatures;


# Using sqlite for the queue
plugin Minion =&gt; { SQLite =&gt; 'minionjobqueue.db', };



#
# Dummy Slow Running Task
#
app-&gt;minion-&gt;add_task(slow_task =&gt; sub ($job) {

        my $id = $job-&gt;id;
        $job-&gt;app-&gt;log-&gt;info("Slow Running Task Initiated -&gt; ".$id);
        sleep 20;
        $job-&gt;app-&gt;log-&gt;info("Slow Running Task Completed -&gt; ".$id);
        $job-&gt;finish({message =&gt; "Slow Running Task Completed -&gt; ".$id});
});

#
# Dummy High Priority Task
#
app-&gt;minion-&gt;add_task(high_priority =&gt; sub ($job) {

        my $id = $job-&gt;id;
        $job-&gt;app-&gt;log-&gt;info("High Priority Task Initiated -&gt; ".$id);
        sleep 3;
        $job-&gt;app-&gt;log-&gt;info("High Priority Task Completed -&gt; ".$id);
        $job-&gt;finish({message =&gt; "High Priority Task Completed -&gt; ".$id});
});



app-&gt;start;</code></pre>



<h4 class="wp-block-heading">Start the worker</h4>



<p>Now that our Worker script is ready time to start it. You can manually start the worker by running the one of the below commands in terminal:</p>



<pre class="wp-block-code"><code>./minion-worker.pl minion worker

./minion-worker.pl minion worker -m production

nohup ./minion-worker.pl minion worker -m production &amp;</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="794" height="208" src="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minion-1.png" alt="" class="wp-image-537" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minion-1.png 794w, https://thecurioustechnoid.com/wp-content/uploads/2021/04/minion-1-768x201.png 768w" sizes="auto, (max-width: 794px) 100vw, 794px" /></figure>



<p>In a production environment, I prefer creating it as a systemd service and run it in the background.</p>



<pre class="wp-block-code"><code>&#91;Unit]
Description=Minion Workers for Mojolicious
After=mariadb.service

&#91;Service]
Type=simple
ExecStart=/path/to/your/worker/minion-worker.pl minion worker -m production
ExecReload=/path/to/your/worker/minion-worker.pl minion worker -m production
KillMode=process

&#91;Install]
WantedBy=multi-user.target</code></pre>



<p>Now we have the worker running, ready to process any jobs added to the queue. You can check the status of the jobs in the queue using the command:</p>



<pre class="wp-block-code"><code>./minion-worker.pl minion job</code></pre>



<p>Minion comes with a pre-built Admin console to monitor the jobs that are enqueued and processed. It can be enabled using the plugin:</p>



<pre class="wp-block-code"><code>plugin 'Minion::Admin';</code></pre>



<p>We will see it&#8217;s usage when we build our Mojolicious app for adding jobs to the queue.</p>



<p>Next task would be create means to enqueue the job queue.</p>



<h2 class="wp-block-heading">Job Queue</h2>



<p>There are many ways to add jobs to the job queue, we will look at the below 3 ways:</p>



<ul class="wp-block-list"><li>Mojolicious App</li><li>Perl Script</li><li>Command Line</li></ul>



<h4 class="wp-block-heading">Mojolicious App</h4>



<p>One of the best use cases of using Minions is to call it from Mojolicious Web App to do time consuming or CPU intensive task in the background. We will create a Mojolicious App which will do the below things:</p>



<ol class="wp-block-list"><li>Add new jobs to the Queue</li><li>Enable Minion Admin Console to monitor the job queue</li></ol>



<p>Without further adieu let us quickly create a new Mojolicious app to begin with:</p>



<pre class="wp-block-code"><code>mojo generate app mojominion</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="794" height="658" src="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionmojoGenerate-1.png" alt="" class="wp-image-549" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionmojoGenerate-1.png 794w, https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionmojoGenerate-1-768x636.png 768w" sizes="auto, (max-width: 794px) 100vw, 794px" /></figure></div>



<p>In our main library created by the <em>mojo</em> command, we will first add the logic to call the Minion plugin.</p>



<p><code>File: mojominion/lib/mojominion.pm</code></p>



<pre class="wp-block-code"><code>$self-&gt;plugin(Minion =&gt; { SQLite =&gt; 'minionjobqueue.db'});</code></pre>



<p>We will keep it simple and only add routes to:</p>



<ol class="wp-block-list"><li>Add new jobs to the queue</li><li>Navigate to Minion Admin Console</li></ol>



<p>We will not think much about security as of this moment. This is just to show you how to add jobs to the queue, so right now anybody can add jobs to the queue.</p>



<pre class="wp-block-code"><code>  $r-&gt;get('/addjob/slow')-&gt;to(controller =&gt; 'Example', action =&gt; 'addSlowJob');  # Route to add slow job
  $r-&gt;get('/addjob/high')-&gt;to(controller =&gt; 'Example', action =&gt; 'addHighJob');  # Route to add high priority job
  $self-&gt;plugin('Minion::Admin' =&gt; {route =&gt; $r-&gt;any('/admin')});  # Route to navigate to Minion Admin Console</code></pre>



<p>You can find the complete source code <a href="https://github.com/curioustechnoid/Minion" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>Let us now add the logic in our default controller to push the job to the queue.</p>



<p><code>File: mojominion/lib/mojominion/Controller/Example.pm</code></p>



<p>Add the below 2 procedures in the controller:</p>



<pre class="wp-block-code"><code># Subroutine to add slow jobs
sub addSlowJob ($self) {

   my $jobid = $self-&gt;minion-&gt;enqueue(slow_task =&gt; &#91;]);

  $self-&gt;render(text =&gt; 'Your Slow Task is Added to the queue, Job ID: '.$jobid.'. &lt;a href="/admin"&gt;Click here&lt;/a&gt; to view the status.');
}



# Subroutine to add high priority jobs
sub addHighJob ($self) {

   # 
   # By default priority is set to 0, anything more than that gets priority.
   # You can have values between -100 to 100
   #
   my $jobid = $self-&gt;minion-&gt;enqueue(high_priority =&gt; &#91;] =&gt; {priority =&gt; 10});
   # my $jobid = $self-&gt;minion-&gt;enqueue(slow_task =&gt; &#91;]); #Another way of adding the task to the job queue

   $self-&gt;render(text =&gt; 'Your Task is Added to the high priority lane, Job ID: '.$jobid.'. &lt;a href="/admin"&gt;Click here&lt;/a&gt; to view the status.');

}</code></pre>



<p>Task given high priority will get picked up first once the worker becomes free. You can see this first hand in a video demo that I created in <a href="https://www.youtube.com/watch?v=Icc9YOOF414" target="_blank" rel="noreferrer noopener">youtube</a>.</p>



<p>You can find the complete source code of the above codes <a href="https://github.com/curioustechnoid/Minion" target="_blank" rel="noreferrer noopener">here</a>.</p>



<h5 class="wp-block-heading">Time to Test</h5>



<p>We created the worker, started it and then created a Mojolicious App that can handle job requests. Let us fire it up and see if it works.</p>



<pre class="wp-block-code"><code>morbo mojominion/script/mojominion</code></pre>



<p>Let us first access the admin console to see if that is accessible:</p>



<p><code>http://127.0.0.1:3000/admin</code></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1400" height="958" src="https://thecurioustechnoid.com/wp-content/uploads/2021/04/miniondashboard1.png" alt="" class="wp-image-539" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/04/miniondashboard1.png 1400w, https://thecurioustechnoid.com/wp-content/uploads/2021/04/miniondashboard1-768x526.png 768w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></figure>



<p>Admin console is working fine and we can see that we have 1 worker running. Time for us add some jobs by using the below URLs (keep the admin console open):</p>



<p><code>http://127.0.0.1:3000/addjob/slow</code><br><code>http://127.0.0.1:3000/addjob/high</code></p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="569" height="217" src="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionslowtask-1.png" alt="" class="wp-image-546"/></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="574" height="212" src="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionhightask.png" alt="" class="wp-image-541"/></figure></div>



<p>Open the URL multiple times to add more jobs. If we head back to our admin console we can see our job getting executed.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1402" height="955" src="https://thecurioustechnoid.com/wp-content/uploads/2021/04/miniondashboard2.png" alt="" class="wp-image-542" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/04/miniondashboard2.png 1402w, https://thecurioustechnoid.com/wp-content/uploads/2021/04/miniondashboard2-768x523.png 768w" sizes="auto, (max-width: 1402px) 100vw, 1402px" /></figure>



<p>Just like that we have successfully implemented Minions using Mojolicious.</p>



<h4 class="wp-block-heading">Perl Script</h4>



<p>Can we use Minions without Mojolicious ? Most definitely. We will keep the above Mojolicious app running to access the admin console and then try to add a job using the below plain Perl script:</p>



<pre class="wp-block-code"><code>#!/usr/bin/env perl
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# add-minion-job.pl
#
# AUTHOR:  Curious Technoid
# DATE:  20-Apr-2021
# VERSION:  1.0
# PURPOSE:
#           This perl script is used to add a new job to
#           minion queue.
#
# USAGE: 
#       ./add-minion-job.pl slow
#       ./add-minion-job.pl fast
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# 
use Minion;


# Do you notice we are using the same database
my $minion = Minion-&gt;new( SQLite =&gt; 'minionjobqueue.db');


# Getting the parameter
my $param = shift;


if(lc $param eq 'slow'){

    # Add slow task to the queue
    my $jobid = $minion-&gt;enqueue(slow_task =&gt; &#91;]);

    print("Your Slow Task is Added to the queue from perl, Job ID: $jobid\n\n");

}elsif(lc $param eq 'fast'){

    # Add high priority task to the queue
    my $jobid = $minion-&gt;enqueue(high_priority =&gt; &#91;] =&gt; {priority =&gt; 10});

    print("Your High Priority Task is Added to the queue from perl, Job ID: $jobid\n\n");
");

}else{

    die("Incorrect parameter\n");
}</code></pre>



<p>Once the script is ready, run it using the below command to add jobs:</p>



<pre class="wp-block-code"><code>./add-minion-job.pl slow
./add-minion-job.pl fast</code></pre>



<p>Now if you head back to the Admin console that is running from our previous example, you can notice that the new jobs added by the Perl script is queued and executed. If you don&#8217;t want to use the Mojolicious Admin console at all, you can always use the command line to check the jobs:</p>



<pre class="wp-block-code"><code>./minion-worker.pl minion job</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="799" height="309" src="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionjob.png" alt="" class="wp-image-543" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionjob.png 799w, https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionjob-768x297.png 768w" sizes="auto, (max-width: 799px) 100vw, 799px" /></figure>



<h4 class="wp-block-heading">Command Line</h4>



<p>We can even add jobs to the queue from command line directly. One way is ofcourse to use the pure Perl script above and use that to add jobs from command line. Not only that, you can also add jobs using the worker script(minion-worker.pl) we wrote in the beginning. Below command adds jobs to the queue directly from command line:</p>



<pre class="wp-block-code"><code>./minion-worker.pl minion job -e slow_task</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="795" height="266" src="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionCLI.png" alt="" class="wp-image-545" srcset="https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionCLI.png 795w, https://thecurioustechnoid.com/wp-content/uploads/2021/04/minionCLI-768x257.png 768w" sizes="auto, (max-width: 795px) 100vw, 795px" /></figure>



<p>You can pass arguments like this:</p>



<pre class="wp-block-code"><code>./minion-worker.pl minion job -e slow_task -a '&#91;"param1","param2"]'</code></pre>



<p>This is very useful if you want to schedule jobs using cron.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<p>That&#8217;s about it. We have configured, deployed and tested Mojolicious Minions in this article. If you wish to check out the hands on demonstration about the things we discussed in this blog, check out my video in youtube below.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Mojolicious Minion - High Performance Job Queue" width="640" height="360" src="https://www.youtube.com/embed/Icc9YOOF414?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>You can read more about Minion documentation in the <a href="https://docs.mojolicious.org/Minion" target="_blank" rel="noreferrer noopener">official page here</a>. </p>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-minion-a-high-performance-job-queue/">Mojolicious Minion &#8211; A High Performance Job Queue</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/mojolicious-minion-a-high-performance-job-queue/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mojolicious (Part 4): Database Management</title>
		<link>https://thecurioustechnoid.com/mojolicious-part-4-database-management/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mojolicious-part-4-database-management</link>
					<comments>https://thecurioustechnoid.com/mojolicious-part-4-database-management/#comments</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Wed, 15 Jul 2020 02:00:00 +0000</pubDate>
				<category><![CDATA[Perl / Mojolicious]]></category>
		<category><![CDATA[mojolicious]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[web framework]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=459</guid>

					<description><![CDATA[<p>We have reached the last part of Mojolicious series. We have so far built a new project with Mojolicious full_app, created a home page for our website, then we looked at layouts &#38; templates, and finally ended our last article with session management. In this session we will cover database management, which is one of&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-part-4-database-management/">Mojolicious (Part 4): Database Management</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="has-drop-cap">We have reached the last part of Mojolicious series. We have so far built a new project with Mojolicious <em>full_app</em>, created a <a aria-label="undefined (opens in a new tab)" href="/mojolicious-part1-homepage/" target="_blank" rel="noreferrer noopener">home page</a> for our website, then we looked at <a aria-label="undefined (opens in a new tab)" href="/mojolicious-part2-layouts-templates/" target="_blank" rel="noreferrer noopener">layouts &amp; templates</a>, and finally ended our last article with <a aria-label="undefined (opens in a new tab)" href="/mojolicious-part-3-session-management/" target="_blank" rel="noreferrer noopener">session management</a>. In this session we will cover database management, which is one of the important functionalities when building a website.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/Y_vg0hdS3YM" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<p>The main functionality of our test case website that we are working on from <a href="/mojolicious-part1-homepage/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">part 1</a> of Mojolicious series is for registered users to be able to publish their testimonials in the website. To achieve that, we need to follow the below steps:</p>



<ul class="wp-block-list"><li>Create Database Components</li><li>Create Testimonials Page Template</li><li>Database Connectivity Logic</li><li>Verification</li><li>Deploy to Production</li></ul>



<h2 class="wp-block-heading">Create Database Components</h2>



<p>The testimonials entered by the users needs to be stored in the database so that all the testimonials entered by all the users is visible to everyone. We will use <em>MariaDB</em> database to store our testimonial table. First, we will create a <em>MariaDB</em> database called <code>tct_mojo_db</code> by logging in as root user:</p>



<pre class="wp-block-code"><code>mysql -u root -p</code></pre>



<pre class="wp-block-code"><code>CREATE database tct_mojo_db;</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="883" height="517" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-create-db.jpg" alt="" class="wp-image-464" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-create-db.jpg 883w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-create-db-768x450.jpg 768w" sizes="auto, (max-width: 883px) 100vw, 883px" /></figure></div>



<p>Then we will create a database user called <strong>demo</strong> and give it all the privileges to the database <code>tct_mojo_db</code></p>



<pre class="wp-block-code"><code>CREATE USER 'demo'@'localhost' IDENTIFIED BY 'welcome123';

GRANT ALL PRIVILEGES ON tct_mojo_db.* TO 'demo'@'localhost';</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="882" height="248" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-create-user.png" alt="" class="wp-image-466" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-create-user.png 882w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-create-user-768x216.png 768w" sizes="auto, (max-width: 882px) 100vw, 882px" /></figure></div>



<p>Finally we login as the new user(<strong>demo</strong>) and create the table <code>tct_mojo_testimonials</code> in our new database <code>tct_mojo_db</code></p>



<pre class="wp-block-code"><code>mysql -u demo -p</code></pre>



<pre class="wp-block-code"><code>use tct_mojo_db;

CREATE TABLE IF NOT EXISTS tct_mojo_testimonials (
id             INT(20)         NOT NULL AUTO_INCREMENT,
published_by   VARCHAR(560)    NOT NULL,
published_on   TIMESTAMP       NOT NULL DEFAULT CURRENT_TIMESTAMP,
testimonial    VARCHAR(32000)  NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="927" height="414" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-create-table.jpg" alt="" class="wp-image-467" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-create-table.jpg 927w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-create-table-768x343.jpg 768w" sizes="auto, (max-width: 927px) 100vw, 927px" /></figure></div>



<p>We will store the testimonials published by the users in the above database table. We have all the database related components in place for your project.</p>



<h2 class="wp-block-heading">Create Testimonials Page Template</h2>



<p>We need a new page template where users can publish their testimonials and view the testimonials of others. We will have a single page which does both. The first section of the page will be a html form which registered users can use to provide their testimonials and we will have a section below which will have all the testimonials given by everyone.</p>



<p>Let us go ahead and create a new template called: <code>managetestimonials.html.ep</code> in our templates folder: <code>myWebSite/templates/myTemplates/</code> with the below content:</p>



<pre class="wp-block-code"><code>% layout 'master';
% title 'View Testimonials';
&lt;a href="/"&gt;Home&lt;/a&gt;&amp;nbsp;&amp;nbsp;
&lt;a href="/logout"&gt;Log Out&lt;/a&gt;

&lt;h1&gt;&lt;%= $msg %&gt;&lt;/h1&gt;

&lt;center&gt;
&lt;form action="/testimonials" method="post"&gt;

    &lt;textarea id="userReview" name="userReview" rows="8" cols="50"&gt;Please enter your testimonial here&lt;/textarea&gt;&lt;/br&gt;
    &lt;input type="reset" value="Clear" /&gt;
    &lt;input type="submit" value="Publish"&gt;

&lt;/form&gt;
&lt;/center&gt;

&lt;table width=100% align=center border=1 cellspacing=0 cellpadding=0&gt;
  &lt;tr&gt;
    &lt;th&gt;Testimonials&lt;/th&gt;
  &lt;/tr&gt;

  &lt;%== $alltestimonials %&gt;

&lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>



<p>We are referring to a perl variable <code>$alltestimonials</code> in the template code, this will have the existing testimonials from database in HTML format. We will set this value in our controller after getting them from database.</p>



<h2 class="wp-block-heading">Database Connectivity Logic</h2>



<p>Now that we have the new page template ready, time for us to add the logic to handle database operations. In order to achieve that we need to make the following changes to our project:</p>



<ul class="wp-block-list"><li>Update DB credentials in myWebSite.conf file</li><li>Add DB handler and logic to handle new route</li><li>Create DB Modeller for database operations</li><li>Change Controller logic to handle DB operations</li></ul>



<h5 class="wp-block-heading">myWebSite.conf</h5>



<p>We need to update our conf file to include database credentials. We will add the database connectivity in the below format:</p>



<pre class="wp-block-code"><code>mysql =&gt; 'mysql://dbusername:dbpassword@localhost/databasename'</code></pre>



<p>So our updated <code>myWebSite.conf</code> file will look like this:</p>



<pre class="wp-block-code"><code>{
  secrets =&gt; &#91;'8c285c2b2f9ce11c46ee322d52179ac32be6d42a'],
  mysql =&gt; 'mysql://demo:welcome123@localhost/tct_mojo_db'
}</code></pre>



<h5 class="wp-block-heading">DB Handler</h5>



<p>We have DB connections in place. Now let us create a helper in our main library(<em>myWebSite.pm</em>) which will be used as a handle to our database. This can be used my our modeller and controller to access the database.</p>



<p>Database helpers can be created using the below statement:</p>



<pre class="wp-block-code"><code># Invoking Database handle 
$self-&gt;helper(mysql =&gt; 
sub { state $mysql = Mojo::mysql-&gt;new(shift-&gt;config('mysql')) });

$self-&gt;helper(dbhandle =&gt; 
sub { state $vikidb = myWebSite::Model::Database-&gt;new(mysql =&gt; shift-&gt;mysql) });</code></pre>



<p>We will also add the below routes to handle the new testimonial page action using :</p>



<pre class="wp-block-code"><code>$authorized-&gt;get('/testimonials')-&gt;to('CustomController#loadTestimonials');
$authorized-&gt;post('/testimonials')-&gt;to('CustomController#saveTestimonial');</code></pre>



<p>If you remember from our previous session, the <code>$authorized</code> handle helps us in making sure that only logged in users can access the above calls since these statements are called after the <em><strong>under</strong></em> statement.</p>



<p>Do not forget to import the module <code>use Mojo::mysql;</code> in your main library. If <code>Mojo::mysql</code> is not installed, go ahead and install the perl module.</p>



<p>We will also import our database modeller in our main library: <code>use myWebSite::Model::Database;</code>. This does not exist yet, we will be creating this modeller in the next section.</p>



<p>Once all the change are done, your main library file <code>myWebSite.pm</code> should look something like <a href="/wp-content/uploads/misc/myWebSite_part4.txt" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">this</a>.</p>



<h5 class="wp-block-heading">DB Modeller</h5>



<p>Next we will be creating a database modeller which will have the logic to query the testimonial data and insert any newly published testimonial. We will create the modeller inside our <code>lib</code> directory using the command:</p>



<pre class="wp-block-code"><code>mkdir lib/myWebSite/Model

touch lib/myWebSite/Model/Database.pm</code></pre>



<p>Let us now open the database modeller file and add the below content:</p>



<pre class="wp-block-code"><code>package myWebSite::Model::Database;
use Mojo::Base -base;

has 'mysql';

# Subroutine to get all the testimonials
sub fetch_all_testimonials{ shift-&gt;mysql-&gt;db-&gt;query('select * from tct_mojo_testimonials order by published_on desc')-&gt;hashes-&gt;to_array }

# Subroutine to insert the new testimonial to database
sub publish_testimonial{


   my ($self, $new_testimonial, $username) = @_;
   my $sql = 'insert into tct_mojo_testimonials(published_by,testimonial) values (?,?)';


   $self-&gt;mysql-&gt;db-&gt;query($sql, $username, $new_testimonial);

}


1;</code></pre>



<p>We have 2 subroutine in our modeller, <code>fetch_all_testimonials</code> will fetch all the testimonials into an array of hashes and the second subroutine <code>publish_testimonial</code> inserts the newly published testimonials to the database. These are the only 2 database operation we require for your website.</p>



<h5 class="wp-block-heading">Controller CustomController.pm Changes</h5>



<p>We have our modeller in place that handles the DB operations, let us go ahead and add subroutines in our controller which calls these.</p>



<p>In the above section, we had added 2 new subroutine calls to our controller in the main library file: <code>myWebSite.pm</code>. Let us add the logic to those 2 subroutines in our existing controller: <code>lib/myWebSite/Controller/CustomController.pm</code></p>



<p><em><strong>loadTestimonials</strong></em> basically generates a HTML data of all the testimonials that are there in the database. The generated HTML data is passed as parameter to the template where it is rendered. It uses the <code>fetch_all_testimonials</code> subroutine from the DB modeller that we created above. In the section <em>Create Testimonials Page Template</em> above we had used the variable <code>$alltestimonials</code> to display the data, the value for it is being set in the below subroutine.</p>



<pre class="wp-block-code"><code>sub loadTestimonials{

    my $self = shift;
    my $all_testimonials_html;

    foreach my $all_testimonials (@{$self-&gt;dbhandle-&gt;fetch_all_testimonials})
    {
        $all_testimonials_html .= "
  &lt;tr&gt;
      &lt;td&gt;
          ".$all_testimonials-&gt;{testimonial}."&lt;/br&gt;&lt;/br&gt;
          &lt;div style='text-align: right;'&gt;&lt;i&gt;".$all_testimonials-&gt;{published_by}."&lt;/br&gt;".$all_testimonials-&gt;{published_on}."&lt;/i&gt;&lt;/div&gt;
     &lt;/td&gt;
  &lt;/tr&gt;";
    }
    $self-&gt;render(template =&gt; 'myTemplates/managetestimonials',msg =&gt; 'View Testimonials',alltestimonials =&gt; $all_testimonials_html);


}</code></pre>



<p><em><strong>saveTestimonial</strong></em> basically saves the newly created testimonial added by the registered users. It uses the <code>publish_testimonial</code> subroutine from the DB modeller that we created above.</p>



<pre class="wp-block-code"><code>sub saveTestimonial{

    my $self = shift;
    my $new_testimonial = $self-&gt;param('userReview');
    my $user = $self-&gt;session('username');

    $self-&gt;dbhandle-&gt;publish_testimonial($new_testimonial,$user);
    &amp;loadTestimonials($self);
}</code></pre>



<p>Once all the above changes are done, our CustomController.pm controller will look like <a href="/wp-content/uploads/misc/CustomController_part4.txt" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">this</a>.</p>



<h2 class="wp-block-heading">Verification</h2>



<p>That&#8217;s about it, we have everything we need to start our web application. Let us start our web application using <code>morbo</code> webserver:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="772" height="321" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1.jpg" alt="" class="wp-image-362" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1.jpg 772w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1-768x319.jpg 768w" sizes="auto, (max-width: 772px) 100vw, 772px" /></figure></div>



<p>I have <a href="/ssh-tunneling/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">SSH Tunnel</a> enabled, so let me access our website using localhost IP and port 3000.</p>



<p>Once we login and navigate to Testimonials page, it should look like this:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1044" height="539" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-new-testimonial-page.png" alt="" class="wp-image-469" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-new-testimonial-page.png 1044w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-new-testimonial-page-768x397.png 768w" sizes="auto, (max-width: 1044px) 100vw, 1044px" /></figure></div>



<p>If we add any new testimonial, we can see it getting added in the table below:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1060" height="513" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-new-testimonial-page-add-1.png" alt="" class="wp-image-471" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-new-testimonial-page-add-1.png 1060w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-new-testimonial-page-add-1-768x372.png 768w" sizes="auto, (max-width: 1060px) 100vw, 1060px" /></figure></div>



<p>We have successfully handled database connection in our website.</p>



<h2 class="wp-block-heading">Deploy to Production</h2>



<p>Now that we have a fully operational website with all the requirements met and tested, we can deploy our changes in production and start it to be available for everyone. To do that, as explained in the <a aria-label="undefined (opens in a new tab)" href="/mojolicious-intro-hello-world/" target="_blank" rel="noreferrer noopener">Mojolicious Introduction</a> article, we will use the production webserver <code>hypnotoad</code>.</p>



<ol class="wp-block-list"><li>Let&#8217;s tell <code>hypnotoad</code> to run on port 80. To do that, we will update the <code>myWebSite/myWebSite.conf</code> file to look like this: </li></ol>



<pre class="wp-block-code"><code>{
     secrets =&gt; &#91;'8c285c2b2f9ce11c46ee322d52179ac32be6d42a'],
     mysql =&gt; 'mysql://demo:welcome123@localhost/tct_mojo_db',
     hypnotoad =&gt; {
          listen =&gt; &#91;'http://*:80'],
          workers =&gt; 10
     }
}</code></pre>



<p>We have also told <code>hypnotoad</code> to run 10 workers.</p>



<ol class="wp-block-list" start="2"><li>Next we will open firewall ports 80 so that the website is accessible to everyone. I run Mojolicious on Fedora and use <strong><em>firewalld</em></strong>, I will run the below command to open the ports: </li></ol>



<pre class="wp-block-code"><code>firewall-cmd --zone=public --permanent --add-port 80/tcp
firewall-cmd --reload</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1029" height="285" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-firewall.png" alt="" class="wp-image-472" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-firewall.png 1029w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-firewall-768x213.png 768w" sizes="auto, (max-width: 1029px) 100vw, 1029px" /></figure></div>



<ol start="3"><li>Start the web application using <code>hypnotoad</code> by using the command: </li></ol>



<pre class="wp-block-code"><code>hypnotoad myWebSite/script/myWebSite</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="858" height="183" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-final-hypno-start.png" alt="" class="wp-image-476" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-final-hypno-start.png 858w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-final-hypno-start-768x164.png 768w" sizes="auto, (max-width: 858px) 100vw, 858px" /></figure></div>



<ol start="4"><li>Finally verify by accessing the website using your server IP (or domain name if you have one mapped):</li></ol>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1207" height="891" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-final-hypno-1.png" alt="" class="wp-image-474" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-final-hypno-1.png 1207w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo4-final-hypno-1-768x567.png 768w" sizes="auto, (max-width: 1207px) 100vw, 1207px" /></figure></div>



<p class="has-small-font-size"><em><span style="color:#313131" class="tadv-color">Note: I recommend to use Apache Reverse Proxy along with hypnotoad for production deployments.</span></em></p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>With that the Mojolicious tutorial comes to an end. We have successfully created a fully operational website covering major features of any website and made it available to general public. Hope the Mojolicious <a aria-label="undefined (opens in a new tab)" href="https://thecurioustechnoid.com/tag/mojolicious/" target="_blank" rel="noreferrer noopener">tutorial series</a> were informative and helpful. Do let me know your thoughts and comments in the comment section below. You can find the entire <a href="https://github.com/curioustechnoid/IntroductionToMojolicious" target="_blank" rel="noreferrer noopener">source code</a> of the testimonials project <a href="https://github.com/curioustechnoid/IntroductionToMojolicious" target="_blank" rel="noreferrer noopener">here</a>. You can watch the entire Mojolicious series that we discussed in this blog series in my <a aria-label="undefined (opens in a new tab)" href="https://www.youtube.com/playlist?list=PLf0DTZRjrjle9aL1LMsUtMr_ExVLeGJAH" target="_blank" rel="noreferrer noopener">youtube channel</a>. Keep visiting this blog for more technical tutorials.</p>



<figure class="wp-block-embed aligncenter is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Mojolicious (Part 4): Database Management" width="640" height="360" src="https://www.youtube.com/embed/Y_vg0hdS3YM?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">Edits:</h4>



<p><strong>[13-May-2021] </strong>It so happened that I missed to mention about changing the <code>homepage.html.ep</code> file to point to the new testimonial route(/testimonials) that we created in the main library(<em>myWebSite.pm</em>). You just need to change the <em>href</em> tag in the homepage template to point to the new route and you should be good to go.</p>



<pre class="wp-block-code"><code>% layout 'master';
% title 'Home Page';
    &lt;a href="/logout">Log Out&lt;/a>
      &lt;h1>&lt;%= $msg %>&lt;/h1>
      &lt;h5 class="w3-padding-32">This is my personal site built with Mojolicious. You can provide testimonials using the link &lt;a href="<span style="font-size: inherit; background-color: inherit;"><mark>/testimonials</mark></span>">here&lt;/a>. 
&lt;/h5></code></pre>



<p>Thanks to Jim for pointing this out.</p>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-part-4-database-management/">Mojolicious (Part 4): Database Management</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/mojolicious-part-4-database-management/feed/</wfw:commentRss>
			<slash:comments>23</slash:comments>
		
		
			</item>
		<item>
		<title>Mojolicious (Part 3): Session Management</title>
		<link>https://thecurioustechnoid.com/mojolicious-part-3-session-management/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mojolicious-part-3-session-management</link>
					<comments>https://thecurioustechnoid.com/mojolicious-part-3-session-management/#comments</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Sun, 05 Jul 2020 13:04:46 +0000</pubDate>
				<category><![CDATA[Perl / Mojolicious]]></category>
		<category><![CDATA[mojolicious]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[web framework]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=431</guid>

					<description><![CDATA[<p>In the previous article we made our home page beautiful by adding a HTML template using the concept of Templates and Layouts. Let us now see how we can restrict access to our website to only registered users. We will achieve this by authenticating known users and using session cookies after successful login. We will&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-part-3-session-management/">Mojolicious (Part 3): Session Management</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In the <a aria-label="undefined (opens in a new tab)" href="/mojolicious-part2-layouts-templates/" target="_blank" rel="noreferrer noopener">previous article</a> we made our home page beautiful by adding a HTML template using the concept of <em><strong>Templates and Layouts</strong></em>. Let us now see how we can restrict access to our website to only registered users. We will achieve this by authenticating known users and using session cookies after successful login. We will break this task into the below steps and conquer it one by one:</p>



<ul class="wp-block-list"><li>Create Login and Logout Pages</li><li>Authentication and Session Management Logic</li><li>Verification</li></ul>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/SnGxyxe41fc" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<p>Before we proceed further, let us all remind ourselves how our Mojolicious website looks as of now:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1546" height="894" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-homepage-new-template.png" alt="" class="wp-image-379" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-homepage-new-template.png 1546w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-homepage-new-template-768x444.png 768w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-homepage-new-template-1536x888.png 1536w" sizes="auto, (max-width: 1546px) 100vw, 1546px" /></figure></div>



<p>and this is our project file structure:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="676" height="817" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo3-tree.jpg" alt="" class="wp-image-432"/></figure>



<h2 class="wp-block-heading">Create Login and Logout Pages</h2>



<p>Instead of the home page, we will redirect the users to the login page whenever they access our website. If they provide the correct username / password, we will create session cookies and re-direct them to the home page. Once they are done browsing our website, they can click the <em>Logout</em> link (which we will add to our homepage). This will remove the session cookies and safely logout.</p>



<p>We have already created a <em>master</em> <em><strong>layout</strong></em> in our <a href="/mojolicious-part2-layouts-templates/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">previous session</a> which is the skeleton of our website. This makes us not worry about the look and feel of the website as it is already taken care of. We just need to create template files for login and logout pages which will call our already created <em>master</em> <strong><em>layout</em></strong>.</p>



<h4 class="wp-block-heading">Login Page</h4>



<p>Let us create a new template called<em> login.html.ep</em> inside the template folder of our project: <em>myWebSite/templates/myTemplates</em>. We will add the below code to it:</p>



<pre class="wp-block-code"><code>% layout 'master';
% title 'Login Page';

&lt;center&gt;
&lt;h1&gt;Please Login to Access the Website&lt;/h1&gt;

&lt;h6&gt;
&lt;!-- Logic to display errors if any --&gt;
&lt;font color=red&gt;
&lt;% if($error_message){ %&gt;
&lt;%= $error_message %&gt;
&lt;% } %&gt;
&lt;/font&gt;
&lt;/h6&gt;

&lt;form action="/login" method="post"&gt;

    &lt;b&gt;UserName&lt;/b&gt; &lt;input type="text" name="username" required&gt;&lt;/br&gt;
    &lt;b&gt;Password&lt;/b&gt; &lt;input type="password" name="pass" required&gt;&lt;/br&gt;

    &lt;input type="submit" value="Submit"&gt;
    &lt;input type="reset" value="Reset" /&gt;

&lt;/form&gt;
&lt;/center&gt;</code></pre>



<p>The variable <code>$error_message</code> is used to display any error encountered while validating the user credentials.</p>



<p>We are using the <em>master</em> <em><strong>layout</strong></em> that we created in the <a href="/mojolicious-part2-layouts-templates/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">previous session</a>. We changed the <em>title</em> helper to say it&#8217;s a <em>Login Page</em>. Then we created a very simple login form which on submit is routed to <code>/login</code> action.</p>



<h4 class="wp-block-heading">Logout Page</h4>



<p>We will now create a logout page template with the name <em>logout.html.ep</em> in our template folder: <em>myWebSite/templates/myTemplates</em> with the below content:</p>



<pre class="wp-block-code"><code>% layout 'master';
% title 'Logout Page';

&lt;center&gt;
&lt;h6&gt;You have successfully logged out of the website. Thank you for visiting. If you want to login again, please &lt;a href="/"&gt;click here&lt;/a&gt;&lt;/h6&gt;
&lt;/center&gt;</code></pre>



<h4 class="wp-block-heading">Modify Home Page</h4>



<p>Let&#8217;s also add a logout link to our <em>homepage</em> template that we created in the previous article.</p>



<pre class="wp-block-code"><code>% layout 'master';
% title 'Home Page';
      &lt;a href="/logout"&gt;Log Out&lt;/a&gt;
      &lt;h1&gt;&lt;%= $msg %&gt;&lt;/h1&gt;
      &lt;h5 class="w3-padding-32"&gt;This is my personal site built with Mojolicious. You can provide testimonials using the link &lt;a href="#"&gt;here&lt;/a&gt;. 
&lt;/h5&gt;</code></pre>



<h2 class="wp-block-heading">Authentication and Session Management</h2>



<p>Our login and logout pages are ready, now time to add logic to authenticate the registered users using session cookies. We will create the below 3 subroutines in our controller (<em>CustomController.pm</em>*):</p>



<ul class="wp-block-list"><li>displayLogin</li><li>validUserCheck</li><li>alreadyLoggedIn</li><li>logout</li></ul>



<p>*<em>myWebSite/lib/myWebSite/Controller/CustomController.pm</em></p>



<h4 class="wp-block-heading">displayLogin</h4>



<p>This subroutine will display the <em>login page</em> template that we created in the previous section of this article. In case the user is already logged in, they will be redirected to the home page.</p>



<pre class="wp-block-code"><code>sub displayLogin {

    my $self = shift;

    # If already logged in then direct to home page, if not display login page
    if(&amp;alreadyLoggedIn($self)){
    # If you are using Mojolicious v9.25 and above use this if statement as re-rendering is forbidden
    # Thank you @Paul and @Peter for pointing this out.
    # if($self->session('is_auth')){

            &amp;welcome($self);

    }else{

       $self->render(template => "myTemplates/login", error_message =>  "");

    }

}</code></pre>



<h4 class="wp-block-heading">validUserCheck</h4>



<p>This subroutine will check the details entered by the user in the login page and authenticates the user to access the website. This also creates session cookies to keep the user&#8217;s session active. The users are prompted with proper error messages when incorrect credentials are passed. We set the variable <code>error_message</code> here which gets displayed in our <em>login.html.ep</em> template.</p>



<pre class="wp-block-code"><code>sub validUserCheck {

    my $self = shift;

    # List of registered users
    my %validUsers = ( "JANE" =&gt; "welcome123"
                      ,"JILL" =&gt; "welcome234"
                      ,"TOM"  =&gt; "welcome345"
                      ,"RAJ"  =&gt; "test123"
                      ,"RAM"  =&gt; "digitalocean123"
                     );

    # Get the user name and password from the page
    my $user = uc $self-&gt;param('username');
    my $password = $self-&gt;param('pass');

    # First check if the user exists
    if($validUsers{$user}){

        # Validating the password of the registered user
        if($validUsers{$user} eq $password){

            # Creating session cookies
            $self-&gt;session(is_auth =&gt; 1);             # set the logged_in flag
            $self-&gt;session(username =&gt; $user);        # keep a copy of the username
            $self-&gt;session(expiration =&gt; 600);        # expire this session in 10 minutes if no activity


            # Re-direct to home page
            &amp;welcome($self);

        }else{

            # If password is incorrect, re-direct to login page and then display appropriate message
            $self-&gt;render(template =&gt; "myTemplates/login", error_message =&gt;  "Invalid password, please try again");
        }

    }else{

        # If user does not exist, re-direct to login page and then display appropriate message
        $self-&gt;render(template =&gt; "myTemplates/login", error_message =&gt;  "You are not a registered user, please get the hell out of here!");

    }

}</code></pre>



<h4 class="wp-block-heading">alreadyLoggedIn</h4>



<p>This subroutine checks session cookies to see if the user has already logged in, if yes then the user will be automatically allowed to access the pages in the website</p>



<pre class="wp-block-code"><code>sub alreadyLoggedIn {

      my $self = shift;

      # checks if session flag (is_auth) is already set
      return 1 if $self-&gt;session('is_auth');


      # If session flag not set re-direct to login page again.
      $self-&gt;render(template =&gt; "myTemplates/login", error_message =&gt;  "You are not logged in, please login to access this website");

      return;

}</code></pre>



<h4 class="wp-block-heading">logout</h4>



<p>We need to destroy all the session cookies that were created when the user logged in, forcing any visitor to the website to enter the credentials again. <code>logout</code> subroutine does that.</p>



<pre class="wp-block-code"><code>sub logout {

    my $self = shift;

    # Remove session and direct to logout page
    $self-&gt;session(expires =&gt; 1);  #Kill the Session
    $self-&gt;render(template =&gt; "myTemplates/logout");

}</code></pre>



<p>After all these changes your controller should look like <a href="/wp-content/uploads/misc/CustomController.txt" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">this</a>.</p>



<p>Now we need to tell Mojolicious to call these subroutine whenever there is any action on the page. What handles the action on the page? If you have gone through the <a aria-label="undefined (opens in a new tab)" href="/mojolicious-part2-layouts-templates/" target="_blank" rel="noreferrer noopener">previous articles</a>, you know it&#8217;s the main library file: <em>myWebSite/lib/myWebSite.pm</em>. Right now we only have 1 routes in our main library file which looks like this:</p>



<pre class="wp-block-code"><code># Normal route to controller
$r-&gt;get('/')-&gt;to('CustomController#welcome');</code></pre>



<p>Lets add the routes to send requests to all the subroutines we created in the previous section</p>



<pre class="wp-block-code"><code># Normal route to controller
$r-&gt;get('/')-&gt;to('CustomController#displayLogin');
$r-&gt;post('/login')-&gt;to('CustomController#validUserCheck');
$r-&gt;any('/logout')-&gt;to('CustomController#logout');

my $authorized = $r-&gt;under('/')-&gt;to('CustomController#alreadyLoggedIn');</code></pre>



<p>Our main library file should finally look like <a aria-label="undefined (opens in a new tab)" href="/wp-content/uploads/misc/myWebSite.txt" target="_blank" rel="noreferrer noopener">this</a>.</p>



<p>Let us just try to understand quickly what all we are trying to do:</p>



<p><code>$r-&gt;get('/')-&gt;to('CustomController#login');</code> Whenever anyone accesses our root path of the website redirect them to <code>login</code> subroutine(which renders login page), instead of the home page which was the case before.</p>



<p><code>$r-&gt;post('/login')-&gt;to('CustomController#validUserCheck');</code> When the credentials are entered and submitted in the login page we will route the request to <code>validUserCheck</code> subroutine which basically validates the user, creates session cookies and redirects the user to website home page.</p>



<p><code>$r-&gt;any('/logout')-&gt;to('CustomController#logout');</code> Whenever <em>Log Out</em> link is clicked, it directs the request to <code>logout</code> subroutine which destroys the session cookies.</p>



<p><code>my $authorized = $r-&gt;under('/')-&gt;to('CustomController#alreadyLoggedIn');</code> This is a special condition. The &#8220;<strong>under</strong>&#8221; call ensures nothing after this statement gets executed, if the subroutine in &#8220;under&#8221; call fails(in our case the subroutine is <code>alreadyLoggedIn</code>). This is especially useful when we have multiple webpages and you want only authorized users has access to it. We will see this is our next session when we build our testimonials page.</p>



<h2 class="wp-block-heading">Verification</h2>



<p>I guess we have done everything that is required to enable authentication to our website. Let us not waste any more time and start our web application with morbo:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="772" height="321" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1.jpg" alt="" class="wp-image-362" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1.jpg 772w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1-768x319.jpg 768w" sizes="auto, (max-width: 772px) 100vw, 772px" /></figure></div>



<p>When we access our website now, we are greeted with the login page instead of the home page:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1185" height="815" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-login-page2.png" alt="" class="wp-image-442" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-login-page2.png 1185w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-login-page2-768x528.png 768w" sizes="auto, (max-width: 1185px) 100vw, 1185px" /></figure></div>



<p>If you give incorrect credentials, you will get not be allowed to login and will get the below messages:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1198" height="822" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-login-wrong-user.png" alt="" class="wp-image-443" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-login-wrong-user.png 1198w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-login-wrong-user-768x527.png 768w" sizes="auto, (max-width: 1198px) 100vw, 1198px" /><figcaption>incorrect username</figcaption></figure></div>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1040" height="740" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-login-wrong-password.png" alt="" class="wp-image-444" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-login-wrong-password.png 1040w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-login-wrong-password-768x546.png 768w" sizes="auto, (max-width: 1040px) 100vw, 1040px" /><figcaption>incorrect password</figcaption></figure></div>



<p>Valid users will be logged into the website and they can access the home page. They will also see a logout link in their home page.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1279" height="868" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-new-homepage.png" alt="" class="wp-image-445" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-new-homepage.png 1279w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-new-homepage-768x521.png 768w" sizes="auto, (max-width: 1279px) 100vw, 1279px" /><figcaption>New homepage with logout</figcaption></figure></div>



<div class="wp-block-image is-style-default"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1257" height="840" src="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-logout-page.png" alt="" class="wp-image-446" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-logout-page.png 1257w, https://thecurioustechnoid.com/wp-content/uploads/2020/07/mojo-logout-page-768x513.png 768w" sizes="auto, (max-width: 1257px) 100vw, 1257px" /><figcaption>Logout Page</figcaption></figure></div>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>With that we have secured our website. This completes the session management and user authentication part of Mojolicious tutorial. Ofcourse in the real world, you would validate the user credentials from your database with encrypted passwords. For the purpose of this demo, I have kept it simple. In the <a href="/mojolicious-part-4-database-management/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">next session</a>, we will cover <a href="/mojolicious-part-4-database-management/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">database management</a> in Mojolicious. You can watch the demo of this article in my youtube channel below.</p>



<figure class="wp-block-embed aligncenter is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Mojolicious (Part 3): Session Management" width="640" height="360" src="https://www.youtube.com/embed/SnGxyxe41fc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-part-3-session-management/">Mojolicious (Part 3): Session Management</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/mojolicious-part-3-session-management/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title>Mojolicious (Part 2): Layouts and Templates</title>
		<link>https://thecurioustechnoid.com/mojolicious-part2-layouts-templates/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mojolicious-part2-layouts-templates</link>
					<comments>https://thecurioustechnoid.com/mojolicious-part2-layouts-templates/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Thu, 02 Jul 2020 05:00:38 +0000</pubDate>
				<category><![CDATA[Perl / Mojolicious]]></category>
		<category><![CDATA[mojolicious]]></category>
		<category><![CDATA[perl web framework]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[web framework]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=376</guid>

					<description><![CDATA[<p>Now that we have our Home Page built in the previous article, let&#8217;s extend our project from it. Our home page looks quite dull and boring, so let&#8217;s add some color to it. This can be achieved by Layouts and Templates in Mojolicious. To start with, what we need is a nice looking HTML template.&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-part2-layouts-templates/">Mojolicious (Part 2): Layouts and Templates</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Now that we have our Home Page built in the <a href="/mojolicious-part1-homepage/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">previous article</a>, let&#8217;s extend our project from it. Our home page looks quite dull and boring, so let&#8217;s add some color to it. This can be achieved by Layouts and Templates in Mojolicious. To start with, what we need is a nice looking HTML template. Then we embed that template so that Mojolicious starts considering it to render our pages. Let us take it step by step. Firstly, how different are Templates and Layouts ?</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/o1NCMK7Yaqo" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<p><em><strong>Layouts</strong></em> are reusable skeleton of your website. This generally would have your header, logo, footer, menus, side bar etc<br><em><strong>Templates</strong></em> are the dynamic content that you want to display based on different actions on the web portal. This is generally the content that needs to be inside the layout.</p>



<h3 class="wp-block-heading">Download Template</h3>



<p>To put it into action, let&#8217;s download a free HTML template from the internet. I downloaded one from <a href="https://www.w3schools.com/w3css/tryw3css_templates_start_page.htm" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">w3 schools</a>. </p>



<p>It looks like this:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1541" height="895" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-original-template-1.jpg" alt="" class="wp-image-378" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-original-template-1.jpg 1541w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-original-template-1-768x446.jpg 768w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-original-template-1-1536x892.jpg 1536w" sizes="auto, (max-width: 1541px) 100vw, 1541px" /></figure></div>



<p>You can get the <a aria-label="undefined (opens in a new tab)" href="/wp-content/uploads/misc/w3school-html-template.txt" target="_blank" rel="noreferrer noopener">source code here</a>.</p>



<h3 class="wp-block-heading">Create a Layout</h3>



<p>Let us make this HTML template as a <strong>layout</strong> in Mojolicious, so that we can use it across our pages. To do so, lets follow the below steps:</p>



<table style="width: 100%;" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr style="vertical-align: top;">
<td style="width: 9.827586206896552%;">              </td>
<td style="width: 3.9655172413793105%;">1.</td>
<td style="width: 85.86206896551725%;">Create a file called: <em>myWebSite/templates/layouts/master.html.ep</em> with the source code of the HTML we downloaded in the previous section. This will be our <em><strong>layout</strong></em> with name: <em>master</em></td>
</tr>
<tr style="vertical-align: top;">
<td style="width: 9.827586206896552%;">              </td>
<td style="width: 3.9655172413793105%;">2.  </td>
<td style="width: 85.86206896551725%;">Remove the section which you think will not be static across the pages. I will comment the &#8220;Second Grid&#8221; section. I don&#8217;t mind all my website pages having the rest of the content from the downloaded HTML template.</td>
</tr>
<tr style="vertical-align: top;">
<td style="width: 9.827586206896552%;">              </td>
<td style="width: 3.9655172413793105%;">3.</td>
<td style="width: 85.86206896551725%;">I will also change parts of &#8220;First Grid&#8221; section and add the line: <code>&lt;%= content %&gt;</code>. <em><strong>content</strong></em> is a Mojolicious helper which will have static or dynamic data mentioned in the Mojolicious <em><strong>template</strong></em> (which we will see in the next section).</td>
</tr>
<tr style="vertical-align: top;">
<td style="width: 9.827586206896552%;">              </td>
<td style="width: 3.9655172413793105%;">4.  </td>
<td style="width: 85.86206896551725%;">Also instead of static title, replace the title with <code>&lt;%= title %&gt;</code>. You can dynamically change the title value from the Mojolicious <em><strong>template</strong></em>.</td>
</tr>
<tr style="vertical-align: top;">
<td style="width: 9.827586206896552%;">              </td>
<td style="width: 3.9655172413793105%;">5.</td>
<td style="width: 85.86206896551725%;">Also, I replaced the text &#8220;START PAGE&#8221; with title helper: <code>&lt;%= title %&gt;</code></td>
</tr>
<tr style="vertical-align: top;">
<td style="width: 9.827586206896552%;">              </td>
<td style="width: 3.9655172413793105%;">6.</td>
<td style="width: 85.86206896551725%;">Since we only have home page now, I will also comment all the other menu links: <em>Link 1</em>, <em>Link 2</em> etc.</td>
</tr>
</tbody>
</table>



<p>We will finally have the <strong>layout</strong> file, <a aria-label="undefined (opens in a new tab)" href="/wp-content/uploads/misc/master.html.ep.txt" target="_blank" rel="noreferrer noopener">master.html.ep</a> which looks <a aria-label="undefined (opens in a new tab)" href="/wp-content/uploads/misc/master.html.ep.txt" target="_blank" rel="noreferrer noopener">like this</a>. You can check comments by <strong>The Curious Technoid</strong> to know the changes I did to the original file.</p>



<p>This will be our <em><strong>layout</strong></em> which is our website skeleton and will be used across our website. We will only change the <em><strong>content</strong></em> and <em><strong>title</strong></em> dynamically using Mojolicious <strong><em>templates</em></strong>.</p>



<h3 class="wp-block-heading">Create Templates</h3>



<p>Now that we have our website <em><strong>layout</strong></em> in place, we will create <strong><em>templates</em></strong> from where these <strong><em>layouts</em></strong> gets called from. If you have gone through the <a aria-label="undefined (opens in a new tab)" href="/mojolicious-part1-homepage/" target="_blank" rel="noreferrer noopener">previous article</a>, you have already created a new <strong><em>template</em></strong> called: <em>myWebSite/templates/myTemplates/homepage.html.ep</em> which looks like this:</p>



<pre class="wp-block-code"><code>% layout 'default';
% title 'Home Page';
&lt;h2>&lt;%= $msg %>&lt;/h2>
&lt;p> This is my personal site built with Mojolicious. You can provide testimonials using the link &lt;a href="#">here&lt;/a>. 
&lt;/p></code></pre>



<p>Lets change it to call our newly created <strong><em>layout</em></strong> <em>master.html.ep</em>. We also add our &#8220;content&#8221; using the same <em>HTML tag</em> and <em>CSS Class</em> which was their in the original HTML source:</p>



<pre class="wp-block-code"><code>% layout 'master';
% title 'Home Page';
&lt;h1>&lt;%= $msg %>&lt;/h1>
&lt;h5 class="w3-padding-32"> This is my personal site built with Mojolicious. You can provide testimonials using the link &lt;a href="#">here&lt;/a>. 
&lt;/h5></code></pre>



<p><code>% layout 'master';</code> tells Mojolicious which <strong><em>layout</em></strong> to use<br><code>% title 'Home Page';</code> &#8211; the title helper which gets replaced in <strong><em>layout</em></strong><br>Any <strong>HTML data</strong> you enter in the <strong><em>template</em></strong> will be displayed in the <code>&lt;%= content %&gt;</code> section of the <strong><em>layout</em></strong>.</p>



<h3 class="wp-block-heading">Verify Changes</h3>



<p>Now that we have our <strong><em>templates</em></strong> and <strong><em>layouts</em></strong> in place. Lets start our web application using <em>morbo</em>:</p>



<pre class="wp-block-code"><code>morbo myWebSite/script/myWebSite</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="772" height="321" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1.jpg" alt="" class="wp-image-362" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1.jpg 772w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1-768x319.jpg 768w" sizes="auto, (max-width: 772px) 100vw, 772px" /></figure></div>



<p>Since we have <a href="/ssh-tunneling/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">SSH Tunnel</a> enabled as usual, we will check our website using local host and port 3000:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1546" height="894" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-homepage-new-template-1.png" alt="" class="wp-image-380" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-homepage-new-template-1.png 1546w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-homepage-new-template-1-768x444.png 768w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-html-homepage-new-template-1-1536x888.png 1536w" sizes="auto, (max-width: 1546px) 100vw, 1546px" /></figure></div>



<p>Our website doesn&#8217;t look that bad now, does it.</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>In the <a href="/mojolicious-part-3-session-management/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">next article</a>, we will make our website accessible by only registered users using sessions and cookies.</p>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Mojolicious (Part 2): Templates and Layouts" width="640" height="360" src="https://www.youtube.com/embed/o1NCMK7Yaqo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-part2-layouts-templates/">Mojolicious (Part 2): Layouts and Templates</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/mojolicious-part2-layouts-templates/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mojolicious (Part 1): Build Full App</title>
		<link>https://thecurioustechnoid.com/mojolicious-part1-homepage/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mojolicious-part1-homepage</link>
					<comments>https://thecurioustechnoid.com/mojolicious-part1-homepage/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Sat, 27 Jun 2020 11:51:40 +0000</pubDate>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Perl / Mojolicious]]></category>
		<category><![CDATA[mojolicious]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[web framework]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=349</guid>

					<description><![CDATA[<p>In the previous article we looked at how to install Mojolicious, build a hello world web app, test it and deploy the same in the instance. In the course of next few articles, we will look at building a mini project which covers session management, database connections, templates and layouts. Test Case Synopsis The test&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-part1-homepage/">Mojolicious (Part 1): Build Full App</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In the <a aria-label="undefined (opens in a new tab)" href="/mojolicious-intro-hello-world/" target="_blank" rel="noreferrer noopener">previous article</a> we looked at how to install Mojolicious, build a hello world web app, test it and deploy the same in the instance. In the course of next few articles, we will look at building a mini project which covers <a href="/mojolicious-part-3-session-management/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">session management</a>, <a href="/mojolicious-part-4-database-management/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">database connections</a>, <a href="/mojolicious-part2-layouts-templates/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">templates and layouts</a>.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/EdZNpI_t3Fw" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<h2 class="wp-block-heading">Test Case Synopsis</h2>



<p>The test case that we have is to build a web application for testimonials. That&#8217;s the easiest one that I could think of to cover the topics I want to discuss. The web application will have the following features:</p>



<ul class="wp-block-list"><li><strong>Login Page:</strong> Which restricts website access to registered users</li><li><strong>Home Page: </strong>Main page for the registered users with a welcome message and website instructions</li><li><strong>Testimonial Page: </strong>Testimonial Page which displays all the testimonials from database entered by the users and option to save new testimonials in the database</li><li><strong>Log Out: </strong>To gracefully logout of the website</li></ul>



<p>We will also add a simple HTML template to the website which would cover the templates and layouts concept in Mojolicious.</p>



<p>Without further adieu, let&#8217;s begin building this project.</p>



<h2 class="wp-block-heading">Create full_app project</h2>



<p>In our previous tutorial on Mojolicious, we created &#8220;Hello World&#8221; web app with <em>lite_app</em>. This time we will build this project with <em>full_app</em>. To create a <em>full_app</em>, open the terminal and enter the below command:</p>



<pre class="wp-block-code"><code>mojo generate app myWebSite</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="758" height="857" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo_generate_full-1.jpg" alt="" class="wp-image-359"/></figure></div>



<p>This will create a directory called <strong>myWebSite</strong> with the below folder structure:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="612" height="817" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo_full_tree.jpg" alt="" class="wp-image-360"/></figure></div>



<p>Lets understand the below components from the above screenshot</p>



<ul class="wp-block-list"><li>lib</li><li>myWebSite.conf</li><li>public</li><li>script</li><li>t</li><li>templates</li></ul>



<h4 class="wp-block-heading">lib</h4>



<p>The library directory is probably the most crucial directory which holds all your programming code. Your Controller and Model logic goes here. The logic to handle any action on your webpage will be somewhere in this directory.</p>



<p>Your routes and page-actions are sent to the file <code>myWebSite/lib/myWebSite.pm</code> which then invokes the relevant Controller and Model to handle your requests.</p>



<h4 class="wp-block-heading">myWebSite.conf</h4>



<p>This is the master configuration file for your web app. You can add secret phrases for signed cookies, mention the number of workers that you want webservers to run, the port that your application should run on, database connection details, so on and so forth.</p>



<h4 class="wp-block-heading">public</h4>



<p>You can find all your static pages here. Along with the static pages, all publicly available components like your css, images or any other media goes into this directory.</p>



<h4 class="wp-block-heading">script</h4>



<p>Script to start your web site is present in this directory. You run you web app using the <code>script/myWebSite</code> file present in this directory.</p>



<h4 class="wp-block-heading">t</h4>



<p>Folder dedicated for your test scripts.</p>



<h4 class="wp-block-heading">templates</h4>



<p>Directory which holds the templates and layouts used by your web app.</p>



<p>I will not go in detail about the theory as you can always read more about it in the <a href="http://mojolicious.org/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">official website</a> of Mojolicious. Let us proceed with our project.</p>



<p>Let&#8217;s go ahead and run this sample web app as it is, using the development web server morbo:</p>



<pre class="wp-block-code"><code>morbo myWebSite/script/myWebSite</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="772" height="321" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1.jpg" alt="" class="wp-image-362" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1.jpg 772w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo_full_1-768x319.jpg 768w" sizes="auto, (max-width: 772px) 100vw, 772px" /></figure></div>



<p>Since we don&#8217;t see any errors, let&#8217;s fire up the browser and check our page (I have <a href="/ssh-tunneling/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">SSH Tunnel</a> enabled, so I can access the webpage with localhost IP and default port(3000):</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="724" height="242" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo_full_samplepage.png" alt="" class="wp-image-363"/></figure>



<p>Our Website is running fine.</p>



<p>How did our website&#8217;s content get rendered ? Let us understand the flow of events. First, let me just remind you how the structure of your web application looks like:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="612" height="817" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo_full_tree.jpg" alt="" class="wp-image-360"/></figure>



<p>Below diagram shows the flow of events from different files when you access your web page:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1543" height="903" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/MojoControlFlow-1.jpg" alt="" class="wp-image-354" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/MojoControlFlow-1.jpg 1543w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/MojoControlFlow-1-768x449.jpg 768w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/MojoControlFlow-1-1536x899.jpg 1536w" sizes="auto, (max-width: 1543px) 100vw, 1543px" /></figure></div>



<p>Whenever you access any web page built in mojolicious, the first file that gets called is the library file: <em>lib/myWebSite.pm</em>. The line <code>$r-&gt;get('/')-&gt;to('example#welcome');</code> in the file basically tells to go to the controller <em>Example.pm</em> and execute the <em>welcome</em> sub-routine. Controllers, as you can see in the above screenshot are stored in <em>lib/myWebSite/Controller</em>.</p>



<p>In the controller we see the below lines:</p>



<pre class="wp-block-code"><code># Render template "example/welcome.html.ep" with message
$self->render(msg => 'Welcome to the Mojolicious real-time web framework!');</code></pre>



<p>This basically tells Mojolicious to set a value to the variable <code>$msg</code> and render the template. But which template ? We don&#8217;t see any template name mentioned in the controller, then which page is getting rendered?? Well, since no template is explicitly called Mojolicious will look for the template is the path similar to the controller path: <em>example/welcome</em>. In the above directory structure, we can see a template: <em>template/example/welcome.html.ep</em>, that&#8217;s what is getting rendered in the home page now. Ofcourse, you can explicitly mention the template name in the controller and it will exactly behave the same way. Just pass the template name like this:</p>



<pre class="wp-block-code"><code>  $self->render(msg => 'Welcome to the Mojolicious real-time web framework!',template => "example/welcome");</code></pre>



<p>I prefer explicitly mentioning the template names in my controller, to avoid any confusion.</p>



<p>Now that we know that our main page&#8217;s content is being displayed by <em>myWebSite/templates/example/welcome.html.ep</em> and the contents looks like this:</p>



<pre class="wp-block-code"><code>% layout 'default';
% title 'Welcome';
&lt;h2>&lt;%= $msg %>&lt;/h2>
&lt;p>
  This page was generated from the template "templates/example/welcome.html.ep"
  and the layout "templates/layouts/default.html.ep",
  &lt;%= link_to 'click here' => url_for %> to reload the page or
  &lt;%= link_to 'here' => '/index.html' %> to move forward to a static page.
&lt;/p></code></pre>



<p>We will change it to add our content:</p>



<pre class="wp-block-code"><code>% layout 'default';
% title 'Home Page';
&lt;h2>&lt;%= $msg %>&lt;/h2>
&lt;p> This is my personal site built with Mojolicious. You can provide testimonials using the link &lt;a href="#">here&lt;/a>. 
&lt;/p></code></pre>



<p>If you notice that the heading in the above html content is displayed by the variable <code>$msg</code>. This was set by our controller: <em>myWebSite/lib/myWebSite/Controller/Example.pm</em>. Let us open the controller file and change the below line:</p>



<pre class="wp-block-code"><code># Render template "example/welcome.html.ep" with message
$self->render(msg => 'Welcome to the Mojolicious real-time web framework!');</code></pre>



<p>to</p>



<pre class="wp-block-code"><code># Render template "example/welcome.html.ep" with message
$self->render(msg => 'Welcome to My Personal Website!',template => "example/welcome");</code></pre>



<p>Not only did I change the heading, I also explicitly mentioned which template to render.</p>



<p>Lets run our web app with morbo:</p>



<pre class="wp-block-code"><code>morbo myWebSite/script/myWebSite</code></pre>



<p>Refresh our web browser:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="724" height="256" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo_morbo_2.png" alt="" class="wp-image-364"/></figure>



<p>Working as expected. Before we wind up, lets just change the default controller and template files to our customized file names:</p>



<pre class="wp-block-code"><code>cp myWebSite/lib/myWebSite/Controller/Example.pm myWebSite/lib/myWebSite/Controller/CustomController.pm</code></pre>



<pre class="wp-block-code"><code>mkdir myWebSite/templates/myTemplates</code></pre>



<pre class="wp-block-code"><code>cp myWebSite/templates/example/welcome.html.ep myWebSite/templates/myTemplates/homepage.html.ep</code></pre>



<p><strong>New Controller Name : </strong><em>myWebSite/lib/myWebSite/Controller/CustomController.pm</em><br><strong>New Template Name : </strong><em>myWebSite/templates/myTemplates/homepage.html.ep</em></p>



<p>Open the new controller(CustomController.pm) and change the first line to reflect the new controller name, from:</p>



<pre class="wp-block-code"><code>package myWebSite::Controller::Example;</code></pre>



<p>to</p>



<pre class="wp-block-code"><code>package myWebSite::Controller::CustomController;</code></pre>



<p>Now change the below line in the same file to point to our newly created template: <em>myTemplates/homepage</em></p>



<pre class="wp-block-code"><code># Render template "example/welcome.html.ep" with message
$self->render(msg => 'Welcome to My Personal Website!',template => "example/welcome");</code></pre>



<p>to</p>



<pre class="wp-block-code"><code># Render template "myTemplates/homepage.html.ep" with message
$self->render(msg => 'Welcome to My Personal Website!',template => "myTemplates/homepage");</code></pre>



<p>Finally, open the main library file: <em>myWebSite/lib/myWebSite.pm</em> and change the below line to call our now custom controller rather than the default:</p>



<pre class="wp-block-code"><code>$r->get('/')->to('example#welcome');</code></pre>



<p>to</p>



<pre class="wp-block-code"><code>$r->get('/')->to('CustomController#welcome');</code></pre>



<p>Lets start our web app and refresh the browser:</p>



<pre class="wp-block-code"><code>morbo myWebSite/script/myWebSite</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="686" height="265" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo_full_page_final.jpg" alt="" class="wp-image-366"/></figure></div>



<p>You will not see any changes since we didn&#8217;t change the content. But we also didn&#8217;t see any errors that means we have achieved what we want.</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>We successfully created the home page of your website. In the <a href="/mojolicious-part2-layouts-templates/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">next session</a>, we will learn about templates and layouts. We will try to add some color to our dull home page that we created in this article.</p>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Mojolicious (Part 1): Build Full App (Home page)" width="640" height="360" src="https://www.youtube.com/embed/EdZNpI_t3Fw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-part1-homepage/">Mojolicious (Part 1): Build Full App</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/mojolicious-part1-homepage/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mojolicious: &#8220;Hello World&#8221; with Mojolicious::Lite</title>
		<link>https://thecurioustechnoid.com/mojolicious-intro-hello-world/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mojolicious-intro-hello-world</link>
					<comments>https://thecurioustechnoid.com/mojolicious-intro-hello-world/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Sun, 21 Jun 2020 12:13:02 +0000</pubDate>
				<category><![CDATA[Perl / Mojolicious]]></category>
		<category><![CDATA[mojolicious]]></category>
		<category><![CDATA[perl web framework]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=291</guid>

					<description><![CDATA[<p>Mojolicious is a full fledged Perl web development framework developed by the original author of Catalyst framework. You can start building websites with it very quickly and easily. It&#8217;s a very powerful web development tool with tons of features which will enable you to build any web application. Recently, I started experimenting on it and&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-intro-hello-world/">Mojolicious: &#8220;Hello World&#8221; with Mojolicious::Lite</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Mojolicious is a full fledged Perl web development framework developed by the original author of Catalyst framework. You can start building websites with it very quickly and easily. It&#8217;s a very powerful web development tool with tons of features which will enable you to build any web application. Recently, I started experimenting on it and thought would share what I have learnt so far. I will only cover the basics of Mojolicious, which should help you in getting started with this web framework.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/LC9UFVbBp2I" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<p>I strongly suggest you visit the <a rel="noreferrer noopener" href="https://mojolicious.org" target="_blank">official website</a> for in depth documentation:<br><center><a href="https://mojolicious.org" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" width="161" height="38" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojolicious-logo1.png" alt="" class="wp-image-294"></a></center></p><br>



<p>Articles on Mojolicious are published with an assumption that you have basic knowledge on Perl and fundamental idea on how web pages work.</p>



<p>In this article, we will look at Mojolicious::Lite, a Micro real-time web framework(as it&#8217;s author puts it). It&#8217;s a light weight domain specific language built around Mojolicious. This can be used for your tiny one page projects. We will cover the following topics in this blog:</p>



<ol class="wp-block-list"><li>Installation of Mojolicious</li><li>Building a simple &#8220;Hello World&#8221; app with Mojolicious::Lite</li><li>Testing</li><li>Deployment</li></ol>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Installation</h2>



<p>There are 2 different methods to install Mojolicious. You can chose whichever method you find convenient:</p>



<h4 class="wp-block-heading">Method 1</h4>



<p>Installation of the powerful Mojolicious framework can be achieved using only a single-line command. Open the terminal in your server and run the below command:</p>



<pre class="wp-block-code"><code>curl -L https://cpanmin.us | perl - -M https://cpan.metacpan.org -n Mojolicious</code></pre>



<p><em><sup><span style="color:#cf2e2e" class="tadv-color">*source: <a href="https://mojolicious.org" target="_blank" rel="noreferrer noopener">https://mojolicious.org</a></span></sup></em></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1285" height="479" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-install.jpg" alt="" class="wp-image-309" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-install.jpg 1285w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-install-768x286.jpg 768w" sizes="auto, (max-width: 1285px) 100vw, 1285px" /></figure>



<p>That&#8217;s all, this will install the full Mojolicious framework.</p>



<h4 class="wp-block-heading">Method 2</h4>



<p>Alternatively, you can also install it with traditional CPAN command similar to installing any Perl module:</p>



<pre class="wp-block-code"><code>cpanm Mojolicious</code></pre>



<p>OR</p>



<pre class="wp-block-code"><code>perl -MCPAN -e shell
install Mojolicious</code></pre>



<p>This also installs full Mojolicious framework that required to build web applications.</p>



<p>Trust me when I say it, use the <strong>Method 1</strong>, it&#8217;s faster to install that way.</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">&#8220;Hello World&#8221; with Mojolicious::Lite</h2>



<p>We have Mojolicious installed in our server by following the previous step, now lets go ahead and create a <em>lite_app</em> and try to bring the famous <strong>&#8220;Hello World&#8221;</strong> page live in that server.</p>



<p>You can create the <em>lite_app</em> using the below command. <em>lite_app</em> are usually used for simple projects involving probably a single page. Let us create a <em>lite_app</em> called <strong>hellomojo</strong> using the command:</p>



<pre class="wp-block-code"><code>mojo generate lite_app hellomojo</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="955" height="357" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-new-lite-project.png" alt="" class="wp-image-311" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-new-lite-project.png 955w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-new-lite-project-768x287.png 768w" sizes="auto, (max-width: 955px) 100vw, 955px" /></figure>



<p>The above command will create a file called <strong>hellomojo</strong> in your current directory:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="786" height="404" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-new-lite-project-list.png" alt="" class="wp-image-312" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-new-lite-project-list.png 786w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-new-lite-project-list-768x395.png 768w" sizes="auto, (max-width: 786px) 100vw, 786px" /></figure>



<p>The <strong>hellomojo</strong> file created is a working sample webpage. You can start building your project on top of this file. The contents of the file will look something like this:</p>



<pre class="wp-block-code"><code>#!/usr/bin/env perl
use Mojolicious::Lite;

get '/' => sub {
  my $c = shift;
  $c->render(template => 'index');
};

app->start;
__DATA__

@@ index.html.ep
% layout 'default';
% title 'Welcome';
&lt;h1>Welcome to the Mojolicious real-time web framework!&lt;/h1>

@@ layouts/default.html.ep
&lt;!DOCTYPE html>
&lt;html>
  &lt;head>&lt;title>&lt;%= title %>&lt;/title>&lt;/head>
  &lt;body>&lt;%= content %>&lt;/body>
&lt;/html></code></pre>



<p>The sample file is easily understandable for anyone familiar with Perl. The contents after <strong><em>_DATA_</em></strong> is treated as templates and layouts that the code uses to display the web content. We will see more about templates and layouts when we build a test project with <em>full_app</em> in future sessions.</p>



<p>For our <strong>&#8220;Hello World&#8221;</strong> page, we will change the contents of hellomojo to look like this:</p>



<pre class="wp-block-code"><code>#!/usr/bin/env perl
use Mojolicious::Lite;

get '/' => sub {
  my $c = shift;
  $c->render(template => 'index');
};

app->start;
__DATA__

@@ index.html.ep
% layout 'default';
% title 'Hello World Tutorial with Mojolicious';
&lt;h1>Hello World!!&lt;/h1>

@@ layouts/default.html.ep
&lt;!DOCTYPE html>
&lt;html>
  &lt;head>&lt;title>&lt;%= title %>&lt;/title>&lt;/head>
  &lt;body>&lt;%= content %>&lt;/body>
&lt;/html></code></pre>



<p>We only changed the below two lines in the file i.e., the window title and the content.</p>



<p><code>% title 'Hello World Tutorial with Mojolicious';<br>&lt;h1&gt;Hello World!!&lt;/h1&gt;</code></p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Testing</h2>



<p>We changed the default sample page&#8217;s content to add our <strong>&#8220;Hello World&#8221;</strong> text. Now let&#8217;s go ahead and test the page. We can test the pages created in Mojolicious using the development web server <em><strong>morbo</strong></em>. Lets not waste any time and go ahead and execute the below command to run our <strong>hellomojo</strong> web app:</p>



<pre class="wp-block-code"><code>morbo hellomojo</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="733" height="254" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-morbo.jpg" alt="" class="wp-image-313"/></figure>



<p>We can see that our page is running. <strong><em>morbo</em></strong> also gives us the URL with port where our website is running:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="570" height="35" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-morbo-port.png" alt="" class="wp-image-314"/></figure>



<p>By default, morbo runs our pages on port 3000. Since <strong><em>morbo </em></strong>is a development web server, debugging is enabled by default and the web server runs in the foreground with debug messages. As we don&#8217;t see any errors on the terminal, the page looks fine.</p>



<p>We won&#8217;t be able to access the webpage from the local Desktop since port 3000 will not be open in the server. Either we open the port in the firewall, or use <a rel="noreferrer noopener" href="/ssh-tunneling/" target="_blank">SSH Tunneling</a>. I prefer SSH Tunneling, <a rel="noreferrer noopener" href="/ssh-tunneling/" target="_blank">read more about SSH Tunneling here</a>.</p>



<p>Let us go ahead and start a SSH Tunnel to our server from the local Desktop using <a href="/how-to-setup-ssh-keys/" target="_blank" rel="noreferrer noopener">SSH Keys</a>:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="965" height="250" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-ssh-tunnel.jpg" alt="" class="wp-image-315" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-ssh-tunnel.jpg 965w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-ssh-tunnel-768x199.jpg 768w" sizes="auto, (max-width: 965px) 100vw, 965px" /></figure>



<p>Now that the SSH Tunnel is active, lets go ahead and check our page from our browser using the server&#8217;s localhost IP(since SSH Tunnel is running) and morbo&#8217;s port(3000): http://127.0.0.1:3000</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="885" height="272" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo-hello-world-page.jpg" alt="" class="wp-image-317" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo-hello-world-page.jpg 885w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/morbo-hello-world-page-768x236.jpg 768w" sizes="auto, (max-width: 885px) 100vw, 885px" /></figure>



<p>Success!! We have a working &#8220;Hello World&#8221; page ready to be deployed.</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Deployment</h2>



<p>Now that we tested and made sure that our <strong>&#8220;Hello World&#8221;</strong> page is working fine, we will deploy it in the server so that it runs all the time. There are different production web servers which gets shipped with Mojolicious (you can <a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#Hypnotoad" target="_blank" rel="noreferrer noopener">read more about it here</a>), I use <em><strong>hypnotoad</strong></em> &#8211; ALL GLORY TO THE HYPNOTOAD!. It&#8217;s a recommended production grade web server to run Mojolicious web apps.</p>



<p>The command to run your page using <strong><em>hypnotoad</em></strong> is similar to <em>morbo</em>:</p>



<pre class="wp-block-code"><code>hypnotoad hellomojo</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="803" height="314" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-hypno.jpg" alt="" class="wp-image-319" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-hypno.jpg 803w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-hypno-768x300.jpg 768w" sizes="auto, (max-width: 803px) 100vw, 803px" /></figure>



<p><strong><em>hypnotoad</em></strong> by default runs on port 8080(which can be changed ofcourse) and runs in the background. Lets fire up the terminal and establish a new <a rel="noreferrer noopener" href="/ssh-tunneling/" target="_blank">SSH Tunnel</a> to our web server on port 8080 this time. Now we can access our <strong>&#8220;Hello World&#8221;</strong> page using the webserver&#8217;s local host IP(because we are connected with SSH Tunnel) on port 8080: http://127.0.0.1:8080</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="944" height="321" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-ssh-tunnel-hypno.jpg" alt="" class="wp-image-320" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-ssh-tunnel-hypno.jpg 944w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-ssh-tunnel-hypno-768x261.jpg 768w" sizes="auto, (max-width: 944px) 100vw, 944px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="832" height="292" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-hypno-hello-world-page.png" alt="" class="wp-image-325" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-hypno-hello-world-page.png 832w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/mojo-hypno-hello-world-page-768x270.png 768w" sizes="auto, (max-width: 832px) 100vw, 832px" /></figure>



<p>There we have it. Our <strong>&#8220;Hello World&#8221;</strong> webpage is running to serve the whole world with it&#8217;s simplicity and humbleness.</p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<p>This was a little introduction as to how to build and deploy Mojolicious apps. In the <a aria-label="undefined (opens in a new tab)" href="/mojolicious-part1-homepage/" target="_blank" rel="noreferrer noopener">next few sessions</a>, we will build a test project using Mojolicious <em>full_app</em> covering <a href="/mojolicious-part2-layouts-templates/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">templates</a>, <a href="/mojolicious-part2-layouts-templates/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">layouts</a>, <a href="/mojolicious-part-3-session-management/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">session management</a> and <a href="/mojolicious-part-4-database-management/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">database connections</a>. Stay tuned.</p>



<p>I strongly suggest you to go through the video tutorials in <a rel="noreferrer noopener" href="http://mojocasts.com" target="_blank">this website</a> called the <a rel="noreferrer noopener" href="http://mojocasts.com" target="_blank">MojoCasts</a>. You can find tremendously useful tutorials on Mojolicious in that website. You can also check this <a rel="noreferrer noopener" href="https://dev.to/akuks/mojoforum-a-forum-in-mojolicious-part-1-4ojd" target="_blank">informative tutorial</a> written by Ashutosh in <a rel="noreferrer noopener" href="https://dev.to/akuks/mojoforum-a-forum-in-mojolicious-part-1-4ojd" target="_blank">dev.to</a>.</p>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Mojolicious Web Development Tool - Introduction" width="640" height="360" src="https://www.youtube.com/embed/LC9UFVbBp2I?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://thecurioustechnoid.com/mojolicious-intro-hello-world/">Mojolicious: &#8220;Hello World&#8221; with Mojolicious::Lite</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/mojolicious-intro-hello-world/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SSH Tunneling (Port Forwarding) &#8211; a use case</title>
		<link>https://thecurioustechnoid.com/ssh-tunneling/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ssh-tunneling</link>
					<comments>https://thecurioustechnoid.com/ssh-tunneling/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Sat, 20 Jun 2020 05:00:00 +0000</pubDate>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[ssh port forwarding]]></category>
		<category><![CDATA[ssh tunnel]]></category>
		<category><![CDATA[ssh tunneling]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=248</guid>

					<description><![CDATA[<p>SSH Tunneling creates an encrypted channel from your local Desktop to the remote server (and vice versa). Once the secured channel is established using SSH Tunnel, you can access the applications in the remote server without the need to open the firewall. This is especially helpful when ports are not open from your local Desktop&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/ssh-tunneling/">SSH Tunneling (Port Forwarding) &#8211; a use case</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>SSH Tunneling creates an encrypted channel from your local Desktop to the remote server (and vice versa). Once the secured channel is established using SSH Tunnel, you can access the applications in the remote server without the need to open the firewall. This is especially helpful when ports are not open from your local Desktop to the remote server that you wish to access. This particularly comes in handy during development phase of your application or during troubleshooting. The only pre-requisite is that you need to have SSH access to that server. There are 3 types of SSH Tunneling: Local Port Forwarding, Remote Port Forwarding and Dynamic Port Forwarding. We will look at <strong>Local Port Forwarding</strong> in this article which is the most frequently used.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/KUdzXueyPZw" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Syntax</h2>



<p>Below is the syntax used to create a SSH Tunnel:</p>



<pre class="wp-block-code"><code>ssh -N -L LOCAL_PORT:HOST:HOST_PORT USER_NAME@REMOTE_SERVER</code></pre>



<ul class="wp-block-list"><li><code>-N</code>restricts you from inputting any command after the connection is established, this is preferred while using SSH Tunneling</li><li><code>-L</code> tells SSH that it’s <em>local port forwarding</em></li><li><code>LOCAL_PORT</code> The port we will use locally</li><li><code>HOST</code> The host address in the remote server. Usually localhost / 127.0.0.1 to access the application running in remote server.</li><li><code>HOST_PORT</code> The port number of the host address where the application is running</li><li><code>USER_NAME</code> User Name of the remote server</li><li><code>REMOTE_SERVER</code> Remote Server IP Address or hostname</li></ul>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Use Case: Connecting to remote database</h2>



<p>If you host your websites in one of the remote VPS servers, you would have stumbled upon the issue of connecting to the database from your local Desktop. I can access the database locally by opening the DB ports in firewall. But, what if I don&#8217;t like opening the DB ports ? The solution: <strong>SSH Tunneling</strong>. We can create a SSH Tunnel from our local Desktop to the VPS server using SSH. Port forward to the remote DB ports, after which we should be able to connect to the database in the remote server as if they are installed locally.</p>



<p>For the purpose of this demo, I have created a new server in <a href="https://m.do.co/c/a023a9d185b3" target="_blank" rel="noreferrer noopener">digital ocean</a> and have installed mariaDB database in it.</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">Setup</h4>



<p><strong><u>Local Desktop:</u></strong><br><strong>Operating System:</strong> macOS Catalina<br><strong>Database Client:</strong> sequel Pro</p>



<p><span style="text-decoration: underline;"><strong>Remote Server:</strong></span><br data-rich-text-line-break="true" /><strong>Provider:</strong> Digital Ocean<br data-rich-text-line-break="true" /><strong>Operating System:</strong> Fedora 31 (Cloud Edition)<br data-rich-text-line-break="true" /><strong>Database Server:</strong> mariaDB</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>
</div></div>



<h4 class="wp-block-heading">Create SSH Tunnel</h4>



<p>First we will create the SSH Tunnel by running the below command in terminal:</p>



<pre class="wp-block-code"><code>ssh -N -L 2000:127.0.0.1:3306 demo@161.35.77.93 -i ~/.ssh/id_curioustechnoid</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1316" height="564" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-tunnel-cmd.png" alt="" class="wp-image-254" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-tunnel-cmd.png 1316w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-tunnel-cmd-768x329.png 768w" sizes="auto, (max-width: 1316px) 100vw, 1316px" /></figure>



<ul class="wp-block-list"><li><code>2000</code> is the <strong>local port</strong> that we will use in the client</li><li><code>127.0.0.1 </code>is the <strong>Remote Server localhost</strong>. This is nothing but <em>localhost</em> in the remote server</li><li><code>3306 </code>is the <strong>Remote Server mariaDB Port</strong></li><li><code>demo</code> is the <strong>Remote SSH User Name</strong>.</li><li><code>161.35.77.93</code> This is the <strong>Remote Server IP Address</strong></li><li><code>~/.ssh/id_curioustechnoid</code> is the private <strong>SSH Key</strong> used to connect to server. Read more about <a href="/how-to-setup-ssh-keys/">SSH Keys here</a>.</li></ul>



<p>Change the values based on your setup. If all the options are provided correctly we should have an active SSH Tunnel created.</p>



<p>What the above command did is that it created a SSH Tunnel which port forwards any request on port 2000 to the remote server&#8217;s port 3306. In our case mariaDB is running in the default port 3306 in the remote server. In the above command, we are using SSH Keys to connect to the server. It&#8217;s strongly recommended to use <a href="/how-to-setup-ssh-keys/" target="_blank" rel="noreferrer noopener">SSH Keys</a> to connect to remote servers instead of username/password. <a href="/how-to-setup-ssh-keys/" target="_blank" rel="noreferrer noopener">Click here</a> to know more about <a href="/how-to-setup-ssh-keys/" target="_blank" rel="noreferrer noopener">SSH Keys</a>.</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">Connect to database</h4>



<p>We now have encrypted connection established between local and remote server using the above SSH Tunnel command. Lets try to connect to the database in the remote server.</p>



<p>I will be using sequelPro database client and will connect to root database user. Enter the following details in connection section:</p>



<figure class="wp-block-table"><table><tbody><tr><td><strong>Host</strong></td><td>127.0.0.1</td><td><em>localhost</em></td></tr><tr><td><strong>Username</strong></td><td>root</td><td><em>Database User</em> <em>in the remote server</em></td></tr><tr><td><strong>Password</strong></td><td>*******</td><td><em>Database Password</em> <em>in the remote server</em></td></tr><tr><td><strong>Database</strong></td><td></td><td><em>Database you want to connect to.</em></td></tr><tr><td><strong>Port</strong></td><td>2000</td><td><em>Local port which while creating the SSH Tunnel</em></td></tr></tbody></table></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1191" height="779" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-tunnel-db-details.png" alt="" class="wp-image-256" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-tunnel-db-details.png 1191w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-tunnel-db-details-768x502.png 768w" sizes="auto, (max-width: 1191px) 100vw, 1191px" /><figcaption>Credential Details</figcaption></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1042" height="501" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-tunnel-db-connected.png" alt="" class="wp-image-257" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-tunnel-db-connected.png 1042w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-tunnel-db-connected-768x369.png 768w" sizes="auto, (max-width: 1042px) 100vw, 1042px" /><figcaption>Connection Established</figcaption></figure>



<p>We have successfully connected to the remote database using SSH Tunneling. You would have noticed that we are using localhost(127.0.0.1) and localport(2000) to connect to the database hosted in remote server. The practical usage of this concept in limitless.</p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Hope this article helps you in using SSH Tunnels. Please feel free to share your experience or your issues in the comment section below. Happy to help!</p>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="SSH Tunneling - A Use Case" width="640" height="360" src="https://www.youtube.com/embed/KUdzXueyPZw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p></p>
<p>The post <a href="https://thecurioustechnoid.com/ssh-tunneling/">SSH Tunneling (Port Forwarding) &#8211; a use case</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/ssh-tunneling/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to use SSH Keys</title>
		<link>https://thecurioustechnoid.com/how-to-setup-ssh-keys/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-setup-ssh-keys</link>
					<comments>https://thecurioustechnoid.com/how-to-setup-ssh-keys/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Wed, 17 Jun 2020 14:06:40 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[ssh keys]]></category>
		<category><![CDATA[ssh-keys]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=208</guid>

					<description><![CDATA[<p>SSH Keys are one of the safest ways to connect to your server. It involves public-private key pair which authenticates the user to login to the server. The private key is installed in the local Desktop / Server, whereas the public key in installed in the server to which you wish to connect. Today we&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/how-to-setup-ssh-keys/">How to use SSH Keys</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>SSH Keys are one of the safest ways to connect to your server. It involves public-private key pair which authenticates the user to login to the server. The <em><strong>private key</strong></em> is installed in the local Desktop / Server, whereas the <em><strong>public key</strong></em> in installed in the server to which you wish to connect.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/Dj3vz0VtuvY" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<p>Today we will cover the below topics which will help you start using SSH keys right away:</p>



<ul class="wp-block-list"><li>Generation of SSH Keys</li><li>Installation of SSH Keys</li><li>Connecting using SSH Keys</li><li>SSH Config File</li></ul>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">How to generate SSH Keys</h3>



<p>We can generate the SSH Key pair using the <strong>ssh-keygen</strong> command. You have the option to choose from 4 encryption algorithms that <strong>ssh-keygen</strong> supports as of this writing. The 4 algorithms are rsa, dsa , ecdsa and ed25519. I always use <em>ecdsa</em> which is a strong algorithm that meets modern security standards. It is highly recommended you generate the SSH key pair using a passphrase. This ensures that, if someone gets their hand on your private key, they wouldn&#8217;t be able to use it without the passphrase.</p>



<p>In your local Desktop / Server you can generate SSH Key pair using the below command:</p>



<pre class="wp-block-code"><code>ssh-keygen -t ecdsa</code></pre>



<p>When you the above command is executed, you will be prompted with the below (optional) inputs:</p>



<ul class="wp-block-list"><li><strong>Enter file in which to save the key (/root/.ssh/id_ecdsa):</strong> &#8211; If you don&#8217;t pass any value to this, the key-pair will be created in the <code>~/.ssh</code> folder by default, with the name <em>id_ecdsa</em>. You can always enter your preferred name to override this.</li><li><strong>Enter passphrase (empty for no passphrase):</strong> &#8211; This accept empty sting as input if you don&#8217;t wish to use a passphrase. However, I strongly recommend you provide a passphrase so that no-one else will be able to access your private key.</li></ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="974" height="636" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-generation1.png" alt="" class="wp-image-214" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-generation1.png 974w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-generation1-768x501.png 768w" sizes="auto, (max-width: 974px) 100vw, 974px" /><figcaption><em><strong>-t ecdsa </strong>option would use the ecdsa algorithm to create the key file pair</em></figcaption></figure>



<p>Once the keys are generated, you will find two files created by <strong>ssh-keygen</strong>, in my case they are: <strong>id_curioustechnoid</strong> and <strong>id_curioustechnoid.pub</strong></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="864" height="354" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-keys.png" alt="" class="wp-image-212" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-keys.png 864w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-keys-768x315.png 768w" sizes="auto, (max-width: 864px) 100vw, 864px" /></figure>



<p><strong>id_curioustechnoid </strong>         : This is your private key<br><strong>id_curioustechnoid.pub </strong>: This is your public key which we need to install in the remote server</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">How to install SSH Keys</h3>



<p>Now that the SSH Keys are generated, let&#8217;s go ahead and install them.</p>



<h5 class="wp-block-heading">1. Install the private key in your local Desktop / Server</h5>



<p>Installation of your private key in your local Desktop / Server is pretty straightforward and easy. You just copy your private key to <code>~/.ssh</code> directory (if your key is not already there):</p>



<p>First create the <code>~/.ssh </code>directory <em>if it doesn&#8217;t exist</em>:</p>



<pre class="wp-block-code"><code>mkdir ~/.ssh
chmod 700 ~/.ssh</code></pre>



<p>Followed by moving the private key to that directory</p>



<pre class="wp-block-code"><code>mv id_curioustechnoid ~/.ssh</code></pre>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="760" height="496" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-privatekey-install1.png" alt="" class="wp-image-221"/><figcaption>Make sure ~/.ssh folder permission is 700</figcaption></figure>



<p>That&#8217;s it! The private key is now installed in your local Desktop or Server.</p>



<p>You can keep your private key in any directory that you want, it&#8217;s a good practice to keep them in <code>~/.ssh</code> folder in your home directory. If you run the <strong>ssh-keygen</strong> command using all default values, your public-private key pair will be created in <code>~/.ssh</code> directory.</p>



<h5 class="wp-block-heading">2. Install the public key in the remote server</h5>



<p>Let&#8217;s see how we can install the public key in the remote server to which you wish to connect.</p>



<p>Firstly, transfer the public key that you created to your server using your favourite <em>sftp</em> tool. Since I am connected to a headless demo server without GUI I will use the good old <code>scp</code> command for this purpose. I will be transferring the key to my <em>development.local</em> server to which I will be connecting to.</p>



<pre class="wp-block-verse"><code>scp id_curioustechnoid.pub guest@development.local:~/</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1009" height="304" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-scp.png" alt="" class="wp-image-216" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-scp.png 1009w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-scp-768x231.png 768w" sizes="auto, (max-width: 1009px) 100vw, 1009px" /></figure>



<p>What this will do is copy the public key that we just created to my development server and place the file in the home directory.</p>



<p>Next we login to the development server using our username/password: </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="806" height="122" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-connect-dev.png" alt="" class="wp-image-219" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-connect-dev.png 806w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-connect-dev-768x116.png 768w" sizes="auto, (max-width: 806px) 100vw, 806px" /><figcaption>Connecting using SSH</figcaption></figure>



<p>After logging in, append your public key to the SSH authorization file: <code>~/.ssh/authorized_keys</code></p>



<pre class="wp-block-verse"><code>cat id_curioustechnoid.pub &gt;&gt; ~/.ssh/authorized_keys</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="891" height="555" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-publickey-install1.png" alt="" class="wp-image-220" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-publickey-install1.png 891w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-publickey-install1-768x478.png 768w" sizes="auto, (max-width: 891px) 100vw, 891px" /><figcaption>Make sure the directory ~/.ssh has 700 permission and file: ~/.ssh/authorized_keys has 600 permission</figcaption></figure>



<p>Don&#8217;t forget to remove the public key file from home directory by running: <code>rm ~/id_curioustechnoid.pub</code></p>



<p>There you have it, public key successfully installed in the server.</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">How to connect using SSH Keys</h3>



<p>The above steps ensures that the SSH setup is in place, now we can go ahead and connect to our server using the SSH Keys. The below option(-i) tells SSH to use the private key that we just created to connect to <em>development.local</em> server:</p>



<pre class="wp-block-code"><code>ssh guest@development.local -i ~/.ssh/id_curioustechnoid</code></pre>



<p>You will be prompted to enter the passphrase on the screen. Soon after we do, we should be able to successfully connect to the development server.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1018" height="376" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-key-connection.png" alt="" class="wp-image-223" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-key-connection.png 1018w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-key-connection-768x284.png 768w" sizes="auto, (max-width: 1018px) 100vw, 1018px" /></figure>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">SSH config file</h3>



<p>If you connect to multiple servers like me, managing the keys becomes cumbersome and hard to remember. That&#8217;s where SSH config file comes in handy. It&#8217;s a master configuration file where you can list all your SSH connections and it&#8217;s respective keys. This makes accessing any server more convenient.</p>



<p>Let&#8217;s go ahead and create a config file and enter the details of our development server:</p>



<h5 class="wp-block-heading">1. SSH by default recognizes the config file under ~/.ssh directory. </h5>



<p>Let us create the SSH config file using the below command and give it the correct permission(600): </p>



<pre class="wp-block-code"><code>touch ~/.ssh/config
chmod 600 ~/.ssh/config</code></pre>



<h5 class="wp-block-heading">2. Enter your SSH details in the below format</h5>



<p>Open the file <code>~/.ssh/config</code> using your <a href="https://thecurioustechnoid.com/category/vim/" target="_blank" rel="noreferrer noopener">favorite editor</a>:</p>



<pre class="wp-block-code"><code>Host dev
    HostName development.local
    User guest
    IdentityFile ~/.ssh/id_curioustechnoid


Host other-server
    HostName 192.168.1.232
    User root
    IdentityFile ~/.ssh/id_ecdsa</code></pre>



<p>You can keep adding any number of server details in this file. Once the server details are added, connecting to the server is a breeze:</p>



<pre class="wp-block-code"><code>ssh dev</code></pre>



<p>This will prompt you for the passphrase. You enter the passphrase and you will be logged into the development server. Pretty handy isn&#8217;t it.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="899" height="304" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-config-connect.png" alt="" class="wp-image-224" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-config-connect.png 899w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-config-connect-768x260.png 768w" sizes="auto, (max-width: 899px) 100vw, 899px" /></figure>



<p> </p>



<p>There you go, we just created, configured and installed SSH keys.</p>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="How to use SSH Keys" width="640" height="360" src="https://www.youtube.com/embed/Dj3vz0VtuvY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://thecurioustechnoid.com/how-to-setup-ssh-keys/">How to use SSH Keys</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/how-to-setup-ssh-keys/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>HR API Hooks / User Hooks</title>
		<link>https://thecurioustechnoid.com/hr-api-hooks-user-hooks/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=hr-api-hooks-user-hooks</link>
					<comments>https://thecurioustechnoid.com/hr-api-hooks-user-hooks/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Mon, 15 Jun 2020 05:00:00 +0000</pubDate>
				<category><![CDATA[Oracle EBS]]></category>
		<category><![CDATA[api hooks]]></category>
		<category><![CDATA[ebs]]></category>
		<category><![CDATA[hcm]]></category>
		<category><![CDATA[hrms]]></category>
		<category><![CDATA[user hooks]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=66</guid>

					<description><![CDATA[<p>What are HR API Hooks ? Hooks enable us to extend the HR APIs&#8217; capabilities to add additional custom features and validations. Hooks are easier to implement and can be used wherever HR APIs are called, be it a custom interface script or a seeded Self-Service request, if APIs are called then your custom validation&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/hr-api-hooks-user-hooks/">HR API Hooks / User Hooks</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h4><strong>What are HR API Hooks ?</strong></h4>
<p>Hooks enable us to extend the HR APIs&#8217; capabilities to add additional custom features and validations. Hooks are easier to implement and can be used wherever HR APIs are called, be it a custom interface script or a seeded Self-Service request, if APIs are called then your custom validation will be invoked.</p>
<p>HR APIs are some times life saver, where-in the business wishes to add custom validations on a form or a self service page, rather than enhancing it, you just add your validation and you are good to go.</p>
<h4><strong>How to use HR API Hooks?</strong></h4>
<p><em><strong>Tested In:</strong> Oracle EBS 12.1.1, 12.1.3, 12.2.6</em></p>
<p>We will take an example to create user hook on HR_EMPLOYEE_API. The sample business case is,<span id="more-66"></span> I should not be able to hire anyone who is single.</p>
<p><strong>1 .Get the Module ID and Hook ID</strong></p>
<p>Query to get the API_MODULE_ID of the API we will be using, in my case HR_EMPLOYEE_API:</p>
<blockquote><p><code><span style="font-size: 10pt;"> SELECT *</span><br />
<span style="font-size: 10pt;"> FROM HR_API_MODULES</span><br />
<span style="font-size: 10pt;"> WHERE module_package = 'HR_EMPLOYEE_API'</span><br />
<span style="font-size: 10pt;"> AND module_name = 'CREATE_EMPLOYEE' ;</span></code></p></blockquote>
<p>Get the API_HOOK_ID for the module ID(1195), in my case BP &#8211; Before Process</p>
<blockquote><p><code><span style="font-size: 10pt;"> SELECT API_HOOK_ID -- 2690</span><br />
<span style="font-size: 10pt;"> FROM HR_API_HOOKS</span><br />
<span style="font-size: 10pt;"> WHERE api_module_id = 1195 --Module ID from the previous query</span><br />
<span style="font-size: 10pt;"> AND API_HOOK_TYPE = 'BP';</span></code></p></blockquote>
<p><strong>2. Create your custom package</strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>CREATE OR REPLACE PACKAGE XXHR_CUSTOM_HOOKS_PKG<br />
AS<br />
-- Make sure to use only those parameters available in the API are used<br />
PROCEDURE validate_status(p_marital_status in varchar2 default null);<br />
--<br />
END XXHR_CUSTOM_HOOKS_PKG;<br />
/<br />
</code></span></p></blockquote>
<blockquote><p><code><span style="font-size: 10pt;">CREATE OR REPLACE PACKAGE BODY XXHR_CUSTOM_HOOKS_PKG</span><br />
<span style="font-size: 10pt;"> AS</span><br />
<span style="font-size: 10pt;">    PROCEDURE validate_status(p_marital_status in varchar2 default null)</span><br />
<span style="font-size: 10pt;"> IS</span><br />
<span style="font-size: 10pt;">    BEGIN</span><br />
<span style="font-size: 10pt;">       --If the marital status is single, throw an error</span><br />
<span style="font-size: 10pt;">       IF p_marital_status = 'S'</span><br />
<span style="font-size: 10pt;">       THEN</span><br />
<span style="font-size: 10pt;">          RAISE_APPLICATION_ERROR(-20006,'Custom Error: Single people cannot join our organization');</span><br />
<span style="font-size: 10pt;">       END IF;</span><br />
<span style="font-size: 10pt;">    END;</span><br />
<span style="font-size: 10pt;"> --</span><br />
<span style="font-size: 10pt;"> END XXHR_CUSTOM_HOOKS_PKG;</span><br />
<span style="font-size: 10pt;"> /</span></code></p></blockquote>
<p><strong>3. Create User Hook</strong></p>
<p>User hooks can be created using the below script by passing the custom package we created the previous step:</p>
<blockquote>
<pre><code><span style="font-size: 10pt;">SET SERVEROUTPUT ON;
--
DECLARE
   l_api_hook_call_id        NUMBER;
   l_object_version_number   NUMBER;
   l_sequence                NUMBER;
BEGIN
   SELECT hr_api_hooks_s.NEXTVAL
     INTO l_sequence
     FROM DUAL;

   hr_api_hook_call_api.create_api_hook_call
       (p_validate                   =&gt; FALSE,
        p_effective_date             =&gt; TO_DATE ('01-JAN-1952', 'DD-MON-YYYY'),
        p_api_hook_id                =&gt; 2690,  -- Retrieved Previously
        p_api_hook_call_type         =&gt; 'PP',
        p_sequence                   =&gt; l_sequence,
        p_enabled_flag               =&gt; 'Y',
        p_call_package               =&gt; 'XXHR_CUSTOM_HOOKS_PKG',
        p_call_procedure             =&gt; UPPER ('validate_status'), -- Custom procedure
        p_api_hook_call_id           =&gt; l_api_hook_call_id,
        p_object_version_number      =&gt; l_object_version_number
       );
   DBMS_OUTPUT.put_line ('l_api_hook_call_id ' || l_api_hook_call_id);
   COMMIT;
END;
/
</span></code></pre>
</blockquote>
<p><strong>4. Register User Hook / Run Pre-Processor</strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>DECLARE</code></span><br />
<span style="font-size: 10pt;"> <code>    l_api_module_id number;</code></span><br />
<span style="font-size: 10pt;"> <code> BEGIN</code></span></p>
<p><span style="font-size: 10pt;"><code>    l_api_module_id := 1195; -- Module ID Retrieved from previous query</code></span></p>
<p><span style="font-size: 10pt;"><code>    --</code></span><br />
<span style="font-size: 10pt;"> <code>     -- Create all hook package body source code for one API module</code></span><br />
<span style="font-size: 10pt;"> <code>     --</code></span><br />
<span style="font-size: 10pt;"> <code>     hr_api_user_hooks_utility.create_hooks_one_module(l_api_module_id);</code></span></p>
<p><span style="font-size: 10pt;"><code>    --</code></span><br />
<span style="font-size: 10pt;"> <code>     -- Build the report text</code></span><br />
<span style="font-size: 10pt;"> <code>     --</code></span><br />
<span style="font-size: 10pt;"> <code>     hr_api_user_hooks_utility.write_one_errors_report(l_api_module_id);</code></span><br />
<span style="font-size: 10pt;"> <code> END;</code></span><br />
<span style="font-size: 10pt;"> <code> /</code></span></p></blockquote>
<p>Don&#8217;t forget to check the status of the hook call after running the pre-processor by using the below query:</p>
<p><span style="font-size: 10pt;"><code>SELECT status, encoded_error<br />
FROM HR_API_HOOK_CALLS<br />
where call_package = 'XXHR_CUSTOM_HOOKS_PKG'<br />
and call_procedure = 'VALIDATE_STATUS';</code></span></p>
<h4><span style="font-size: 12pt;"><strong>What does the status mean?</strong></span></h4>
<p>N &#8211; New / Not Active<br />
I &#8211; Invalid / Errored<br />
V &#8211; Valid</p>
<p>If the pre-processor succeeded in registering your Hook call, then the status will be <strong>V</strong> if not then the status will be <strong>I</strong>. There is no direct way of finding the reason for the pre-processor to have failed. There is a script which can help you to find the error details which we will look into now. Run the below scripts in the <strong>same session where you ran pre-processor</strong> script to find the errors if any:</p>
<p><em>Note: This will only work if you have ran the hr_api_user_hooks_utility.write_one_errors_report(l_api_module_id); package call when you ran pre-processor as seen in the pre-processor script above.</em></p>
<p><span style="font-size: 10pt;"><code>/* Run the below script to get the error output */<br />
set heading off<br />
set feedback off<br />
select text<br />
from hr_api_user_hook_reports<br />
where session_id = userenv('SESSIONID')<br />
order by line;</code></span></p>
<p><span style="font-size: 10pt;"><code>/* Don't forget to clear the data from report tables by running the below script */<br />
execute hr_api_user_hooks_utility.clear_hook_report;</code></span></p>
<p><strong>5. Delete User Hook</strong></p>
<p>If you wish to delete the user hook, you can use the below script by passing api_hook_call_id and object_version_number:</p>
<blockquote><p><span style="font-size: 10pt;"><code>SET SERVEROUTPUT ON;</code><br />
<code>DECLARE</code><br />
<code>    --</code><br />
<code>     ln_object_version_number NUMBER;</code><br />
<code>     --</code><br />
<code>BEGIN</code><br />
<code>     /* You can get the api_hook_call_id by using the below query:</code><br />
<code>     SELECT api_hook_call_id, object_version_number</code><br />
<code>     FROM HR_API_HOOK_CALLS</code><br />
<code>     where call_package = 'XXHR_CUSTOM_HOOKS_PKG'</code><br />
<code>     and call_procedure = 'VALIDATE_STATUS';</code><br />
<code>     */</code><br />
<code>     hr_api_hook_call_api.delete_api_hook_call (p_api_hook_call_id =&gt; 1112,</code><br />
<code>                                               p_object_version_number =&gt; 1);</code><br />
<code>     DBMS_OUTPUT.put_line ('DELETED HOOK...');</code><br />
<code>EXCEPTION</code><br />
<code>     WHEN OTHERS</code><br />
<code>     THEN</code><br />
<code>        DBMS_OUTPUT.put_line (SUBSTR ('Error: ' || SQLERRM, 1, 255));</code><br />
<code>END;</code><br />
<code>/</code></span></p></blockquote>
<p><strong>Important tables of Hooks:</strong></p>
<p><span style="font-size: 10pt;"><code>SELECT * FROM HR_API_MODULES -- All Hook Modules can be found here</code></span></p>
<p><span style="font-size: 10pt;"><code>SELECT * FROM HR_API_HOOKS -- All hooks can be found here</code></span></p>
<p><span style="font-size: 10pt;"><code>SELECT * FROM HR_API_HOOK_CALLS -- All custom hook package calls can be found here</code></span></p>
<p><span style="color: #ff0000; font-size: 12pt;"><strong>Caution:</strong></span><br />
<span style="font-size: 12pt;"> 1. API Hooks gets invoked if and only if HR API&#8217;s are called.</span><br />
<span style="font-size: 12pt;"> 2. In quite a few cases HR API Hooks cannot be used where APIs aren&#8217;t called, few examples are:</span></p>
<ul>
<li style="list-style-type: none;">
<ul>
<li><span style="font-size: 12pt;">Certain forms like People Screen does not call API hence hooks will not work. (That&#8217;s where custom.pll or forms personalization comes into play)</span></li>
<li><span style="font-size: 12pt;">If you have configured a Special Information Type(SIT) with approvals, in Employee Self Service for employee&#8217;s to request for something, then don&#8217;t use hooks as API&#8217;s gets invoked only at the time of approval</span></li>
</ul>
</li>
</ul>
<p>The post <a href="https://thecurioustechnoid.com/hr-api-hooks-user-hooks/">HR API Hooks / User Hooks</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/hr-api-hooks-user-hooks/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Secure your computer using fail2ban</title>
		<link>https://thecurioustechnoid.com/step-by-step-guide-to-configure-fail2ban/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=step-by-step-guide-to-configure-fail2ban</link>
					<comments>https://thecurioustechnoid.com/step-by-step-guide-to-configure-fail2ban/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Fri, 12 Jun 2020 10:57:05 +0000</pubDate>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[fail2ban]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=143</guid>

					<description><![CDATA[<p>If you are not aware, fail2ban is a brute-force attack mitigation tool. This post will guide you to quickly install fail2ban with basic configuration. In this article I will be showing how to configure fail2ban for SSH brute-force attacks. Let&#8217;s cut to the chase and start installing fail2ban. For the purpose of this demonstration I&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/step-by-step-guide-to-configure-fail2ban/">Secure your computer using fail2ban</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/EcIJ9yj9Y2U" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="217" height="87"/></a></figure></div>



<p>If you are not aware, fail2ban is a brute-force attack mitigation tool. This post will guide you to quickly install fail2ban with basic configuration. In this article I will be showing how to configure fail2ban for SSH brute-force attacks.</p>



<p>Let&#8217;s cut to the chase and start installing fail2ban.</p>



<p>For the purpose of this demonstration I shall be using Fedora 31. You should be able to find similar commands in your respective distros.</p>



<h2 class="wp-block-heading">Installation</h2>



<p>Installation is pretty straight forward similar to installing any other software in Linux. I will use the DNF package manager which is the default for Fedora now.</p>



<pre class="wp-block-code"><code>dnf install fail2ban -y</code></pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1249" height="699" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/install.png" alt="" class="wp-image-160" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/install.png 1249w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/install-768x430.png 768w" sizes="auto, (max-width: 1249px) 100vw, 1249px" /></figure></div>



<h2 class="wp-block-heading">Configuration</h2>



<p>In fail2ban, setup for a particular service like SSH is called as jail. Like any intruder being put into a jail, any intruder attempting to gain access to your server via SSH would be put inside &#8220;SSHD jail&#8221; and anyone trying to gain access via SFTP would be put inside &#8220;SFTP jail&#8221;. Controlling the parameters to be &#8220;eligible&#8221; to be put into these jails are handled by jail configuration file.</p>



<p>There are 2 configuration files in fail2ban:</p>



<ul class="wp-block-list"><li>/etc/fail2ban/jail.conf</li><li>/etc/fail2ban/fail2ban.conf</li></ul>



<p>It is recommended not to edit these files, but to create a copy of them with &#8216;.local&#8217; file extension. Once you have created the copy change the desired values in those files.</p>



<p><strong>fail2ban.conf </strong>file has the configuration to control fail2ban&#8217;s behaviour. For instance you can set the log level parameters here.<br><strong>jail.conf </strong>file is where you enable services (like ssh, sftp, apache) which you wish to monitor for intrusion. You also define criteria&#8217;s on when to block the IPs.</p>



<p>Below are the brief steps I usually follow to setup fail2ban to mitigate SSH brute-force attacks on my servers.</p>



<h3 class="wp-block-heading">1. <strong>Create &#8216;local&#8217; copies of config files:</strong></h3>



<pre class="wp-block-code"><code> cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
 cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local</code></pre>



<h3 class="wp-block-heading"><strong>2. Enable SSHD jail in jail.local file</strong></h3>



<p>First run the below command to check the active jails configured(should be none obviously):</p>



<p><code>fail2ban-client status</code></p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="885" height="401" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-status-nosetup.png" alt="" class="wp-image-161" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-status-nosetup.png 885w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-status-nosetup-768x348.png 768w" sizes="auto, (max-width: 885px) 100vw, 885px" /></figure></div>



<p>Since this is a fresh installation we can see that no jail has been configured.</p>



<p>Open the <em>jail.conf</em> using your favorite editor(obviously it&#8217;s vim!). Find the section where it says [sshd]. You might find 2 entries, 1 commented and the other uncommented, go to the uncommented entry which should look like this:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="886" height="585" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-default-jail.png" alt="" class="wp-image-162" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-default-jail.png 886w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/ssh-default-jail-768x507.png 768w" sizes="auto, (max-width: 886px) 100vw, 886px" /></figure></div>



<p>Change it to make it look something like this:</p>



<pre class="wp-block-code"><code>#
# SSH servers
#

&#91;sshd]

# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
# normal (default), ddos, extra or aggressive (combines all).
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
#mode   = normal
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3</code></pre>



<p>What did we exactly do here ?</p>



<ul class="wp-block-list"><li><strong>enabled</strong> : This enables the SSHD jail for fail2ban to keep monitoring the SSH connections to your server.</li><li><strong>maxretry</strong> : This defines how many incorrect password tries will you allow users trying to connect to your server via SSH. Beyond this, fail2ban will block them.</li></ul>



<h3 class="wp-block-heading"><strong>3. Additional Configuration</strong></h3>



<p><em>You can skip to step 4, if you want to ignore the below additional configurations but trust me you would want to know about these steps</em></p>



<p>I prefer to change few other parameters in <em>jail.local</em> when I setup fail2ban.</p>



<h5 class="wp-block-heading"><img loading="lazy" decoding="async" width="12" height="12" class="wp-image-184" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot.png" alt="" style="width: 12px;" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot.png 1024w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot-768x768.png 768w" sizes="auto, (max-width: 12px) 100vw, 12px" /><strong>  Ignoring IPs from being blocked</strong></h5>



<p>I have this habit of adding my own IPs to exception list so that I never get blocked by fail2ban. You might want to add your work IPs to this list so that you don&#8217;t get blocked while connecting from office in case you enter incorrect credentials multiple times. To add the the IPs that you want to exclude from monitoring, add them to the ignoreip parameter.</p>



<p>Uncomment and change the below line in <em>jail.local</em></p>



<p><code>#ignoreip = 127.0.0.1/8 ::1</code></p>



<p>to</p>



<p><code>ignoreip = 127.0.0.1/8 ::1 192.168.1.119</code></p>



<p>Assuming that my local IP that I want to exclude from blocking is 192.168.1.119, fail2ban will not &#8220;ban&#8221; this IP no matter how many times I enter incorrect credentials. You can add any number of IPs separated by space or comma.</p>



<h5 class="wp-block-heading"><img loading="lazy" decoding="async" width="12" height="12" class="wp-image-184" style="width: 12px;" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot.png" alt="" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot.png 1024w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot-768x768.png 768w" sizes="auto, (max-width: 12px) 100vw, 12px" />  <strong>Changing bantime and findtime</strong></h5>



<p>Fail2ban gives you the ability to customize certain things like When to Ban? How long to Ban?</p>



<p><strong>findtime</strong> parameter instructs fail2ban, within what duration should the &#8220;maxretry&#8221; value be checked. We had set the maxretry value(in sshd setup above) to 3, lets say we set findtime value to 60mins. So within 60mins if there are 3 incorrect attempts to login, then source IP gets added to ban list.</p>



<p> <strong>bantime</strong> parameter defines how long the IP should be banned, you may wish to ban the IP for a day, a week or a month. This parameter instructs fail2ban the same thing.</p>



<p>For example, lets say our maxretry value is 3 in SSHD configuration. You want to ban users if he enters incorrect password 3 times within a span of 10mins and block him from further attempting to try logging in for 3 days. You will change the value as below:</p>



<p><code>findtime = 10m</code></p>



<p><code>bantime = 76h</code></p>



<h5 class="wp-block-heading"><img loading="lazy" decoding="async" width="12" height="12" class="wp-image-184" style="width: 12px;" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot.png" alt="" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot.png 1024w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot-768x768.png 768w" sizes="auto, (max-width: 12px) 100vw, 12px" />  <strong>Enable logging via systemd journals</strong></h5>



<p>Fedora has a problem where unless logging is directed via systemd journald, it throws an error while starting fail2ban. To avoid this issue, you need to tell fail2ban to log via systemd journald by changing the below parameter:</p>



<p><code>backend = auto</code></p>



<p>to</p>



<p><code>backend = systemd</code></p>



<h5 class="wp-block-heading"><img loading="lazy" decoding="async" width="12" height="12" class="wp-image-184" style="width: 12px;" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot.png" alt="" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot.png 1024w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/blue-dot-768x768.png 768w" sizes="auto, (max-width: 12px) 100vw, 12px" />  Tell fail2ban to use firewalld to block the IPs</h5>



<p>I use firewalld as my firewall management tool so I tell fail2ban to use it to block the IPs by changing the below parameter</p>



<pre class="wp-block-code"><code># Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
banaction_allports = iptables-allports</code></pre>



<p>changed to:</p>



<pre class="wp-block-code"><code># Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = firewallcmd-ipset
banaction_allports = firewallcmd-ipset</code></pre>



<h2 class="wp-block-heading">Verify and start fail2ban</h2>



<p>Once we have all the changes done, we can verify our setup by running the command:</p>



<p><code>fail2ban-client -x start</code></p>



<p>fail2ban will tell us that set up in looking good.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="890" height="403" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-server-ready.png" alt="" class="wp-image-163" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-server-ready.png 890w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-server-ready-768x348.png 768w" sizes="auto, (max-width: 890px) 100vw, 890px" /></figure></div>



<p>Next step is to enable fail2ban so that it starts at boot time automatically. Then we proceed to start the fail2ban service to start monitoring all SSH connections.</p>



<p>Enable fail2ban so that it automatically starts at boot time</p>



<p><code>systemctl enable fail2ban.service</code></p>



<p>Start fail2ban service using the command:</p>



<p><code>systemctl start fail2ban.service</code></p>



<p>Make sure fail2ban is running fine</p>



<p><code>systemctl status fail2ban.service</code></p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1041" height="609" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-running-status-1.png" alt="" class="wp-image-165" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-running-status-1.png 1041w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-running-status-1-768x449.png 768w" sizes="auto, (max-width: 1041px) 100vw, 1041px" /></figure></div>



<p></p>



<p>Congratulations! We just enabled SSH jail to start monitoring all SSH connections to your server. You can check your ssh jail status by running the below command:</p>



<p><code>fail2ban-client status</code></p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="777" height="393" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-status.png" alt="" class="wp-image-166" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-status.png 777w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-status-768x388.png 768w" sizes="auto, (max-width: 777px) 100vw, 777px" /><figcaption>We can see 1 jail is configured, and the service enabled is SSH</figcaption></figure></div>



<p>You can check all the blocked IPs by running the command:</p>



<p><code>fail2ban-client status sshd</code></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="908" height="510" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-ssh-status.png" alt="" class="wp-image-167" srcset="https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-ssh-status.png 908w, https://thecurioustechnoid.com/wp-content/uploads/2020/06/fail2ban-ssh-status-768x431.png 768w" sizes="auto, (max-width: 908px) 100vw, 908px" /><figcaption>No IPs are blocked as it is a fresh installation</figcaption></figure>



<p>You can find the <a rel="noreferrer noopener" href="http://thecurioustechnoid.com/wp-content/uploads/misc/jail.local" target="_blank">jail.local</a> file with all the configuration discussed in this article <a rel="noreferrer noopener" href="http://thecurioustechnoid.com/wp-content/uploads/misc/jail.local" target="_blank">here</a>.</p>



<h2 class="wp-block-heading">Some useful commands to keep in mind</h2>



<ul class="wp-block-list"><li>Check all services monitored by fail2ban: <code>fail2ban-client status</code></li><li>Check the blocked IP List by ssh jail: <code>fail2ban-client status sshd</code></li><li>Remove blocked IPs: <code>fail2ban-client set sshd unbanip 192.168.143.191</code></li><li>Remove all blocked IPs: <code>fail2ban-client unban --all</code></li></ul>



<h2 class="wp-block-heading">Enable Debugging</h2>



<p>In case you stumble upon any issues, we can enable debugging to get more information.</p>



<p><strong>1. Open the file: /etc/fail2ban/fail2ban.local and change the below parameter</strong></p>



<p><code>loglevel = INFO</code></p>



<p>Change to</p>



<p><code>loglevel = DEBUG</code></p>



<p><strong>2. Restart the service</strong></p>



<p><code>systemctl restart fail2ban</code></p>



<p><strong>3. Monitor the debug messages</strong> by looking at the log file which be found at: /var/log/fail2ban.log</p>



<p><code>tail -f /var/log/fail2ban.log</code></p>



<p>If you wish to see fail2ban in action, I suggest you head to the <a rel="noreferrer noopener" href="https://youtu.be/EcIJ9yj9Y2U" target="_blank">video tutorial</a> that I created regarding fail2ban setup. You can drag the video to go directly to <strong>06:32</strong> to see fail2ban in action skipping all the setup which we already discussed in this article. </p>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Secure your computer using fail2ban" width="640" height="360" src="https://www.youtube.com/embed/EcIJ9yj9Y2U?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://thecurioustechnoid.com/step-by-step-guide-to-configure-fail2ban/">Secure your computer using fail2ban</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/step-by-step-guide-to-configure-fail2ban/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Query to check active users in EBS</title>
		<link>https://thecurioustechnoid.com/query-to-check-active-users-in-ebs/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=query-to-check-active-users-in-ebs</link>
					<comments>https://thecurioustechnoid.com/query-to-check-active-users-in-ebs/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Wed, 10 Jun 2020 14:52:00 +0000</pubDate>
				<category><![CDATA[Oracle EBS]]></category>
		<category><![CDATA[active users]]></category>
		<category><![CDATA[ebs]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=74</guid>

					<description><![CDATA[<p>Many times, it so happens that all that you are looking for in google is a query for your problem. I will be putting across important queries in the coming few days, that will be handy in our day to day lives while working on Oracle E-Business Suite. Today we will look into queries to&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/query-to-check-active-users-in-ebs/">Query to check active users in EBS</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Many times, it so happens that all that you are looking for in google is a query for your problem. I will be putting across important queries in the coming few days, that will be handy in our day to day lives while working on Oracle E-Business Suite.</p>
<p>Today we will look into queries to get the number of active users connected to the application and all the active users connect to the (EBS)application.</p>
<p><em><strong>Tested In:</strong> Oracle EBS 12.1.1, 12.1.3, 12.2.6</em></p>
<p>First lets get the all the active users connected to the application using the below query:<span id="more-74"></span></p>
<blockquote>
<pre><span style="font-size: 10pt;"><code>SELECT fnd.node_name
      ,(SELECT user_name 
          FROM fnd_user f 
         WHERE f.user_id = icx.user_id) user_name
  FROM icx_sessions icx
      ,fnd_nodes fnd
 WHERE icx.disabled_flag  &lt;&gt; 'Y'
   AND icx.PSEUDO_FLAG     = 'N'
   AND icx.node_id         = fnd.node_id
   AND (icx.last_connect +
       decode(FND_PROFILE.VALUE('ICX_SESSION_TIMEOUT'),
               NULL,
               icx.limit_time,
               0,
               icx.limit_time,
               FND_PROFILE.VALUE('ICX_SESSION_TIMEOUT') / 60) / 24) &gt; SYSDATE       
   AND counter              &lt; icx.limit_connects</code> </span></pre>
</blockquote>
<p>This query below, will help you to get the number of all active users connected to the application:</p>
<blockquote>
<pre><span style="font-size: 10pt;"><code>SELECT icx.node_id,
       fnd.node_name,
       count(distinct icx.session_id) "ACTIVE_USER_SESSIONS_COUNT"
  FROM icx_sessions icx
      ,fnd_nodes fnd
 WHERE icx.disabled_flag != 'Y'
   AND icx.PSEUDO_FLAG    = 'N'
   AND icx.node_id        = fnd.node_id
   AND (icx.last_connect +
       decode(FND_PROFILE.VALUE('ICX_SESSION_TIMEOUT'),
               NULL,
               icx.limit_time,
               0,
               icx.limit_time,
               FND_PROFILE.VALUE('ICX_SESSION_TIMEOUT') / 60) / 24) &gt;  SYSDATE
   AND counter             &lt; icx.limit_connects
 GROUP by icx.node_id, fnd.node_name</code> </span></pre>
</blockquote>
<p>Hope this helps.</p>
<p>The post <a href="https://thecurioustechnoid.com/query-to-check-active-users-in-ebs/">Query to check active users in EBS</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/query-to-check-active-users-in-ebs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Quit Vim ?</title>
		<link>https://thecurioustechnoid.com/how-to-quit-vim/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-quit-vim</link>
					<comments>https://thecurioustechnoid.com/how-to-quit-vim/#respond</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Fri, 05 Jun 2020 13:35:14 +0000</pubDate>
				<category><![CDATA[Vim]]></category>
		<category><![CDATA[quit]]></category>
		<category><![CDATA[vim]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=120</guid>

					<description><![CDATA[<p>More often than we realize, we see these memes teasing how difficult it is to quit vim if you are new to vim. What better way to start writing about vim than to show &#8220;How to Quit Vim&#8221;. Quitting is nothing but closing the open (and hidden) files in vim. There are multiple ways to&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/how-to-quit-vim/">How to Quit Vim ?</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://youtu.be/41OAQWz-ei0" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" src="https://thecurioustechnoid.com/wp-content/uploads/2020/06/WatchOnYoutubeImage.png" alt="" class="wp-image-78" width="210" height="87"/></a></figure></div>



<p>More often than we realize, we see these memes teasing how difficult it is to quit vim if you are new to vim. What better way to start writing about vim than to show &#8220;How to Quit Vim&#8221;.</p>



<p>Quitting is nothing but closing the open (and hidden) files in vim. There are multiple ways to quit vim:</p>



<h3 class="wp-block-heading">1. :q</h3>



<p>If only 1 file is open and there are no changes to the file, you can quit vim using the below command:</p>



<pre class="wp-block-code"><code>&lt;ESC>:q</code></pre>



<p>If there are any unsaved changes, vim will prompt you saying it cannot exit. Suppose if there are multiple files open in different tabs then it will close the file in the current tab.</p>



<h3 class="wp-block-heading">2. :q!</h3>



<p>If the above command failed to quit vim, you force vim to quit without saving using the below command:</p>



<pre class="wp-block-code"><code>&lt;ESC>:q!</code></pre>



<p>The exclamatory symbol force quits vim without saving. As before, if multiple files are open then it will close the file in the current tab.</p>



<h3 class="wp-block-heading">3. :qa[ll]</h3>



<p>What if there are multiple files that are open and we need to close all the files and quit vim? One way is you keep on hitting :q until all the open files are closed or, alternatively use the below command to quit all the files in one go:</p>



<pre class="wp-block-code"><code>&lt;ESC>:qall</code></pre>



<p>You can also use the shorter version:</p>



<pre class="wp-block-code"><code>&lt;ESC>:qa</code></pre>



<p>But be aware, similar to :q this will close all the files only if there are no unsaved files. If there are then vim will prompt you that it cannot quit.</p>



<h3 class="wp-block-heading">4.  :qa[ll]!</h3>



<p>I guess by now this is pretty self explanatory, it will close all the files before quitting vim even if there are unsaved changes. The unsaved changes will be lost.</p>



<h3 class="wp-block-heading">5. :wq  &lt;or&gt;  : x</h3>



<p>If you wish to save and close the file then use the below command:</p>



<pre class="wp-block-code"><code>&lt;ESC>:wq</code></pre>



<p>You can also use the single letter command:</p>



<pre class="wp-block-code"><code>&lt;ESC>:x</code></pre>



<p>This will save the open file in the current tab and close that file. This will quit vim only if there are only 1 tab that are open. If there are multiple files open in different tabs, then vim will close the current file and bring the file in the next tab ready to be edited.</p>



<h3 class="wp-block-heading">6. :wqa[ll]</h3>



<p>This is pretty self explanatory , it will save all the files and close all the files before quitting vim. Unlike :wq which might or might not quit vim, this will quit vim after taking care of all the files.</p>



<p>Hope after reading this article you will never be stuck inside vim again.</p>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="How to Quit Vim ?" width="640" height="360" src="https://www.youtube.com/embed/41OAQWz-ei0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://thecurioustechnoid.com/how-to-quit-vim/">How to Quit Vim ?</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/how-to-quit-vim/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>FNDLOAD &#8211; A Boon to EBS Developers</title>
		<link>https://thecurioustechnoid.com/fndload-a-boon-to-ebs-developers/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fndload-a-boon-to-ebs-developers</link>
					<comments>https://thecurioustechnoid.com/fndload-a-boon-to-ebs-developers/#comments</comments>
		
		<dc:creator><![CDATA[Rakshith Chengappa Mullengada]]></dc:creator>
		<pubDate>Mon, 01 Jun 2020 05:00:00 +0000</pubDate>
				<category><![CDATA[Oracle EBS]]></category>
		<category><![CDATA[ebs]]></category>
		<category><![CDATA[fndload]]></category>
		<category><![CDATA[hcm]]></category>
		<category><![CDATA[hrms]]></category>
		<category><![CDATA[oracle]]></category>
		<guid isPermaLink="false">https://thecurioustechnoid.com/?p=8</guid>

					<description><![CDATA[<p>I guess one of the boons to application developers in Oracle E-Business Suite is FNDLOAD when it comes to migration of AOL objects; without which our lives would be nothing less than a hell. Here we will explore FNDLOAD commands used to upload and download AOL objects. FNDLOAD command is run from the application server.&#8230;</p>
<p>The post <a href="https://thecurioustechnoid.com/fndload-a-boon-to-ebs-developers/">FNDLOAD &#8211; A Boon to EBS Developers</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I guess one of the boons to application developers in Oracle E-Business Suite is FNDLOAD when it comes to migration of AOL objects; without which our lives would be nothing less than a hell. Here we will explore FNDLOAD commands used to upload and download AOL objects.</p>
<p>FNDLOAD command is run from the application server. This command needs database apps password for uploading and downloading AOL objects. FNDLOAD command can very well be used in shell scripts to automate the migration activity.</p>
<p>FNDLOAD is present in $FND_TOP/bin folder. If your $FND_TOP folder is set then you can directly use FNDLOAD instead of the complete path.</p>
<p>The structure of FNDLOAD goes like this:</p>
<blockquote><p><strong><span style="font-size: 10pt;">$FND_TOP/bin/FNDLOAD &lt;db_user_name&gt;/&lt;db_password&gt; 0 Y &lt;UploadDownloadMode&gt; &lt;AOLSpecificScriptName&gt; &lt;FileWhereYourSetupWillBeStored&gt; &lt;EntityName&gt; &lt;AOLSpecificParameters&gt;</span></strong></p></blockquote>
<p>You can use the wild character &#8216;%&#8217; to extract multiple AOL objects. For any specific parameters, you can check the &lt;AOLSpecificScriptName&gt;, the variables starting with a colon(:) can be used as parameter in the FNDLOAD commands.</p>
<p>Below are few of the commonly used FNDLOAD sample script.<span id="more-8"></span></p>
<p><em>Tested In: Oracle EBS 12.1.1, 12.1.3, 12.2.6</em></p>
<p><span style="text-decoration: underline;"><strong>Lookups</strong></span></p>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Download:</span></strong></p>
<blockquote><p><code><span style="font-size: 10pt;">$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; O Y DOWNLOAD $FND_TOP/patch/115/import/aflvmlu.lct XXHR_CUSTOM_LOOKUP.ldt FND_LOOKUP_TYPE APPLICATION_SHORT_NAME="XXHR" LOOKUP_TYPE="XXHR_CUSTOM_LOOKUP"</span></code></p></blockquote>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Upload:</span></strong></p>
<blockquote><p><code><span style="font-size: 10pt;">$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; O Y UPLOAD $FND_TOP/patch/115/import/aflvmlu.lct XXHR_CUSTOM_LOOKUP.ldt UPLOAD_MODE=REPLACE CUSTOM_MODE=FORCE</span></code></p></blockquote>
<hr>
<p><span style="text-decoration: underline;"><strong>Messages</strong></span></p>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Download:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; 0 Y DOWNLOAD $FND_TOP/patch/115/import/afmdmsg.lct XXHR_CUSTOM_MESSAGE.ldt FND_NEW_MESSAGES APPLICATION_SHORT_NAME="XXHR" MESSAGE_NAME="XXHR_CUSTOM_MESSAGE"</code></span></p></blockquote>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Upload:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; O Y UPLOAD $FND_TOP/patch/115/import/afmdmsg.lct XXHR_CUSTOM_MESSAGE.ldt UPLOAD_MODE=REPLACE CUSTOM_MODE=FORCE</code></span></p></blockquote>
<hr>
<p><span style="text-decoration: underline;"><strong>Concurrent Programs</strong></span></p>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Download:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; O Y DOWNLOAD $FND_TOP/patch/115/import/afcpprog.lct XXHR_CONCURRENT_PROGRAM.ldt PROGRAM APPLICATION_SHORT_NAME="XXHR" CONCURRENT_PROGRAM_NAME="XXHR_CONC_SHORT_NAME"</code></span></p></blockquote>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Upload:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; O Y UPLOAD $FND_TOP/patch/115/import/afcpprog.lct XXHR_CONCURRENT_PROGRAM.ldt UPLOAD_MODE=REPLACE CUSTOM_MODE=FORCE</code></span></p></blockquote>
<hr>
<p><span style="text-decoration: underline;"><strong>Form Functions</strong></span></p>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Download:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; 0 Y DOWNLOAD $FND_TOP/patch/115/import/afsload.lct XXHR_CUSTOM_FUNC.ldt FUNCTION FUNC_APP_SHORT_NAME='XXHR' FUNCTION_NAME='XXHR_CUSTOM_FUNC'</code></span></p></blockquote>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Upload:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; 0 Y UPLOAD $FND_TOP/patch/115/import/afsload.lct XXHR_CUSTOM_FUNC.ldt</code></span></p></blockquote>
<hr>
<p><span style="text-decoration: underline;"><strong>Menus</strong></span></p>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Download:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; O Y DOWNLOAD $FND_TOP/patch/115/import/afsload.lct XXHR_CUSTOM_MENU.ldt MENU MENU_NAME="XXHR_CUSTOM_MENU"</code></span></p></blockquote>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Upload:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; O Y UPLOAD $FND_TOP/patch/115/import/afsload.lct XXHR_CUSTOM_MENU.ldt</code></span></p></blockquote>
<hr>
<p><span style="text-decoration: underline;"><strong>Responsibilities</strong></span></p>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Download:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>FNDLOAD apps/&lt;apps_password&gt; O Y DOWNLOAD $FND_TOP/patch/115/import/afscursp.lct XXHR_CUSTOM_RESP.ldt FND_RESPONSIBILITY RESP_KEY="XXHR_RESP_KEY"</code></span></p></blockquote>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Upload:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; O Y UPLOAD $FND_TOP/patch/115/import/afscursp.lct XXHR_CUSTOM_RESP.ldt</code></span></p></blockquote>
<hr>
<p><span style="text-decoration: underline;"><strong>XML Publisher Data Definitions</strong></span></p>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Download:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; 0 Y DOWNLOAD $XDO_TOP/patch/115/import/xdotmpl.lct XXHR_CUSTOM_REPORT_DATA_DEFINITION.ldt XDO_DS_DEFINITIONS APPLICATION_SHORT_NAME=XXHR DATA_SOURCE_CODE=XXHR_CUSTOM_REPORT_DATA_DEFINITION</code></span></p></blockquote>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Upload:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; O Y UPLOAD $FND_TOP/patch/115/import/afsload.lct XXHR_CUSTOM_REPORT_DATA_DEFINITION.ldt</code></span></p></blockquote>
<hr>
<p><span style="text-decoration: underline;"><strong>Alerts</strong></span></p>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Download:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; 0 Y DOWNLOAD $ALR_TOP/patch/115/import/alr.lct XXHR_CUSTOM_ALERT.ldt ALR_ALERTS APPLICATION_SHORT_NAME=XXHR ALERT_NAME="Custom Alert"</code></span></p></blockquote>
<p style="padding-left: 30px;"><strong><span style="font-size: 10pt;">Upload:</span></strong></p>
<blockquote><p><span style="font-size: 10pt;"><code>$FND_TOP/bin/FNDLOAD apps/&lt;apps_password&gt; 0 Y UPLOAD $ALR_TOP/patch/115/import/alr.lct XXHR_CUSTOM_ALERT.ldt CUSTOM_MODE=FORCE</code></span></p></blockquote>
<p>You can find more information in the documentation provided by oracle:<span style="font-size: 12pt;">&nbsp;<a href="https://docs.oracle.com/cd/E18727_01/doc.121/e12893/T174296T206863.htm">Oracle Documentation</a></span></p>
<p>Happy Migrating.</p>
<p>The post <a href="https://thecurioustechnoid.com/fndload-a-boon-to-ebs-developers/">FNDLOAD &#8211; A Boon to EBS Developers</a> appeared first on <a href="https://thecurioustechnoid.com">The Curious Technoid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://thecurioustechnoid.com/fndload-a-boon-to-ebs-developers/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/

Page Caching using Disk: Enhanced 
Database Caching using Disk (Request-wide modification query)

Served from: thecurioustechnoid.com @ 2026-05-29 18:46:14 by W3 Total Cache
-->