Friday, July 30, 2021

OIC - Resolved - Stage read file in segements - XML-22031 : Error variable not defined.

Scenario:

This is a strange error. I have a orchestrated integration which performs the following:
  • First list the files from s3 directory using sftp
  • Then for each file, it downloads the file and  reads the file reference using stage read in segments. 
  • In the read in segement, we are wrting the line records in the required erp comma separated format. 
  • The downloaded file size is ~21MB.

Observation:

During transformation, we received below error:

Xpath expression failed to execute.

The reason was javax.xml.transform.TransformerException. 

XML-22031 : (Error) Variable not defines for "currFileRef".

Screenshot from OIC: errored in the writeLineRecord stage activity.



Solution: 

This is an Oracle bug. During mapping if any fields are blanks, then this kind of issues can occure. 

Oracle recommended to use a scope in the read file in segemets. Whintin the scope, the writeline stage and mapper will be there.

Screenshot after change:



After this small change, I have tested again with same 21MB source payload and it has magically processed without any error.

Thursday, July 29, 2021

django - POST request and CSRF tokens

lets first know the difference between http get and post. 

HTTP GET :

  • The GET method is the default submission method for a form.
  • The GET method sends the data in the form of URL parameters. Therefore, any data sent with the help of the GET method remains visible in the URL. Since the data is exposed in the URL, the GET method is not considered to send sensitive information such as passwords.
  • The GET method reveals the data in the URL bar; therefore, the length of the URL increases. The maximum length of a URL is 2048 characters, so only a limited amount of data can be sent using the GET method. The following error occurs when we try to send more than 2048 characters using GET :

POST :

  • Data sent by the POST method never gets visible in the URL box, and therefore it is more secure than the GET method, and sensitive information can be sent with the help of this method.
  • Since the data is not visible in the URL query, the length of the URL remains less than 2048 characters, and a large amount of data can be sent with the help of the POST method.
  • Data is sent to the server in the form of packages in a separate communication with the processing script.


Now, we will start our discussion on CSRF tokens.

WHAT ARE CSRF TOKENS?

  • CSRF stands for Cross-Site Request Forgery.
  • The server-side application generates and transmits a huge, random, and unpredictable number to the client to make sure that the request is coming from the original client and not from a malicious website.
  • CSRF tokens are used to protect the site against CSRF attacks.


Use POST:

In the template, here index.html file add the post method in the form.

<form action="/removePunctuation" method="post">

In the views.py, replace all the request.GET.get with the request.POST.get. 

from django.http import HttpResponse
from django.shortcuts import render


def removePunc(request):
# text=request.GET.get('text','default')
text = request.POST.get('text', 'default')
# text = request.POST.get('text', 'default')
check = request.POST.get('removepunc','off')

If you now test from server, you will get the CSRF error:

Test:

Error:

Use CSRF token:

To overcome the CSRF error, add the {% csrf_token%} in the template form

<form action="/removePunctuation" method="post">{% csrf_token %}


Test:

Success page:

Wednesday, July 28, 2021

OIC - callback action

Callback action used to end a process and return to the trigger. 

For instance, if you add a switch activity and define a branch in which you add a callback. If some defined logic is not met, then it moves to this branch and the integration is stopped and the trigger receives a response indicating that the integration is stopped here. 

This action is only valid for delayed or asynchronous integrations.


Lets have a small POC and see:


TBD


OIC - SFTP operations - Move and delete

Generally OIC supports following  5 Ftp operations:

  • Read a file
  • Write a file
  • List Files
  • Delete a file
  • Download a file
Here, I will show you the steps for a POC for move and delete operation.

Steps:

Step1: create an app driven or any other integration and create a rest trigger connection and drag and drop in the integration and configure the following:

Provide a endpoint name
Verb as POST
URI: /
Configure the request payload option

Request payload as Json:

{
"sourceDirectory": "sourceDirectory",
"fileName":"sourceFileName",
"targetDirectory":"target",
"targetFileName":"targetFile",
"moveFileFlag":"Y",
"deleteFileFlag" : "Y"
}

Step2: Take a switch acrivity and mention the condition moveFileFlag="Y" and take a SFTP connection and config the following:

Provide endpoint name: moveFile
Operation: Move a file
Overwrite file option checked.
Next
Done

Map the following :

directory: your source direcrory
fileName: file name
targetDirectory
targetFilename:

Step3: now take again a switch and mention the condition as deleteFileFlag=Y and drop a ftp connection and configure the following:

Provide endpoint name:

Operation : delete a file

Next

Done

Map the following:

directory:

fileName:

Step4: add the tracking, save and activate amd test it with proper data.

Monday, July 26, 2021

OIC - invoke BI control report and store in s3 bucket using rest connection.

Requirement:

Once the inbound file like policy, sub ledger or FAH processed to Oracle ERP, we get a IMPORT REQUEST ID. Based on the import id, we have to fetch the control file details and save it as text file to s3 bucket.

High level Solution steps:

  • Create BI report invoke soap connection and aws S3 rest connection.
  • Invoke the BI report for the control file
  • Decode the response to base64 reference 
  • Take an amazone s3 rest connection and configure to store the  control response to s3.

Detailed Implementation steps:

Create BI report invoke soap connection:

Here we will configure  " ExternalReprtWSSService WSDL URL " which can be used to run a report. The same connection we will use in below steps while developing integration.

  1. Navigate to connection window and select SOAP adapter, give any meaningful name for connection.
  2. Enter the ExternalReportWSSService WSDL URL  and Select the TLS Version. TLS Version depends on your ERP Cloud Application Instance. Mostly it is TLSv1.1WSDL URL Format : https://<your oracle cloud application instance domain>/xmlpserver/services/ExternalReportWSSService?WSDL
  3. Choose Security policy as Username Password token and Enter the *Username and *Password of the Oracle Cloud Application Instance. Click SAVE and TEST the Connection.
Create AWS s3 rest invoke connection:

create a rest S3 connection using  following details:

Connection type: Rest api base url.
Connection URL: https://hostname
Security:  AWS Signature version 4 
Provide access key, secret key, 
AWS region:  like US West(Oregon) Region (us-west-2) 
Service Name: Amazon S3.

Invoke BI report :

Step1: Create a schedule orchestrated integration and specify a schedule parameter like importRequestID.

Step2: Next, drag and drop the BI report soap invoke connection and choose operation as runReport.

Step3: Next, open the mapper and map the following:

reportAbsolutePath: 
sizeOfDataChunkDownload: -1
ParameterNamesValues:
name : "P_IMPORT_REQUEST_ID"
values item: importRequestID.




Decode BI report response to base64 reference:

decodeBase64ToReference(reportBytes)

Invoke AWS s3 rest connection and configure:

Step1: Drag and drop your created AWS s3 rest connection and configure the following:

provide relative url as /{pathAndFileName}, 
verb put ,  
provide request payload as Binary and choose other media type and mention media type as "text/plain".

Step2: In the map, assign the following:

Template param: pathAndFilename : "/rootnode/inbound/poc/ctrl.txt"
Stream reference :  Base64 reference


Thursday, July 22, 2021

OIC - substring a string using index-within-string() function.

Suppose we have a variable which contains a string like "a/b/c/d.txt;name=value" and we need to take the value before the searchstring(;) then that we can achieve following 2 ways:

1. Using substring-before():

substring-before($string,";")

2. Using substring() and index-within-string() functions;

substring($string,1,oraext:index-within-string($string,";")

This function(index-within-string()) returns the zero based index of the first occurance od search string within the input string. The function returns -1 if search string is not found.


OIC - Opaque schema for creating base64Binary file

Opaque_schema.xsd: this will be used in the stage write file adapter configuration.

<?xml version='1.0' encoding='UTF-8'?>

<schema targetNamespace="http://xmlns.oracle.com/pcbpel/adapter/opaque/" xmlns="http://www.w3.org/2001/XMLSchema">

<element name="opaqueElement" type="base64Binary"/>

</schema>


Tuesday, July 20, 2021

OIC - Run a schedule integration now using rest api

Why to run schedule integration now:

  • Creates an ad-hoc integration run for a scheduled integration. This is useful when you want to test you schedule integration.

Relative URI: /ic/api/integration/v1/integrations/{id}/schedule/jobs/

Scenario1: we will create a schedule service accepting few parameters and then run it now from postman tool.

Implementation steps:

Step1: Create a schedule integration and mention the schedule parameters as required. Maximum you can define 5 parameters. Here I have mentioned following 3 params:

p_email : ""

p_fileName : ""

p_reportPath: ""

Step2: add a logger activity and concat 3 these params to show in log testing time. Add tracking and save and activate it.

Step3: open POSTMAN and provide the following details.

Verb : Post

URL: https://oic_instance_hostname:port/ic/api/integration/v1/integrations/{id}/schedule/jobs

Here Id: identifiername|version = POC19_scheduleintegrat|01.00.0000

| = %7C

In authrization tab, add basic authrization and provide username and password.

In Body tab, choose raw type and select JSON and provide the below payload:

{

"action":"NOW",

"parameters": [{

"name": "p_reportPath",

"value": "report_path"

},{

"name": "p_fileName",

"value": "put_filename"

},{

"name": "p_email",

"value": "provide_emailId"

}]

}


Or we can also use following:


{

"runAsSchedule" : false,

"parameters": [{

"name": "p_reportPath",

"value": "report_path"

},{

"name": "p_fileName",

"value": "put_filename"

},{

"name": "p_email",

"value": "provide_emailId"

}]

}

Note: If you mention runAsSchedule : true then the integration should have a active schedule in simple or ical. Otherwise it will fail with:

HTTP 412 Precondition failed.

Can not submit the run as part of the schedule because its not active.


Click on Send button and check from OIC monitoring and check activity stream and you will see the data in logger.


Scenario 2: we will create another intergration and from there we will run the schedule integration now.

Implementation steps:

Step1: Create a schedule integration and mention the schedule parameters as required. Maximum you can define 5 parameters. Here I have mentioned following 3 params:

p_email : ""

p_fileName : ""

p_reportPath: ""

Step2: add a logger activity and concat 3 these params to show in log testing time. Add tracking and save and activate it.

Step3: create a Rest_OIC_Invoke connection with below details:

Role: Trigger and Invoke

Connection Type: Rest API Base URL

Connection URL: https://your_oic_instance_hostname/

Security: Basic Authetication and provide Username and Password.

And test and save it.

Step4: create an app driven integration and choose the created rest connection as trigger point and provide following details:

Endpoint name: callSchedileInt and next

Verb : post

URI: /call

And as we are not passing any params here so not configuring anything just next and save.

Step5: drag and drop the rest connection as invoke point and provide following details:

Verb: post

Relative URI: /ic/api/integration/v1/integrations/{id}/schedule/jobs/

Add  select option -Configure a request payload for this endpoint.

Next

Next

In request section, choose jason sample and click inline and add the following payload:

{

"action":"NOW",

"Parameters": [{

"name": "p_email",

"value": "email"

},{

"name": "p_fileName",

"value": "put_filename"

},{

"name": "p_reportPath",

"value": "yourreportpath"

}]

}

Next

Done

Step6: go to the mapping part and map the following:

Id: POC19_scheduleintegrat|01.00.0000

Action: NOW

Repeat node for parameters 3 times for name value pair:

Name: p_email 

Value: "youremail"

Name: p_fileName

Value: "yourfilename"

Name: p_reportPath

Value: "yourreportpath"

Step7: add tracking and save and activate and test


You can also call schedule integration which does not have any schedule parameters for that you have to use below json payload:

payload:

{

"action":"NOW"

}


OIC - get ESS JOB Status of a ESS import job

Here, I will show you how to get the ESS job status once the import job completed and you have the ess import request id.

Logic: 

we will create a loop and check the ess job status using the import request id whether the ess import job is successful or not(at each loop it will wait 59 sec). 




Follow the below steps:

Step1: Take an assign activity named like setImportLoopVariable and assign the following 2 variables:

I_inProgress : "true"

I_importRequestStatus : ""

Step2: take a while activity and add the following condition.

$I_inProgress = "true"

Step3: Take a wait activity and assign some time to complete the import ESS process lika value 59sec.

Step4: Drag and drop Erp cloud adapter and configure following:

Provide a name: essJobStatus

Select Query, Create, Update or delete information.

Select service: ErpIntegrationService

Operation: getESSJobStatus

Step5: Map the ess import request id to request id of the getEssJobstatus.

Step6: Take a assign named like updateProgress and do the following:

I_inProgress : returnStatus(result of getESSJobStatusResponse)

I_importRequestStatus: result of getESSJobStatusResponse.


Click here how to convert the status to boolean value:

oic-js-return-boolean-status


Saturday, July 17, 2021

OIC - Convert a Scheduled Integration to a REST Adapter-Triggered Orchestration Integration

You can convert a scheduled integration to a REST Adapter-triggered, app driven orchestration integration. This eliminates the need to recreate the integration if you need to change the integration style from scheduled to app driven orchestration.

Restrictions:

  • You cannot convert a scheduled integration to a REST Adapter-triggered integration with multiple verbs.
  • You cannot convert a scheduled integration with assignments that have the fault data type.

Implementation steps:

Step1: In the left navigation pane, click Home > Integrations > Integrations > de activate and Open the scheduled integration you want to convert.

The integration canvas is displayed.

Right-click the schedule icon and select Convert to REST Trigger.



Menu is displayed with selections for Edit Schedule Definition, Edit Integration Properties, View Integration Properties, and Convert to REST Trigger.


Step2: A list of available REST Adapter triggers is displayed > Select the REST Adapter to use as the trigger connection in this integration. > This invokes the Adapter Endpoint Configuration Wizard. Configure the REST Adapter in the wizard.

When wizard configuration is complete, click Done.

A message is displayed.

Clicking done will perform conversion to REST trigger and will clear tracking information, delete any assignment variables with fault data types and update any impacted actions. Errors and warnings may occur which will require manual correction. Are you sure you want to continue?

Review the message, then click Convert.

Step3: A conversion progress bar is displayed. When complete, the converted integration is displayed in the canvas with the REST Adapter trigger connection.

The integration is displayed horizontally. Conversion errors identified by little red circles are displayed on the impacted actions in the integration.

Step4: Investigate any errors and manually correct the impacted actions or invokes. For example, any scheduled parameters in the scheduled integration are deleted during conversion to an app driven orchestrated integration. This results in errors in any actions that reference those schedule parameters (for example, an assign or logger action).

OIC - Why to avoid creating too many scheduled integrations

When there are too many scheduled integrations configured, instances can get backlogged waiting for resources to become available or previous integration runs to complete. This can cause processing delays where some instances are in a waiting state longer than they should be and schedules may not start at the scheduled time.

Best practice:

  • Do not create too many scheduled integrations that are scheduled to run at the same time. 
  • Use an asynchronous REST Adapter trigger instead of a scheduled trigger when an active schedule is not absolutely required.
  • Do not create any long-running scheduled integrations (a scheduled integration that takes longer than one hour, for example, to complete). This blocks scheduler resources impacting other scheduled runs.
  • Spread schedules out over time to avoid schedule clusters.
  • You can convert a scheduled integration to an application-driven orchestrated, REST Adapter trigger-based integration. 

django - adding Bootstrap to django website

What Is Bootstrap?

Bootstrap is a front-end development framework. It is a library of HTML, CSS, and JS, which is used to create modern websites and web applications.

Adding Bootstrap starter template:

Go to the https://getbootstrap.com/ and navigate to docs tab --starter template and copy and paste to index.html page.

Starter template:

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <title>Hello, world!</title>
  </head>
  <body>
    <h1>Hello, world!</h1>

    <!-- Optional JavaScript; choose one of the two! -->

    <!-- Option 1: Bootstrap Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

    <!-- Option 2: Separate Popper and Bootstrap JS -->
    <!--
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
    -->
  </body>
</html>

Adding Navigation Bar :Adding Navigation Bar :
components --navbar
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link active" aria-current="page" href="#">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Link</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            Dropdown
          </a>
          <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
            <li><a class="dropdown-item" href="#">Action</a></li>
            <li><a class="dropdown-item" href="#">Another action</a></li>
            <li><hr class="dropdown-divider"></li>
            <li><a class="dropdown-item" href="#">Something else here</a></li>
          </ul>
        </li>
        <li class="nav-item">
          <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
        </li>
      </ul>
      <form class="d-flex">
        <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
        <button class="btn btn-outline-success" type="submit">Search</button>
      </form>
    </div>
  </div>
</nav>

adding alerts: components--alerts
<div class="alert alert-warning alert-dismissible fade show" role="alert">
  <strong>Holy guacamole!</strong> You should check in on some of those fields below.
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
Adding Text Area :
Copy and paste the code given below to add text area:

 <div class="form-group">
    <label for="exampleFormControlTextarea1">Enter your text here and let Text Utils do the magic</label>
    <textarea class="form-control" name='text' id="exampleFormControlTextarea1" rows="9"></textarea>
  </div>
 Adding Switches :
Copy the below code and paste in the index.html file.

<div class="custom-control custom-switch">
  <input type="checkbox" name="removepunc" class="custom-control-input" id="customSwitch1">
  <label class="custom-control-label" for="customSwitch1">Remove Punctuations</label>
</div>

Adding Analyze Text Button :
Type the code given below to add the analyze text button :

<button type="submit" class="btn btn-dark mt-2">Analyze Text</button>
After successfully adding buttons and switches, add action attribute in the form tag. Write the following code :

<form action='/removepunc' method='get'>

Adding Bootstrap To analyze.html:
Copy the below code and paste it in analyze.html file : 
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">

<title>Text Utils</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">TextUtils.in</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About Us</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact Us</a>
</li>

</ul>
</div>
<form class="form-inline">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</nav>


<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>Success!Your Text Has Been Analyzed</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>


<div class="container mt-5">
<h1>Your Analyzed Text -- {{purpose}}</h1>
<p>
{{ analyzed_text}}
</p>
</div>


<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
</body>
</html>

views.py code:

from django.http import HttpResponse
from django.shortcuts import render

def removePunc(request):
text=request.GET.get('text','default')
check=request.GET.get('removepunc','off')
if check == "on":
puncList= '''!()-[]{};:'"\,<>./?@#$%^&*_~'''
newText=''
for char in text:
if char not in puncList:
newText=newText + char

param= {"purpose": "Text after removed punctuation","analyzed_text": newText}
return render(request,'analyze.html',param)

# return HttpResponse(newText)

else:
param = {"purpose": "No Changes", "analyzed_text": text}
return render(request, 'analyze.html', param)
# return HttpResponse(text)
def navigationBar(request):
return render(request, 'navigationUrls.html')
def index(request):
# return HttpResponse("Hello")
return render(request,'index.html')

def about(request):
return HttpResponse("<h1>about</h1>")
def textAnalyze(request):
ttext = request.GET.get('text','default')
print(ttext)
return HttpResponse(ttext)
index.html:
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<title>Text Analyzer</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>Welcome to Text Analyzer</strong> You can analyze your text here.
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<form action="/removePunctuation" methlod="get">
<div class="form-group">
<label for="exampleFormControlTextarea1">Enter your text here and let Text Utils do the magic</label>
<textarea class="form-control" name='text' id="exampleFormControlTextarea1" rows="9"></textarea>
</div>
<div class="custom-control custom-switch">
<input type="checkbox" name="removepunc" class="custom-control-input" id="customSwitch1">
<label class="custom-control-label" for="customSwitch1">Remove Punctuations</label>
</div>
<button type="submit" class="btn btn-dark mt-2">Analyze Text</button>
</form>


<!-- Optional JavaScript; choose one of the two! -->

<!-- Option 1: Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

<!-- Option 2: Separate Popper and Bootstrap JS -->
<!--
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
-->
</body>
</html>

website:




Featured Post

11g to 12c OSB projects migration points

1. Export 11g OSB code and import in 12c Jdeveloper. Steps to import OSB project in Jdeveloper:   File⇾Import⇾Service Bus Resources⇾ Se...