My database is 19c ATP and I want to call a Rest API using PLSQL using Apex_Web_Service or UTL_Http but struggling to understand how to do so.
Below is the URL I am successfully able to call with Postman and can see the response but the same is not working well in PLSQL.
https://ta38.ocs.oraclecloud.com/test2/wms/lgfapi/v10/entity/inventory_history?company_id__code=INFOSYS&facility_id__code=NCO&history_activity_id=17&status_id=90
Maybe I am calling it incorrectly so requesting you to help me call the above correctly in PLSQL.
It always asks the value of facility_id__code as it has "&" sign in the URL.
DECLARE
p_content CLOB;
BEGIN
p_content := apex_web_service.make_rest_request (
p_url => 'https://ta38.wms.ocs.oraclecloud.com/cummins_test2/wms/lgfapi/v10/entity/inventory_history?company_id__code=CUMMINS&facility_id__code=NCO&history_activity_id=17&status_id=90'
, p_http_method => 'GET'
, p_username => 'TEST'
, p_password => 'WELCOME'
) ;
END;
Related
My Oracle Database cannot currently handle TLS 1.2 needed to communicate with Office 365 for mail. So I am using an old mail server to send out my mail because it does not need authentication and is located on premise. For internal communication I need to alter all "to" addresses to change the domain so the mail is sent to Microsoft and not back to the internal mail server.
Example: I need to change all emails from user#domain.com to user#domain.onmicrosoft.com. Is there a way I can alter the APEX_MAIL package in Oracle so that any use of domain.com in the "TO" field will automatically change to domain.onmicrosoft.com?
Typically you don't change a proprietary package - even if you could, it would be wrong. Instead you wrap your own pl/sql procedure around apex_mail. Create a package with the same signature as the apex_mail procedures you are using and within those procedures invoke apex_mail. Before the call to apex_mail, do whatever magic you need (change the email adresses in your case). The only downside is that you cannot use this in processes of type "send email" - you'll have to use pl/sql.
Here is an example of a procedure:
PROCEDURE send (
mail_to_i IN VARCHAR2,
mail_from_i IN VARCHAR2,
mail_reply_to_i IN VARCHAR2,
mail_body_i IN VARCHAR2,
mail_body_html_i IN VARCHAR2 DEFAULT NULL,
mail_subject_i IN VARCHAR2 DEFAULT NULL,
mail_cc_i IN VARCHAR2 DEFAULT NULL,
mail_bcc_i IN VARCHAR2 DEFAULT NULL
)
IS
l_mail_to VARCHAR2(4000) := NULL;
l_mail_cc VARCHAR2(4000) := NULL;
l_mail_bcc VARCHAR2(4000) := NULL;
BEGIN
l_mail_to := REPLACE (LOWER(mail_to_i),'#domain.com','#domain.onmicrosoft.com');
-- do other substitutions if needed
apex_mail.send
(
p_to => l_mail_to,
p_from => mail_from_i,
p_cc => mail_cc_i,
p_subj => mail_subject_i,
p_body => mail_body_i,
p_body_html => mail_body_html_i,
p_replyto => mail_reply_to_i,
p_bcc => mail_bcc_i
);
END send;
You cannot and should not modify the APEX_MAIL package. You should modify the process that is calling the APEX_MAIL package to do any replacements if necessary or just validate the input of the email addresses so they are what you expect.
If you have emails that have already been added to apex_mail_queue and have errored, you can update apex_190200.wwv_flow_mail_queue (or whatever the proper APEX schema is for your environment) to correct the addresses in the MAIL_TO column. You will also need to reset mail_send_count and mail_send_error so that it is processed next time emails are attempted to be sent.
UPDATE apex_190200.wwv_flow_mail_queue
SET mail_to = 'some.email#domain.onmicrosoft.com', mail_send_count = 0, mail_send_error = NULL;
I am working with a temporary Oracle Cloud account. What I thought was identical functionality works on the Apex Web Service, but not with UTL_HTTP. So this snippet works and returns the issue we are looking for.
DECLARE
L_json_response varchar2(32767);
BEGIN
apex_web_service.g_request_headers(1).name := 'Content-Type';
apex_web_service.g_request_headers(1).Value := 'application/json';
L_json_response := apex_web_service.make_rest_request ( p_url =>
'https://mycompany.atlassian.net/rest/api/3/issue/BLABLA-23862', p_http_method => 'GET',
p_username => 'My.Username#mycompany', p_password => 'osBJWHhPasdffNVOQ5AA11D5'); -- Password is my Jira API Token
EXCEPTION WHEN OTHERS THEN raise_application_error(-20001,'An error was encountered -
'||SQLCODE||' -ERROR- '||SQLERRM);
END;
I can't use the Apex web service in the end product, and we need to use UTL_HTTP. This snippet should from my understanding do the same:
DECLARE
req utl_http.req;
res utl_http.resp;
url varchar2(4000) := 'https://mycompany.atlassian.net/rest/api/3/issue/BLABLA-23862';
buffer varchar2(4000);
BEGIN
req := utl_http.begin_request(url, 'GET');
utl_http.set_header(req, 'Content-Type', 'application/json');
utl_http.set_header(req, 'Authorization', 'Basic ' || utl_encode.base64_encode('my.msername#mycompany:osBJWHhPasdffNVOQ5AA11D5'));
res := utl_http.get_response(req);
utl_http.read_text(res, buffer);
END;
But returns:
ORA-29273: HTTP request failed
ORA-29024: Certificate validation failure
ORA-06512: at "SYS.UTL_HTTP", line 639
ORA-06512: at "SYS.UTL_HTTP", line 1415 ORA-06512...
The key is the UTL_HTTP.SET_WALLET('');. You need to set the wallet(with empty string parameter) before initial http request.
The following code snippet tested with in Oracle Cloud ATP (Autonomous Transition Processing) database:
Setup network ACL
BEGIN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(acl => 'my_acl.xml',
description => 'ACL for http request.',
principal => 'MY_USER',
is_grant => true,
privilege => 'connect');
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(acl => 'my_acl.xml',
principal => 'MY_USER',
is_grant => true,
privilege => 'resolve');
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(acl => 'my_acl.xml', host => 'www.oracle.com');
END;
Test https request
DECLARE
l_text VARCHAR2(32767);
BEGIN
UTL_HTTP.SET_WALLET('');
l_text := UTL_HTTP.REQUEST('https://www.oracle.com/index.html');
dbms_output.put_line(l_text);
END;
See official document and example (on the bottom of page):
In a way #OldProgrammer answered this the comment from 29-12-2020m but I don't know how to attribute the answer.
I needed to either couple the UTL_HTTP code to default wallet or create a new one. APEX_WEB_SERVICE probably does this implicitly while UTL_HTTP has to have it spelled out.
My question was for Oracle Cloud and I couldn't make the toolchain from OldProgrammers link work in Oracle Cloud. Rolled out a VM and it works.
Hey Guys I need Help How to send EMAIL Automatically in oracle APEX, I know some using DBMS_SCHEDULER we can achieve it, I have no idea how to do it where to start any suggestion, Along with that i want to attach a report. COuld you help me?
Can you Suggestest any blog?
Thank You in Advance.......
This blog is a good place to start: https://blogs.oracle.com/apex/creating-email-campaign-app-with-oracle-apex
The code below as long as the owner of the job is a schema that has been provisioned for the APEX workspace, or the schema has been granted the role APEX_ADMINISTRATOR_ROLE. You will need to substitute 100 for your actual application number and 1 with an actual page in that application. The third parameter is the username and can be anything.
DECLARE
l_mail_id NUMBER;
BEGIN
apex_session.create_session (100, 1, 'send_email');
l_mail_id :=
apex_mail.send (p_to => 'youremail#gmail.com',
p_from => 'nobody#test.com',
p_body => 'plaintext body',
p_body_html => '<h1>HTML Body</h1>',
p_subj => 'Test Email Subject');
apex_mail.add_attachment (p_mail_id => l_mail_id,
p_attachment => EMPTY_BLOB (),
p_filename => 'attachment_name.json',
p_mime_type => 'application/json');
apex_mail.push_queue;
apex_session.delete_session;
END;
/
I created a Concurrent Program that creates an Excel File from a long, parametrized query using PL/SQL.
Once the Program successfully completes, the file is placed in the remote server's directory and is usually around 4 MB in Size.
I'm thinking of an approach to notify the requestor and enable him/her to save the file to their local directory.
However, I cannot use UTL_MAIL to attach and send the file via email due to the 32 Kilobyte Limitation. (Does UTL_MAIL have an attachment limit of 32k).
In the same post, Tom Kyte preferred approach would be to:
store the attachment to the database.
email a very small email with a link. the link points to my database - using a URL.
With that, i was thinking taking the same approach and use the block below to notify the requestor and enable him/her to download the said Excel file:
declare
l_url_link varchar2(100); -- how can i get the URL of the File?
BEGIN
UTL_MAIL.SEND(sender => 'xxx#oracle.com'
, recipients => 'Migs.Isip.23#Gmail.com'
, subject => 'Testmail'
, message => 'Your File is Ready to be downloaded, click the link here: '||l_url_link);
END;
My Questions would be:
How can i generate the "URL" of the Remote file using PL/SQL?
Do the users need to be granted access to the remote server to download the file?
Thank you!
Oracle Database Version:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
"CORE 11.2.0.4.0 Production"
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
Here is a pl/sql function I wrote to retrieve the URL of either the concurrent log file or output file. If you write your Excel file to the concurrent output, this should work fine. Let me know how you get on. I have not checked to see if this will give the correct mime-type or extension - not sure how EBS handles this but the function itself will definitely compile as is for 12.1.3.
Spec
FUNCTION get_concurrent_url (p_file_type IN VARCHAR2
,p_request_id IN NUMBER
,p_expiry IN NUMBER)
RETURN VARCHAR2;
Body
/* Get a URL to view the log/output
File Type is LOG or OUT
Request ID is the concurrent request ID
Expiry is in minutes */
FUNCTION get_concurrent_url (p_file_type IN VARCHAR2
,p_request_id IN NUMBER
,p_expiry IN NUMBER)
RETURN VARCHAR2
IS
CURSOR c_gwyuid
IS
SELECT profile_option_value
FROM fnd_profile_options FPO
,fnd_profile_option_values FPOV
WHERE FPO.profile_option_name = 'GWYUID'
AND FPO.application_id = FPOV.application_id
AND FPO.profile_option_id = FPOV.profile_option_id;
CURSOR c_two_task
IS
SELECT profile_option_value
FROM fnd_profile_options FPO
,fnd_profile_option_values FPOV
WHERE FPO.profile_option_name = 'TWO_TASK'
AND FPO.application_id = FPOV.application_id
AND FPO.profile_option_id = FPOV.profile_option_id;
l_request_id NUMBER;
l_file_type VARCHAR2 (3 BYTE);
l_expiry NUMBER;
l_two_task VARCHAR2 (100 BYTE);
l_gwyuid VARCHAR2 (100 BYTE);
l_url VARCHAR2 (1024 BYTE);
BEGIN
l_request_id := p_request_id;
l_file_type := p_file_type;
l_expiry := p_expiry;
FOR i IN c_gwyuid LOOP
l_gwyuid := i.profile_option_value;
END LOOP;
FOR i IN c_two_task LOOP
l_two_task := i.profile_option_value;
END LOOP;
IF l_file_type = 'LOG' THEN
l_url := fnd_webfile.get_url
(file_type => fnd_webfile.request_log
,id => l_request_id
,gwyuid => l_gwyuid
,two_task => l_two_task
,expire_time => l_expiry);
ELSE
l_url := fnd_webfile.get_url
(file_type => fnd_webfile.request_out
,id => l_request_id
,gwyuid => l_gwyuid
,two_task => l_two_task
,expire_time => l_expiry);
END IF;
RETURN l_url;
END get_concurrent_url;
I was able to find a solution for this using a (slightly different) method using the FND_GFM File Uploader Package in Oracle EBS.
FND_GFM is a package usually used in Oracle EBS when uploading files from the front-end application pages.
First, generate the Excel file (xlsx) using the code from the previous post: Create an Excel File (.xlsx) using PL/SQL,
Then the file is inserted into FND_LOBS and removed the from the OS (for good housekeeping), and finally sent as an email using UTL_FILE:
procedure generate_and_send_excel
is
l_content varchar2(250);
l_file_url varchar2(4000);
l_directory varchar2(250);
l_filename varchar2(250);
l_message clob;
l_instance varchar2(100);
l_ebs_url varchar2(100);
begin
/* your excel generation code here */
l_content := 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
l_directory := 'EXT_TAB_DATA';
l_filename := 'report.xlsx';
select instance_name
into l_instance
from v$instance;
select home_url
into l_ebs_url
from icx_parameters;
IMPORT_TO_LOB (p_file_name => l_filename -- this is the actual filename of the saved OS File
, p_directory => l_directory -- should be a defined directory in the Database
, p_content_type => l_content -- standard for Excel Files
, p_program_name => 'your prog here'
, p_program_tag => 'your prog here'
, p_file_url => l_file_url); -- this will be the generated URL of your File
utl_file.fremove(l_directory, l_filename);
l_message := l_message||'<h2 style="color: #5e9ca0;">'||l_title||'</h2>';
l_message := l_message||'<h3 style="color: #2e6c80;">Report is Ready for Download: '||l_filename||'</h3>';
l_message := l_message||'<p>File was generated on '|| sysdate ||' from '||l_instance||'</p>';
l_message := l_message||'<strong>Regards,</strong><br/><strong>Sample Team</strong>';
l_message := l_message||'<br/>Sample#sample.com';
UTL_MAIL.SEND(sender => 'SAMPLE#SAMPLE.com'
, recipients => 'Migs.Isip.23#gmail.com'
, subject => 'Hello message'
, message => l_message
, mime_type => 'text/html; charset=us-ascii');
end generate_and_send_excel;
Procedure below to insert into FND_LOBS (there's no available seeded API):
Procedure IMPORT_TO_LOB (p_file_name IN FND_LOBS.FILE_NAME%TYPE
, p_directory IN dba_directories.directory_name%type
, p_content_type IN FND_LOBS.file_content_type%type
, p_program_name IN FND_LOBS.program_name%type
, p_program_tag IN FND_LOBS.program_tag%type
, p_language IN FND_LOBS.language%type default 'US'
, p_file_format IN FND_LOBS.file_format%type default 'binary'
, p_file_url OUT varchar2)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
lBlob BLOB;
lFile BFILE := BFILENAME(p_directory, p_file_name);
L_ORA_CHARSET VARCHAR2(100);
P_COUNT NUMBER;
BEGIN
SELECT value
into l_ora_charset
FROM nls_database_parameters
where parameter = 'NLS_CHARACTERSET';
insert into FND_LOBS
(
file_id
, file_name
, file_content_type
, file_data
, upload_date
, expiration_date
, program_name
, program_tag
, LANGUAGE
, oracle_charset
, file_format
)
values
(
fnd_lobs_s.NEXTVAL -- FILE_ID
, p_file_name -- FILE_NAME
, p_content_type -- FILE_CONTENT_TYPE
, EMPTY_BLOB() -- FILE_DATA
, sysdate -- UPLOAD_DATE
, NULL -- EXPIRATION_DATE
, p_program_name -- PROGRAM_NAME
, p_program_tag -- PROGRAM_TAG
, p_language -- LANGUAGE
, l_ora_charset -- ORACLE_CHARSET
, p_file_format -- FILE_FORMAT
)
RETURNING file_data INTO lBlob;
DBMS_LOB.OPEN(lFile, DBMS_LOB.LOB_READONLY);
DBMS_LOB.OPEN(lBlob, DBMS_LOB.LOB_READWRITE);
DBMS_LOB.LOADFROMFILE(DEST_LOB => lBlob,
SRC_LOB => lFile,
AMOUNT => DBMS_LOB.GETLENGTH(lFile));
DBMS_LOB.CLOSE(lFile);
DBMS_LOB.CLOSE(lBlob);
commit;
p_file_url := fnd_gfm.construct_download_url (fnd_web_config.gfm_agent, fnd_lobs_s.currval);
END IMPORT_TO_LOB;
Note that this is an AUTONOMOUS_TRANSACTION so it needs to be committed before returning to the calling package/block.
Hope that Helps!
I want to redirect the post login page to a change login page.
I have a custom authentication schema which call user_mng.authenticate as authentication function.
function authenticate(p_username in VARCHAR2, p_password in VARCHAR2) RETURN BOOLEAN IS
ntype int;
pwobf varchar2(100);
BEGIN
pwobf:=obfuscate(nvl(p_password,'**'));
select user_role
into ntype
from( select 1 user_role
from view_users
where upper(user_id)=upper(p_username)
and password=p_password
union all
select 2 user_role
from view_users
where upper(user_id)=upper(p_username)
and password=pwobf);
apex_util.set_authentication_result(0);
RETURN TRUE;
exception when no_data_found then
apex_util.set_authentication_result(1);
return false;
END authenticate;
you can find below a printscreen of the login page
http://gyazo.com/10dc90b9e271ae11fadfa48201665a3d.png
The login page is pretty much the one automatically created by APEX where in the post submit LOGIN process I have added
begin APEX_CUSTOM_AUTH.LOGIN (
p_uname => :P101_USERNAME,
p_password => :P101_PASSWORD,
p_session_id => V('APP_SESSION'),
p_app_page => :APP_ID||':18');end;
where page 18 is my target page while 1 is the home page.
I don't know why, most of the time the page is sent to the home... I haven't be able to relate to any other condition but from time to time it goes to the change login page. If in the p_app_page => :APP_ID||':18' I set an invalid page a receive an error (the page is being read) as well if I set an invalid password (the auth. process is working) during the login.
I've tried to clean browser cache... but it does not appear to have any effect.
I'm using Apex 4.2.4 with Tomcat 7.
I would deeply appreciate any help.
Regards
the villain is the deep link. Solved as follows
declare
vpg varchar2(10):=':1';
begin
APEX_UTIL.SET_SESSION_STATE('FSP_AFTER_LOGIN_URL');
IF user_mng.need_psw_rst(:P101_USERNAME) then
vpg:=':18';
end if;
APEX_CUSTOM_AUTH.LOGIN (
P_UNAME => :P101_USERNAME,
P_PASSWORD => :P101_PASSWORD,
P_SESSION_ID => v('APP_SESSION'),
p_app_page => :APP_ID||vpg
);
end;