ODTUG Aggregator ODTUG Blogs http://localhost:8080 Wed, 21 Nov 2018 09:44:54 +0000 http://aggrssgator.com/ How do I add an image to a page in Oracle APEX? https://joelkallman.blogspot.com/2018/11/how-do-i-add-image-to-page-in-oracle.html <i>Preface:&nbsp; Many blog posts about Oracle APEX seem to cover a new feature or something rather obtuse &amp; complex.&nbsp; The sophisticated blog posts have little relevance to someone who is completely new to APEX and Oracle Database.&nbsp; Having worked with APEX since 1999, it's always difficult for me to put myself in the shoes of a brand new student of APEX.&nbsp; When I interact with people new to APEX, I try to look at APEX through their eyes, and listen to what they find confusing.&nbsp; Sometimes, it's completely obvious to me and, at the same time, completely vexing to them.&nbsp; Thus, this will begin a series of blog posts how to perform very common tasks in APEX.&nbsp; It will be boring for the experienced user, but hopefully helpful to the APEX developer in training.&nbsp; And separately, we will also strive to make APEX simpler and easier to understand, so that blog posts like this one become unnecessary&nbsp;in the future.</i><br /><br /><br /><br /><a href="https://twitter.com/geraldvenzl" target="_blank">Gerald Venzl</a>, a highly respected <a href="https://www.oracle.com/database/index.html" target="_blank">Oracle Database</a> product manager, was recently participating in a hackathon with a team of people, and they were using <a href="https://apex.oracle.com/" target="_blank">Oracle APEX</a> as part of their solution.&nbsp; They produced a <a href="https://en.wikipedia.org/wiki/QR_code" target="_blank">QR code</a> for the URL to their app, they saved this QR code image to a local file, and they wanted to include the image on a page in their APEX application.&nbsp; As Gerald stated, it took more than 30 minutes for this learned and competent group of people to figure out how to do this.&nbsp; This is not a criticism of Gerald and his colleagues, it's a criticism of APEX.&nbsp; Gerald and his team were expecting a simple upload to a page item of type Image and they would be done, right?&nbsp; Well, not so simple.<br /><br />This blog post is not intended to cover the case where you have images in BLOB columns in a database table (we'll cover that in the future), or the case where the image can already be referenced via a URL.&nbsp; I am presenting the simple case of you having an image on the file system on your local computer, and you want to reference it in your APEX page.<br /><br />From a high-level, the steps are:<br /><ol><li>Upload the file as a static application file.</li><li>Using the HTML <a href="https://www.w3schools.com/tags/tag_img.asp" target="_blank">IMG tag</a>, reference the static application file in your application.</li></ol><br /><br />Now, for the more detailed explanation.<br /><br />Before you can reference an image in your APEX application, it has to be in a location which can be "served" by your Web server.&nbsp; With APEX, you have access to the back-end Oracle Database, but you don't have access to the Web server file system.&nbsp; Fortunately, there is an easy way to upload the image into the Oracle Database and have it served by your Web server when used within an APEX application.&nbsp; These are called Static Application Files.<br /><br />The steps are really quite simple:<br /><ol><li>Edit your application in the Application Builder</li><li>Click <b>Shared Components</b></li><li>Click <b>Static Application Files</b></li><li>Click <b>Upload File</b></li><li>Choose the file from your local computer</li><li>Click the <b>Upload</b> button</li></ol><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-30tK7rhoJo0/W-Wkkamx1kI/AAAAAAAADtU/uLHGPs-qYV8Glxt0cW5TWjcDc3ZJwwLXACLcBGAs/s1600/FileUploaded.png" imageanchor="1"><img border="0" data-original-height="533" data-original-width="1065" height="320" src="https://3.bp.blogspot.com/-30tK7rhoJo0/W-Wkkamx1kI/AAAAAAAADtU/uLHGPs-qYV8Glxt0cW5TWjcDc3ZJwwLXACLcBGAs/s640/FileUploaded.png" width="640" /></a></div><br /><br />In the picture above, this is the list of Static Application Files in the APEX Application Builder, after uploading file Three_Stooges.jpg.&nbsp; Under the Reference column, there is the string&nbsp;<i>#APP_IMAGES#Three_Stooges.jpg</i>.&nbsp; This is how you can reference the file when used in an HTML context in your APEX application.&nbsp; This reference means <b>nothing</b>&nbsp;when used outside of an APEX application.&nbsp; When someone is running your application, the APEX engine will replace the substitution string <i>#APP_IMAGES#</i> with an absolute URL reference to an embedded REST endpoint which will return the stored image.<br /><br />To reference this image in your application, you just need to include a reference to it from an HTML IMG tag on your APEX page.&nbsp; This image reference would have to be entered into the attributes of your APEX application wherever it's appropriate to embed HTML.&nbsp; This includes the headers and footers of page regions, templates, and even the Source attribute of certain region types.&nbsp; An easy way to get started is to reference an image in a region of type <i>Static Content</i>.<br /><br />As an example, edit a page in Page Designer.&nbsp; In the gallery at the bottom of the page, drag a region of type <i>Static Content</i> onto your page.&nbsp; In the Source attribute of this region, enter the HTML string to reference the image:<br /><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>&lt;img src="#APP_IMAGES#Three_Stooges.jpg"&gt;</b></span><br /><br />Obviously, reference your file and not the name of the file in my example (<i>Three_Stooges.jpg</i>).&nbsp; Save your page and run.&nbsp; That's all there is to it!<br /><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-aSBe9VDxc0k/W-XtfF0YR7I/AAAAAAAADts/ngBFpG361hgDRTBX-qCNlvj6IbMTTjzFgCLcBGAs/s1600/Blog_Image2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="498" data-original-width="535" src="https://2.bp.blogspot.com/-aSBe9VDxc0k/W-XtfF0YR7I/AAAAAAAADts/ngBFpG361hgDRTBX-qCNlvj6IbMTTjzFgCLcBGAs/s1600/Blog_Image2.gif" /></a></div><div class="separator" style="clear: both; text-align: center;"></div><br /><br /><br /><br />One last point.&nbsp; If you <b>do</b> have access to the web server file system, and you wish to include static file references in your application, then definitely put them on your web server file system and simply serve them from there.&nbsp; It will always be more efficient to have these served by a web server instead of having to fetch them out of the database. Joel R. Kallman tag:blogger.com,1999:blog-12214002.post-5279723043778719903 Fri Nov 09 2018 15:04:00 GMT-0500 (EST) Advantages of Modernizing Oracle Forms with APEX https://insum.ca/advantages-of-modernizing-oracle-forms-with-apex/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/11/Advantages-of-Modernizing-Oracle-Forms-with-APEX-100x100.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Advantages of Modernizing Oracle Forms with APEX" srcset="https://insum.ca/wp-content/uploads/2018/11/Advantages-of-Modernizing-Oracle-Forms-with-APEX-100x100.jpg 100w, https://insum.ca/wp-content/uploads/2018/11/Advantages-of-Modernizing-Oracle-Forms-with-APEX-150x150.jpg 150w, https://insum.ca/wp-content/uploads/2018/11/Advantages-of-Modernizing-Oracle-Forms-with-APEX-600x600.jpg 600w, https://insum.ca/wp-content/uploads/2018/11/Advantages-of-Modernizing-Oracle-Forms-with-APEX-300x300.jpg 300w, https://insum.ca/wp-content/uploads/2018/11/Advantages-of-Modernizing-Oracle-Forms-with-APEX-50x50.jpg 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p>In my previous blog (<a href="https://insum.ca/oracle-forms-apex-similarities/">2 of 4 in this series</a>) I explained how similar the web-based development platform called Oracle APEX is to Oracle Forms. These similarities give your Forms developers the confidence and efficiency that come with working in familiar territory.  This brings me to the business advantages of modernizing Oracle Forms with APEX.</p> <h2>Oracle APEX is a Bridge to New Technologies</h2> <p>APEX is like a bridge that allows Forms developers and Web developers to meet and collaborate. More importantly, they can be productive together to achieve your business goals. Before, your Forms developers worked in a world of their own. Now, switching over to the hybrid PL/SQL-Web-based declarative environment which is APEX, they can collaborate with Web UI and Web UX specialists. They also get to leverage an array of new tools, as well as take advantage of web services.  What&#8217;s more, other specialized resources such as JavaScript developers can collaborate in APEX as well, needing only the most basic knowledge of the platform to integrate their work.</p> <p>From a business perspective, this means that any of your internal IT/development resources can now team up more closely with your Forms and Reports resources. Together they can quickly move forward with development plans and modernization, creating new functionalities and new applications.</p> <h2>Oracle APEX is Quick to Learn</h2> <p>Your team can start learning Oracle APEX today. I strongly recommend your developers download the latest version of Oracle APEX <a href="https://apex.oracle.com/en/">here</a>. They&#8217;ll get the hang of it in no time.  Once they learn the basic functions they can quickly create applications that are productive and secure. APEX is so simple to learn, you may even choose to get some of your users to work with it. Your dev team can declaritively add functions such as sorting, Excel extractions, PDF creation, file uploads, integration with Web services and interactive reports, just to name a few.  Using APEX&#8217;s Create Page Wizard, end users can quickly create Dashboards, Adhoc reports and also import Excel data.</p> <p>In other programming languages, developers must build such functions themselves, basically from scratch. The beauty of this approach is that since APEX is a Rapid Application Development Platform, it isn&#8217;t necessary to be familiar with the inner workings of web applications. On the contrary, these organize themselves &#8220;behind the scenes&#8221; as applications are built. to add to this efficiency, APEX generates recurrent code. This is useful for building applications quickly and improving overall performance. It also has the advantage of being genuine Oracle code, optimized for the database. After all, APEX is built by Oracle employees! APEX builds as much code as possible to be reusable. Oracle fully supports APEX, so any code produced interacts seamlessly with the Oracle database.</p> <h2>Start Simple, Small and Manageable</h2> <p>You&#8217;ll want your development team to start with something simple. For example, create a dashboard, an interactive report or a simple form. When working on modernizing your existing applications, I would recommend proceeding by segments or modules, in phases, a little bit at a time. This way you aren’t throwing large amounts of money at a project with a rollout that is 2 or 3 years away. Working in phases means the code and the applications will be more easily evaluated. You&#8217;ll see tangible results within weeks. Costs will remain under control.</p> <h2>APEX Can Quickly Take the Work To an Expert Level</h2> <p>Of course, APEX also allows experienced developers to go much further down the road of customization. They can add more sophisticated elements, create a deeper integration with their JavaScript, at various levels. for example, they can use existing plug-ins or even create their own. These Deeper integrations can include Single Sign-On (SSO) capability and advanced security features.</p> <h2>Just starting out? Consult with Experts</h2> <p>If you are just starting out with APEX, we recommend <a href="https://insum.ca/contact/">contacting experienced APEX experts</a>, who can train and guide you throughout the adoption process. Also, a major advantage of APEX over other application development platforms is its community of developers. The APEX community, primarily found on Twitter under <a href="https://twitter.com/hashtag/orclapex">#orclapex</a> is enthusiastic and responsive. The spirit of collaboration that you&#8217;ll find among its members is like an extension APEX&#8217;s open and collaborative nature. Its unbiased support is a tangible business advantage that your developers can tap into at any time. Finally, a quick search on <a href="https://apex.oracle.com/en/community/events/">Oracle APEX&#8217;s events page</a> will provide a host of opportunities to meet and learn from active APEX developers from the world over.</p> <p>The business advantage is this: there is no big bang. It&#8217;s a controlled Roll-out. Long-term plans and actions can be sequenced over several months, or even years.  Budget and investments can be easily managed. You can manage the rhythm and phases of the project.</p> <h2>Change management is key to Forms Modernization</h2> <p>It&#8217;s important to mention: If you want to be successful in your Forms modernization, be prepared to pay careful attention to change management. This is, after all, a change of paradigm: from client-server, to web.  I&#8217;ve found that almost any time such changes cause problems, the source can be traced back to issues with change management. such issues can occur at all levels: with the development team, the users, or upper management.</p> <h2>Lack of Adoption Means Trouble</h2> <p>When it comes to user adoption, you can’t come up to people and tell them “here is a new application, use this instead”. No matter how slick and effective the application, people will challenge it. They’ll try to prove that the new way of doing things is less efficient than what they were doing before.  There is some truth to that.  Up until that point, the old way is more efficient because your users are too upset with this new thing being forced upon them. This lack of adoption forces you into a cycle of making changes to keep the users happy, which will almost certainly include re-creating exactcly what they had before. This isn’t an efficient path for your users, nor will it satisfy the business needs being addressed.</p> <h2>Involve Users from the Start</h2> <p>Rather, you should involve your users in the project from the beginning. Train them on what a web interface is like and how it works. Train them on how to get the most out of an interactive report. Give examples.  Show them that the Web is a different environment, yes, but a more productive one too. You can make parallels between this system and their internet banking or other web-based systems in the company. It is a road your users must travel down. You can’t just plop them down at the arrival point and expect them to understand why things are so different.</p> <p>Involve your users in the creation process. Get their opinion on the user interfaces while you are building them. Involve in your analysis and your approach.  Perhaps they are used to shortcuts and they don’t like to click a couple more times to get to the same data. Then show them what they are getting in the trade-off. More dynamism, more direct and real-time access to the data, Reports that can be customized on the fly, so much more quickly than before. Shortcut keys are great but overall productivity involves much more than that.</p> <p>We use an agile approach to quickly come up with concrete deliverables (“low hanging fruit”). Quick wins that are small in scale but that useful to the business and convincing. Once people see the value in a new way, they will want to continue down the path of change.</p> <h2>Don&#8217;t try and reproduce what was there before</h2> <p>The biggest error that companies still make when transferring to new technology (in this case from client-server to web technology) is trying to reproduce exactly what they had before. This can greatly complexify maintenance and development, which will nullify your gains in speed and flexibility. This is the most important aspect of Modernization: The approach must be from the standpoint of the business need, not technical needs.</p> <p>Once the changes you are making gain acceptance change management becomes much easier. User enthusiasm and engagement is just as important as creating a process that makes them efficient. You’ll notice that the less experienced younger users will adapt more quickly than the older, more experienced users who’ve been using the system for years.</p> <p>Involving users makes them feel like their opinions are important (because they are) and can even allow you and your users to come up with solutions that had never been considered.</p> <h2>Conclusion</h2> <p>From a technical standpoint, APEX is exceptionally well-adapted to bringing your Forms applications into the 21<sup>st</sup> century. However, if you don’t handle change management properly, all this is for nothing. To be frank, we’ve never encountered a technical problem we couldn’t solve. Virtually all the problems we’ve faced have concerned people’s ability to adapt to a new way of doing things. This is why change management is so important.</p> <p>To recap the business advantages of Modernizing Oracle Forms with APEX: Avoid the Big Bang approach. This way, you are in control. You can make long-term plans and a establish sequence of actions over several months or even years. The budgeting for such a project becomes reasonable. You can easily manage investments. You can manage the rhythm and phases of the project. Best of all your Oracle Forms Applications will be up to speed with the rest of your business.</p> <h2>Other Links on Forms Modernization</h2> <p><strong>First blog in this series</strong> <a href="https://insum.ca/oracle-forms-and-reports-modernization-forms-challenges/">Forms and reports Modernization &#8211; Forms Challenges</a></p> <p><strong>Second blog in this series</strong> <a href="https://insum.ca/oracle-forms-apex-similarities/">Oracle Forms Modernization, Forms-APEX similarities</a></p> <p>See also</p> <p><a href="https://insum.ca/oracle-forms-conversion-to-oracle-apex-where-to-start/">Oracle Forms Conversion to Oracle APEX &#8211; Where to Start</a></p> <p><a href="https://insum.ca/oracle-forms-modernization-journey/">The Oracle Forms Modernization Journey</a></p> <p><a href="https://insum.ca/time-modernize-oracle-forms-reports-application/">How You Know It&#8217;s Time To Modernize Your Oracle Forms &amp; Reports App</a></p> <p><a href="https://insum.ca/oracle-forms-keep-or-migrate/">Debating Whether to Keep Oracle Forms or to Migrate From It?</a></p> <p>&nbsp;</p> <p>The post <a rel="nofollow" href="https://insum.ca/advantages-of-modernizing-oracle-forms-with-apex/">Advantages of Modernizing Oracle Forms with APEX</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Francis Mignault https://insum.ca/?p=13398 Thu Nov 08 2018 08:54:44 GMT-0500 (EST) Developing PWA with Oracle APEX – why now is a good time https://insum.ca/developing-pwa-oracle-apex-why-now/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/11/apex-pwa-1-Site-100x100.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Developing PWA with Oracle APEX why now is a good time" srcset="https://insum.ca/wp-content/uploads/2018/11/apex-pwa-1-Site-100x100.png 100w, https://insum.ca/wp-content/uploads/2018/11/apex-pwa-1-Site-150x150.png 150w, https://insum.ca/wp-content/uploads/2018/11/apex-pwa-1-Site-600x600.png 600w, https://insum.ca/wp-content/uploads/2018/11/apex-pwa-1-Site-300x300.png 300w, https://insum.ca/wp-content/uploads/2018/11/apex-pwa-1-Site-50x50.png 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p>A PWA (Progressive Web App) is essentially a website that can act very much as an app does on a mobile phone or tablet.</p> <p>This is beyond simple responsive design, a technology that’s been almost universally adopted these past few years. Whereas responsive design adjusts the same information (desktop page) for viewing on all other sizes of pages, the progressive web app enables your website to provide a full app experience. This includes displaying an icon on your mobile device’s home screen and mimicking app look and behavior.</p> <p>PWA represent a huge opportunity for website owners wanting to attract more mobile users. It enables their visitors to enjoy the comfort and speed of app-like experience, without ever having to bother with getting the app at an app store and downloading it.</p> <h2>Big Platform Support for PWA is here</h2> <p>Now is indeed the time. This year, large platforms have set the stage for widespread support. In March, without announcing it, Apple added technology to support PWA on iOS 11.3 onward (as of the time of this article, this support has continued into iOS 12.x). In May at their I/O 2018 event, Google announced that it was using PWA technology to “<a href="https://www.youtube.com/watch?v=NITk4kXMQDw">Build bridges to mobile, desktop and native</a>”. For example, to help Google Search load faster. It is also using PWA for the Android version of Google maps (Google maps go) and in the new Gmail. As for Microsoft, its Windows 10 now also <a href="https://developer.microsoft.com/en-us/windows/pwa">supports</a> PWA.</p> <p>All sorts of other large companies are already using PWA to enhance their services. Just to name a few: Twitter, Pintrest, Starbucks, Vimeo, NASA and Tinder (probably the only time those last two names will be used in the same sentence).</p> <h2>PWA Advantages</h2> <p>It just makes sense for developers to find out how they could benefit from working with this technology. <strong>Here are four good reasons</strong></p> <h2>1. Installing Oracle APEX on your mobile device</h2> <p>Imagine the sheer joy of building an APEX application that installs on your smartphone. Of course, Mobile app building is nothing new for Oracle APEX. There are books about it, using technologies such as Apache Cordova or PhoneGap. But building a PWA has the advantage of being platform agnostic. You are also able to develop using only your APEX and JavaScript skills, there is no new technology to learn.</p> <h2>2. Offline usage</h2> <p>This is a significant UX advantage. Because PWA development allows you to control the cache and how to respond to resource requests, you can configure pre-caching to reduce the application&#8217;s dependence on the network and make for a much smoother user experience. This could represent huge benefits in developing countries with limited internet access. Building online business processes for Banking or Healthcare in remote areas would no longer depend on uninterrupted internet connection. To quote a recent visitor to the Insum LinkedIn account from Kenya: &#8220;PWA is a game changer&#8221;</p> <h2><strong>3. Synchronization</strong></h2> <p>This is nothing new for any social media app. For example, when you write a message and send it in a location without internet access the app automatically communicates with the server once the connection is reestablished.  This can now applied to any website through PWA. Very exciting. It automates and enhances the flow of actions for the user.</p> <h2>4. Push Notification</h2> <p>This technology has long been known to <a href="https://rubygarage.org/blog/benefits-of-push-notifications">increase user engagement</a>. It increases app retention rate, conversion rates and generally gives a real-time feel to the user&#8217;s interaction with the brand. With PWA, you can send push notifications even when all browsers are closed.</p> <h2>Join Insum&#8217;s Free Webinar</h2> <p>Those are just some of the advantages of using Progressive Web Apps. If you&#8217;d like an in-depth technical introduction to this technology, I recommend you attend my Free Webinar &#8220;<a href="https://info.insum.ca/turning-apex-into-a-progressive-web-app">Turning APEX into a Progressive Web App (PWA)</a>&#8221; Tomorrow, November 7th at 2 pm. ET.</p> <p>&nbsp;</p> <p>I look forward to meeting you there!</p> <p>&nbsp;</p> <p>The post <a rel="nofollow" href="https://insum.ca/developing-pwa-oracle-apex-why-now/">Developing PWA with Oracle APEX – why now is a good time</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Vincent Morneau https://insum.ca/?p=13445 Tue Nov 06 2018 10:16:21 GMT-0500 (EST) Oracle APEX is coming to Japan and Korea! https://blogs.oracle.com/apex/oracle-apex-is-coming-to-japan-and-korea <p>&nbsp;</p> <p><a href="https://apex.oracle.com" target="_blank">Oracle APEX</a> team members <a href="https://twitter.com/christinacho22" target="_blank">Christina Cho</a> and <a href="https://twitter.com/shakeeb" target="_blank">Shakeeb Rahman</a> will be visiting Tokyo, Japan and Seoul, South Korea in November!&nbsp; If you&#39;re in Tokyo or Seoul, please do not miss this opportunity to meet and learn directly from members of the Oracle APEX product development team!</p> <p>In Japan, there will be an Oracle APEX User Group meetup where you will learn what is new in Oracle APEX 18 and how you can use APEX to build beautiful, responsive apps using Universal Theme.&nbsp; In Seoul, there will be the Oracle APAC Developer Tour 2018 which is a full day event featuring two sessions on APEX, in addition to two APEX hands-on workshops for both beginners and experienced developers.&nbsp;</p> <p>The schedule of the Oracle APEX Japan and Korea tour is:</p> <p><u><strong>Japan</strong></u></p> <ul> <li>November 6, 2018:&nbsp; <a href="https://apex-tokyo.doorkeeper.jp/events/81173" target="_blank">Tokyo APEX User Group Meetup</a></li> </ul> <p><strong><u>South Korea</u></strong></p> <ul> <li>November 8, 2018:&nbsp; <a href="https://onoffmix.com/event/155113" target="_blank">APAC Developer Tour 2018</a></li> <li>November 13, 2018: <a href="http://www.mktg.co.kr/eDM/20181113_ODP_seminar/html/ODP_edm.html" target="_blank">APEX Intro Hands-on Workshop</a></li> <li>November 14, 2018: <a href="http://www.mktg.co.kr/eDM/20181113_ODP_seminar/html/ODP_edm.html" target="_blank">APEX New Features Hands-on Workshop</a></li> </ul> <p>&nbsp;</p> <p>Please register in advance.&nbsp; We hope to see you there!</p> Joel Kallman https://blogs.oracle.com/apex/oracle-apex-is-coming-to-japan-and-korea Mon Nov 05 2018 09:05:40 GMT-0500 (EST) Oracle APEX is coming to Japan and Korea! https://blogs.oracle.com/apex/oracle-apex-is-coming-to-japan-and-korea <p>&nbsp;</p> <p><a href="https://apex.oracle.com" target="_blank">Oracle APEX</a> team members <a href="https://twitter.com/christinacho22" target="_blank">Christina Cho</a> and <a href="https://twitter.com/shakeeb" target="_blank">Shakeeb Rahman</a> will be visiting Tokyo, Japan and Seoul, South Korea in November!&nbsp; If you&#39;re in Tokyo or Seoul, please do not miss this opportunity to meet and learn directly from members of the Oracle APEX product development team!</p> <p>In Japan, there will be an Oracle APEX User Group meetup where you will learn what is new in Oracle APEX 18 and how you can use APEX to build beautiful, responsive apps using Universal Theme.&nbsp; In Seoul, there will be the Oracle APAC Developer Tour 2018 which is a full day event featuring two sessions on APEX, in addition to two APEX hands-on workshops for both beginners and experienced developers.&nbsp;</p> <p>The schedule of the Oracle APEX Japan and Korea tour is:</p> <p><u><strong>Japan</strong></u></p> <ul> <li>November 6, 2018:&nbsp; <a href="https://apex-tokyo.doorkeeper.jp/events/81173" target="_blank">Tokyo APEX User Group Meetup</a></li> </ul> <p><strong><u>South Korea</u></strong></p> <ul> <li>November 8, 2018:&nbsp; <a href="https://onoffmix.com/event/155113" target="_blank">APAC Developer Tour 2018</a></li> <li>November 13, 2018: <a href="http://www.mktg.co.kr/eDM/20181113_ODP_seminar/html/ODP_edm.html" target="_blank">APEX Intro Hands-on Workshop</a></li> <li>November 14, 2018: <a href="http://www.mktg.co.kr/eDM/20181113_ODP_seminar/html/ODP_edm.html" target="_blank">APEX New Features Hands-on Workshop</a></li> </ul> <p>&nbsp;</p> <p>Please register in advance.&nbsp; We hope to see you there!</p> Joel Kallman https://blogs.oracle.com/apex/oracle-apex-is-coming-to-japan-and-korea Mon Nov 05 2018 09:05:40 GMT-0500 (EST) 5 Client Excuses For Not Upgrading Apex http://everythingapex.blogspot.com/2018/11/5-client-excuses-for-not-upgrading-apex_4.html In case you live under a rock, the latest release of Apex is Apex 18.2. This update was released on September 28, 2018. In case you missed it, you can find the release announcement&nbsp;<a href="https://blogs.oracle.com/apex/announcing-oracle-apex-182" target="_blank">here</a>. But even when there is a new Apex release, it seems that many Apex customers neither celebrate the release nor upgrade to it very quickly. Now I am in no way suggesting that you throw you production applications into Apex 18.2, but merely that you begin using it in your dev environment.<br /><br />I have been working with a lot of Apex clients. In some case they do not know that there is a new release. For others, there is a huge reluctance&nbsp;to update.<br /><br />As I work with my clients, I hear a lot of excuses that they repeatedly use for not upgrading to the latest release of Apex. In this post, I try to present the top 5 excuses I hear, and to respond to them as thoroughly as I can.<br /><h2>Excuse 1<br />I am waiting for the new release to be stable</h2>I am sure you have heard this one before. It really has no merit. I don't know of any release of Apex to be so so buggy as to cause it to be pulled back or immediately followed by another major. Most often, I see the Oracle Apex team respond to any issues by releasing a patch release. The patch is released sometimes to address some unintended behaviour.<br /><br />Sometimes, Apex hosting companies will also give this same excuse. But, the excuse is not really the right reason for them not to upgrade. The more valid reason, I suppose, is to avoid a sudden change of the Apex hosting environment. They want to give their clients time to upgrade their own apps. Wait a minute! This is another important reason for those clients to upgrade.<br /><br />No matter how you slice it, this excuse is simply that - an invalid excuse.<br /><h2>Excuse 2<br />Eveything is working fine now</h2>I am sure you've heard this one too. It is said over and over again.<br /><br />One of my recent larger clients were working in an Apex 5.1 environment. At least they upgraded to that version. Right? Wrong. While they upgraded to 5.1 most of their apps were built in 4.2, 4.0 and one even in 3.2. These apps were running in a 5.1 environment using the compatibility mode. Sure, the apps are working now, but for how much longer. While the Oracle Apex team is really good at supporting legacy versions, there will simply come a time that the version is so old that they surely break.<br /><br />Apex 5 was such a watershed release, it is crazy to have apps in any earlier version. Apex 5 significantly changed the performance of apps and introduce a whole new way of structuring applications. And, if you apps were built using Apex 5, it will be a snap to do the upgrade to release 18.2. So, to me, this excuse also has no validity.<br /><h2>Excuse 3<br />Our developers don't know the latest version</h2>This excuse is pathetic. There is always a lot of good documentation, articles and blog posts that will help you as a developer to make the transition. But if your developers have never even transitioned to Apex 5 then that failure rests entirely on you.<br /><br />When you think of it, this excuse is quite insulting to the ability of your developers. If they have any skill at all, they surely won't find the transition difficult.<br /><br />Let's say you just got the latest iPhone. Would you just leave it sitting on the table until someone from Apple comes along to show you how to use it. No. You play, explore and discover for yourself. If something has changed so much that you just don't know how to use it, you check web articles or forums to get the information you need. Surely it is like that with&nbsp;a new release of Apex. As developers, we are used to experimenting and poking around. For us, it is fun to learn and to discover new answers to old questions.<br /><br />Stop blaming your developers. Any developer that can't learn new things are really not developers anyway.<br /><br /><h2>Excuse 3<br />We don't need anything in version 18.2</h2>Really? Do you even know what the new release has to offer?<br /><br />Usually those who use this excuse know very little about the new release They have not read the <a href="https://docs.oracle.com/database/apex-18.2/HTMRN/toc.htm#HTMRN-GUID-540B73CB-08A7-4422-B6BF-CC785EC47694" target="_blank">release notes</a>. They haven't looked at the <a href="https://apex.oracle.com/en/learn/release-notes/" target="_blank">new features</a>. And they haven't at least taken a cursory look at the version 18.2 <a href="https://docs.oracle.com/database/apex-18.2/" target="_blank">documentation</a>. Until you have done all of this, you simply can't use this excuse.<br /><br /><h2>Excuse 4<br />We can't stop development to do an upgrade</h2>This excuse is a bit like excuse 3. Sure, if you are in the middle of a large project, now may not be the right time. However, if are just thinking the upgrade will take hors and hours - you are simply wrong.<br /><br />You can start my upgrading your development environment. Check out the level of effort to do the upgrade. Usually, it's a breeze. If it causes issues, just rollback to your pervious version. But rolling back should be your last choice. Look at the issues and try to resolve. It is not likely that you have been the first to come across the issue. Head on to the <a href="https://community.oracle.com/community/groundbreakers/database/developer-tools/application_express" target="_blank">Apex forum</a>.<br /><br />If you need to continue with the active development, create a new 18.2 environment to check things out.<br /><br /><h2>Excuse 5<br />We don't have anyone who knows how to do the upgrade</h2>If you've ever upgraded an Apex environment, you'll know that the Oracle Apex team has made the job pretty straight forward. In other words, the upgrade is not rocket science. It is not as if you are upgrading the database! With proper planning, it won't take a DBA or upgrade expert to get the job done.<br /><br />Luckily there are a lot of good resources to help you. One of the best blogs on upgrading that I have come across is Dimitri Gielis's <a href="http://dgielis.blogspot.com/2018/05/safely-upgrading-to-oracle-apex-181.html">Safely uprade to Apex 18.1.</a><br /><h2>Conclusion</h2><div>Okay. The decision to update is not one to take recklessly. It requires evaluation and planning. Nonetheless, it is unwise to remain on an older release indefinitely. It is even worse to continue to have applications that were built in very old versions of Apex. And, if it is not yet time to upgrade, remember that as developers we can&nbsp;<a href="https://apex.oracle.com/pls/apex/f?p=4700:2:106046438321969::NO:RP::" target="_blank">request a workspace</a>.</div><div><br /></div><div>Just stop using excuses. They make you look silly.</div><div><br /></div><div>Drop me a comment and let me know your thoughts on upgrading Apex.</div><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> Bruce Clark tag:blogger.com,1999:blog-2927557081925713627.post-7741266401262746421 Sun Nov 04 2018 08:55:00 GMT-0500 (EST) Relational to JSON with PL/SQL https://jsao.io/2018/11/relational-to-json-with-pl-sql/ <p>In the <a href="https://jsao.io/2018/10/relational-to-json-with-sql/">last post in this series</a>, I demonstrated how powerful functions added to the SQL engine in Oracle Database 12.2 allow you to generate JSON with ease. But what if you were doing something sufficiently complex that it required the procedural capabilities that PL/SQL provides? Well, you&#8217;re covered there too! In this post, I&#8217;ll show you how new JSON based object types can be used to get the job done.<br /> <span id="more-3215"></span></p> <div class="alert alert-info" role="alert"> <strong>Please Note:</strong> This post is part of <a href="https://jsao.io/2015/07/relational-to-json-in-oracle-database">a series on generating JSON from relational data in Oracle Database</a>. See that post for details on the solution implemented below as well as other options that can be used to achieve that goal. </div> <h4>Solution</h4> <p>The <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/adjsn/pl-sql-object-types-for-json.html#GUID-C0C2A8C0-99BD-4770-9EA2-B7D53804FC18">12.2+ PL/SQL object types</a> available for working with JSON are:</p> <ul> <li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/arpls/json-types.html#GUID-639D871E-D116-4793-888E-F7948E48F4DE">JSON_ELEMENT_T</a> &#8211; supertype of the other JSON types (rarely used directly)</li> <li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/arpls/json-types.html#GUID-10062646-E36F-48B1-9F24-751B613DFB5A">JSON_OBJECT_T</a> &#8211; used to represent JSON objects</li> <li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/arpls/json-types.html#GUID-69E61601-5533-418B-8C03-E591B4F7FE36">JSON_ARRAY_T</a> &#8211; used to represent JSON arrays</li> <li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/arpls/json-types.html#GUID-B9526171-92E2-423A-8831-872ADCC71D1E">JSON_SCALAR_T</a> &#8211; used to represent scalar values in JSON (strings, numbers, booleans, and null)</li> <li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/arpls/json-types.html#GUID-50692D34-FEAF-471E-BA22-17530E31D95D">JSON_KEY_LIST </a> &#8211; lesser used collection type for object keys</li> </ul> <p>In the following solution, I use the <span class="inline-code">JSON_OBJECT_T</span> and <span class="inline-code">JSON_ARRAY_T</span> types to generate the desired JSON output. Smaller data structures are used to compose larger ones until I have the JSON object I want. Then I use the <span class="inline-code">to_clob</span> method to serialize the in-memory representation to JSON.</p> <pre class="crayon-plain-tag">create or replace function get_dept_json( p_dept_id in departments.department_id%type ) return clob is cursor manager_cur ( p_manager_id in employees.employee_id%type ) is select * from employees where employee_id = manager_cur.p_manager_id; l_date_format constant varchar2(20) := 'DD-MON-YYYY'; l_dept_rec departments%rowtype; l_dept_json_obj json_object_t; l_loc_rec locations%rowtype; l_loc_json_obj json_object_t; l_country_rec countries%rowtype; l_country_json_obj json_object_t; l_manager_rec manager_cur%rowtype; l_manager_json_obj json_object_t; l_employees_json_arr json_array_t; l_employee_json_obj json_object_t; l_job_rec jobs%rowtype; l_jobs_json_arr json_array_t; l_job_json_obj json_object_t; begin select * into l_dept_rec from departments where department_id = get_dept_json.p_dept_id; l_dept_json_obj := json_object_t(); l_dept_json_obj.put('id', l_dept_rec.department_id); l_dept_json_obj.put('name', l_dept_rec.department_name); select * into l_loc_rec from locations where location_id = l_dept_rec.location_id; l_loc_json_obj := json_object_t(); l_loc_json_obj.put('id', l_loc_rec.location_id); l_loc_json_obj.put('streetAddress', l_loc_rec.street_address); l_loc_json_obj.put('postalCode', l_loc_rec.postal_code); select * into l_country_rec from countries cou where cou.country_id = l_loc_rec.country_id; l_country_json_obj := json_object_t(); l_country_json_obj.put('id', l_country_rec.country_id); l_country_json_obj.put('name', l_country_rec.country_name); l_country_json_obj.put('regionId', l_country_rec.region_id); l_loc_json_obj.put('country', l_country_json_obj); l_dept_json_obj.put('location', l_loc_json_obj); open manager_cur(l_dept_rec.manager_id); fetch manager_cur into l_manager_rec; if manager_cur%found then l_manager_json_obj := json_object_t(); l_manager_json_obj.put('id', l_manager_rec.employee_id); l_manager_json_obj.put('name', l_manager_rec.first_name || ' ' || l_manager_rec.last_name); l_manager_json_obj.put('salary', l_manager_rec.salary); select * into l_job_rec from jobs job where job.job_id = l_manager_rec.job_id; l_job_json_obj := json_object_t(); l_job_json_obj.put('id', l_job_rec.job_id); l_job_json_obj.put('title', l_job_rec.job_title); l_job_json_obj.put('minSalary', l_job_rec.min_salary); l_job_json_obj.put('maxSalary', l_job_rec.max_salary); l_manager_json_obj.put('job', l_job_json_obj); l_dept_json_obj.put('manager', l_manager_json_obj); else l_dept_json_obj.put_null('manager'); end if; close manager_cur; l_employees_json_arr := json_array_t(); for emp_rec in ( select * from employees where department_id = l_dept_rec.department_id ) loop l_employee_json_obj := json_object_t(); l_employee_json_obj.put('id', emp_rec.employee_id); l_employee_json_obj.put('name', emp_rec.first_name || ' ' || emp_rec.last_name); l_employee_json_obj.put('isSenior', emp_rec.hire_date &lt; to_date('01-jan-2005', 'dd-mon-yyyy')); l_employee_json_obj.put('commissionPct', emp_rec.commission_pct); l_jobs_json_arr := json_array_t(); for jh_rec in ( select job_id, department_id, start_date, end_date from job_history where employee_id = emp_rec.employee_id ) loop l_job_json_obj := json_object_t(); l_job_json_obj.put('id', jh_rec.job_id); l_job_json_obj.put('departmentId', jh_rec.department_id); l_job_json_obj.put('startDate', to_char(jh_rec.start_date, l_date_format)); l_job_json_obj.put('endDate', to_char(jh_rec.end_date, l_date_format)); l_jobs_json_arr.append(l_job_json_obj); end loop; l_employee_json_obj.put('jobHistory', l_jobs_json_arr); l_employees_json_arr.append(l_employee_json_obj); end loop; l_dept_json_obj.put('employees', l_employees_json_arr); return l_dept_json_obj.to_clob(); exception when others then if manager_cur%isopen then close manager_cur; end if; raise; end get_dept_json;</pre> <h4>Output</h4> <p>When passed a department id of 10, the function returns a CLOB populated with JSON that matches the goal 100%. </p> <pre class="crayon-plain-tag">{ &quot;id&quot;: 10, &quot;name&quot;: &quot;Administration&quot;, &quot;location&quot;: { &quot;id&quot;: 1700, &quot;streetAddress&quot;: &quot;2004 Charade Rd&quot;, &quot;postalCode&quot;: &quot;98199&quot;, &quot;country&quot;: { &quot;id&quot;: &quot;US&quot;, &quot;name&quot;: &quot;United States of America&quot;, &quot;regionId&quot;: 2 } }, &quot;manager&quot;: { &quot;id&quot;: 200, &quot;name&quot;: &quot;Jennifer Whalen&quot;, &quot;salary&quot;: 4400, &quot;job&quot;: { &quot;id&quot;: &quot;AD_ASST&quot;, &quot;title&quot;: &quot;Administration Assistant&quot;, &quot;minSalary&quot;: 3000, &quot;maxSalary&quot;: 6000 } }, &quot;employees&quot;: [ { &quot;id&quot;: 200, &quot;name&quot;: &quot;Jennifer Whalen&quot;, &quot;isSenior&quot;: true, &quot;commissionPct&quot;: null, &quot;jobHistory&quot;: [ { &quot;id&quot;: &quot;AD_ASST&quot;, &quot;departmentId&quot;: 90, &quot;startDate&quot;: &quot;17-SEP-1995&quot;, &quot;endDate&quot;: &quot;17-JUN-2001&quot; }, { &quot;id&quot;: &quot;AC_ACCOUNT&quot;, &quot;departmentId&quot;: 90, &quot;startDate&quot;: &quot;01-JUL-2002&quot;, &quot;endDate&quot;: &quot;31-DEC-2006&quot; } ] } ] }</pre> <h4>Summary</h4> <p>The JSON types for PL/SQL are a very welcome addition to Oracle Database. I&#8217;ve only demonstrated how to build up objects in memory to generate JSON, but there are many other methods for modification, serialization, introspection, and so on.</p> <p>If you&#8217;ve seen the <a href="https://jsao.io/2015/07/relational-to-json-with-pljson/">PL/JSON solution</a>, you&#8217;ll note that the code is very similar since they both use the object-oriented capablities of Oracle Database (as opposed to <a href="https://jsao.io/2015/07/relational-to-json-with-apex_json/">APEX_JSON</a> which is more procedural). When compared to PL/JSON, the main advantages to the 12.2+ built-in types are:</p> <ul> <li>Simplicity: There&#8217;s no installation needed.</li> <li>Documentation: The <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/adjsn/">JSON Developer&#8217;s Guide</a> provides some getting started content in <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/adjsn/pl-sql-object-types-for-json.html#GUID-C0C2A8C0-99BD-4770-9EA2-B7D53804FC18">Part IV: PL/SQL Object Types for JSON</a> and the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/arpls/json-types.html#GUID-BDE10AAA-445B-47B5-8A39-D86C8EA99283">PL/SQL Packages and Types Reference </a>provides additional API details.</li> <li>Peformance: I ran a small test on a local <a href="https://www.oracle.com/database/technologies/appdev/xe.html">18c XE</a> database where I generated the JSON for each department in the HR schema 100 times. The PL/JSON solution took about 4.6 seconds on average while the solution in this post and the APEX_JSON solution both took around 1.5 seconds.</li> </ul> <p>Having said all that, if you&#8217;re not yet using Oracle Database 12.2+, then PL/JSON is still a great option for working with JSON. The PL/JSON team continues to build out the APIs, address issues, and develop the documentation.</p> danmcghan https://jsao.io/?p=3215 Fri Nov 02 2018 12:18:23 GMT-0400 (EDT) New Emerging Technologies Track at ODTUG Kscope19 https://www.odtug.com/p/bl/et/blogaid=836&source=1 New to ODTUG Kscope19, the Emerging Technologies track offers ODTUG Kscope attendees the opportunity to learn about the latest and greatest technologies making a mark on the world. ODTUG https://www.odtug.com/p/bl/et/blogaid=836&source=1 Thu Nov 01 2018 14:31:43 GMT-0400 (EDT) Oracle Database + APEX + JavaScript/Python = Awesome! https://blogs.oracle.com/apex/oracle-database-%2B-apex-%2B-javascriptpython-%3D-awesome <p>The <a href="https://www.oracle.com/technetwork/database/multilingual-engine/overview/index.html" target="_blank">Oracle Database Multilingual Engine (MLE)</a> is an exciting new feature, targeted for a future release in <a href="https://www.oracle.com/database/index.html" target="_blank">Oracle Database</a>.&nbsp; This feature will enable the inclusion of other programming languages for execution inside the database.&nbsp; While the native procedural language of Oracle Database will remain the ever-powerful and elegant <a href="https://www.oracle.com/technetwork/database/features/plsql/index.html" target="_blank">PL/SQL</a>, extending the database with support for other languages opens up the creation of Oracle Database powered applications to a plethora of developers with other skill sets.</p> <p>The Oracle Database Multilingual Engine is based on the work done for <a href="https://www.graalvm.org/" target="_blank">GraalVM</a>, a high-performance virtual machine developed by the researchers at <a href="https://labs.oracle.com" target="_blank">Oracle Labs</a>.&nbsp; GraalVM is an <a href="https://github.com/oracle/graal" target="_blank">open source</a> project which is already used with success at many high-profile companies around the world (<a href="https://www.youtube.com/watch?v=OSyvidFXL7M" target="_blank">Twitter</a>, for example).</p> <p>The Oracle Labs, Oracle Database &amp; <a href="https://apex.oracle.com" target="_blank">Oracle APEX</a> teams have collaborated to provide an online, free preview of what this integration will look like.&nbsp; Beginning today and running through December 2018, anyone can sign up for a free hosted preview (&quot;early adopter&quot;) at <a href="https://apexea.oracle.com" target="_blank">https://apexea.oracle.com</a>.&nbsp; The purpose of this site is to offer our many Oracle Database and Oracle APEX customers a glimpse of what the future holds, as well as obtain your feedback and suggestions.</p> <p>&nbsp;</p> How do you get started? <p>To get started, you first need to sign up for a workspace at <a href="https://apexea.oracle.com" target="_blank">https://apexea.oracle.com</a>.&nbsp; Click the <strong>Request a Workspace</strong> button and complete the 3 short steps.&nbsp; Within a minute, you should receive an email with a link to verify your account and create your workspace.&nbsp; Upon first login, you&#39;ll also be prompted to setup a password for your associated APEX account credentials.&nbsp; These credentials will only be necessary if you create or install an APEX application.</p> <p>&nbsp;</p> You don&#39;t know anything about APEX.&nbsp; How can you test MLE? <p>Simple.&nbsp; Once you have successfully logged into your workspace, click the green <strong>SQL Workshop</strong> icon and then click <strong>SQL Commands</strong>.&nbsp; This is a SQL command processor, just like you would find with <a href="https://www.oracle.com/database/technologies/appdev/sqlcl.html" target="_blank">sqlcl</a> or <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/sqpug/SQL-Plus-quick-start.html#GUID-BF1995BD-EF9B-4EA2-9B32-7BFACDEB79DA">SQL*Plus</a>.&nbsp; Using this command interface, you can execute SQL &amp; PL/SQL.&nbsp; You can create and drop tables.&nbsp; You can issue any SELECT statement.&nbsp; You can now also execute JavaScript and Python from the command processor.&nbsp; As a quick example, select Language = JavaScript and enter the following code:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> console.log(<span style="color: #BA2121">&quot;hello world!&quot;</span>); </div> <p><br /> and click the <strong>Run</strong> button.&nbsp; The output should be displayed in the Results region at the bottom.</p> <p>To try out Python (Python support is experimental, at this stage), select Language = Python and execute the following code:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">datetime</span> <span style="color: #008000; font-weight: bold">import</span> date today <span style="color: #666666">=</span> <span style="color: #008000">str</span>(date<span style="color: #666666">.</span>today()) <span style="color: #008000; font-weight: bold">print</span>(today) </div> <p>&nbsp;</p> <p>Let&#39;s try another simple example.&nbsp; Enter the following code in the SQL Command processor with Language = JavaScript:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">var</span> currentDate <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> <span style="color: #008000">Date</span>(), day <span style="color: #666666">=</span> currentDate.getDate(), month <span style="color: #666666">=</span> currentDate.getMonth() <span style="color: #666666">+</span> <span style="color: #666666">1</span>, year <span style="color: #666666">=</span> currentDate.getFullYear(); console.log(day <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;/&quot;</span> <span style="color: #666666">+</span> month <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;/&quot;</span> <span style="color: #666666">+</span> year) </div> <p><br /> click the <strong>Run</strong> button, and the current date will be printed in the results.</p> <p>For the next example, you will need to create some sample database objects in your workspace.&nbsp; Click the <strong>SQL Workshop </strong>tab, then go to <strong>Utilities</strong> -&gt; <strong>Sample Datasets</strong>.&nbsp; Install the EMP / DEPT sample dataset, which will create both tables and insert sample data into them.&nbsp; After creating the sample tables, navigate back to <strong>SQL Commands</strong>.</p> <p>To show the integration between the SQL engine and JavaScript, ensure that the Language select list is set to JavaScript and enter the following code:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">for</span> (<span style="color: #008000; font-weight: bold">var</span> row of mle.sql.execute(<span style="color: #BA2121">&quot;SELECT EMPNO, ENAME FROM EMP ORDER BY EMPNO&quot;</span>).rows) { console.log(<span style="color: #BA2121">&quot;[&quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">0</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;, &quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">1</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;]&quot;</span>) }; </div> <p><br /> This will use the MLE engine to execute the SQL query, and then in JavaScript, iterate through the results and print them.&nbsp; But what if you wanted to include a bind variable in your query?&nbsp; It&#39;s actually quite easy with the SQL driver for JavaScript.&nbsp; You simply need to provide an array of the bind values following the SQL statement, with the position in the array corresponding to the position of the bind variable in the SQL statement.&nbsp; As a complete example:</p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">for</span> (var row of mle<span style="color: #666666">.</span>sql<span style="color: #666666">.</span>execute(<span style="color: #BA2121">&quot;SELECT EMPNO, ENAME FROM EMP WHERE SAL &gt; :sal AND DEPTNO = :deptno ORDER BY EMPNO&quot;</span>, [ <span style="color: #666666">1000</span>, <span style="color: #666666">30</span> ])<span style="color: #666666">.</span>rows) { console<span style="color: #666666">.</span>log(<span style="color: #BA2121">&quot;[&quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">0</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;, &quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">1</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;]&quot;</span>) }; </div> <p><br /> In this example, the value 1000 will be bound to bind variable :sal and 30 will be bound to bind variable :deptno.</p> <p>For more information on the SQL driver for JavaScript in MLE, please refer to the <a href="https://oracle.github.io/oracle-db-mle/releases/0.2.7/js/callouts/" target="_blank">Callouts section of the MLE documentation</a>.</p> <p>It is also possible to dynamically execute JavaScript or Python from PL/SQL, using the PL/SQL package DBMS_MLE.&nbsp; Data can be exchanged both ways, between JavaScript and PL/SQL.&nbsp; In SQL Commands, set the Language to &quot;SQL and PL/SQL&quot; and execute the following code:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">declare</span> l_script_source <span style="color: #008000; font-weight: bold">clob</span>; l_script_handle dbms_mle.script_handle_t; l_script_result <span style="color: #008000">number</span>; <span style="color: #008000; font-weight: bold">begin</span> l_script_source :<span style="color: #666666">=</span> q<span style="color: #BA2121">&#39;~</span> <span style="color: #BA2121"> mle.binds.totalsal = 0;</span> <span style="color: #BA2121"> for (var row of mle.sql.execute(&quot;SELECT SAL FROM EMP WHERE SAL &gt; &quot; + mle.binds.salary).rows) {</span> <span style="color: #BA2121"> mle.binds.totalsal += row[0];</span> <span style="color: #BA2121"> }</span> <span style="color: #BA2121"> ~&#39;</span>; l_script_handle :<span style="color: #666666">=</span> dbms_mle.create_script( l_script_source, <span style="color: #BA2121">&#39;JS&#39;</span> ); dbms_mle.bind_variable( l_script_handle, <span style="color: #BA2121">&#39;salary&#39;</span>, <span style="color: #666666">1000</span> ); dbms_mle.execute_script( l_script_handle ); dbms_mle.variable_value( l_script_handle, <span style="color: #BA2121">&#39;totalsal&#39;</span>, l_script_result ); dbms_mle.drop_script( l_script_handle ); dbms_output.put_line( <span style="color: #BA2121">&#39;Total Salary: &#39;</span> <span style="color: #666666">||</span> l_script_result ); <span style="color: #008000; font-weight: bold">end</span>; </div> <p>&nbsp;</p> <p>In this block of PL/SQL, you are creating a script handle for the JavaScript code, binding a value for salary (represented as mle.binds.salary in the JavaScript code), executing the script, which will execute the query and then iterate through the results, computing a sum of the salaries, and then retrieving the output value which was assigned in the script (i.e., mle.binds.totalsal).</p> &nbsp; Where can you use JavaScript or Python in an APEX application? <p>If you are knowledgable with APEX, you&#39;ll be able to appreciate the combination of APEX + MLE, as this is where the integration of these two technologies really shines.&nbsp; JavaScript is available in the APEX application definition, in page processes, validations, computations.&nbsp; You can author JavaScript functions returning SQL queries as the dynamic source for classic reports, calendars &amp; charts.&nbsp; And you can use Python for page processes and validations.</p> <p>When used within an APEX context, you are able to reference the value of page items (to both get and set the item values) using mle.binds.<em>PAGE_ITEM</em>.&nbsp; For example, the following code could be used in a page validation of type &quot;JavaScript Function Body (returning Boolean)&quot;:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">var</span> l <span style="color: #666666">=</span> mle.binds.P3_NAME.length; <span style="color: #008000; font-weight: bold">return</span> l <span style="color: #666666">&gt;=</span> <span style="color: #666666">3</span> <span style="color: #666666">&amp;&amp;</span> l <span style="color: #666666">&lt;=</span> <span style="color: #666666">20</span>; </div> <p><br /> The length of the value of page item P3_NAME is referenced via mle.binds.P3_NAME.length.&nbsp; The function body then returns the boolean result of the expression, if the length is greater than or equal to 3 and less than or equal to 20.</p> <p>Binding of page item values to bind variables in a SQL statement is similar to the PL/SQL example above, but you have to remember that the page item values will be available via mle.binds.<em>PAGE_ITEM</em>.&nbsp; Assuming you had page 2 in your APEX application with page items for salary and department number, an example would be:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">for</span> (<span style="color: #008000; font-weight: bold">var</span> row of mle.sql.execute(<span style="color: #BA2121">&quot;SELECT EMPNO, ENAME FROM EMP WHERE SAL &gt; :sal AND DEPTNO = :deptno ORDER BY EMPNO&quot;</span>, [ mle.binds.P2_SAL, mle.binds.P2_DEPTNO ]).rows) { console.log(<span style="color: #BA2121">&quot;[&quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">0</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;, &quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">1</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;]&quot;</span>) }; </div> <p>&nbsp;</p> <p>For APEX developers, the easiest way to get started is to install the APEX + MLE Sample Application.&nbsp; To do this:</p> <ol> <li>Login to your workspace</li> <li>Click <strong>App Gallery</strong></li> <li>Click&nbsp;<strong>MLE + APEX Sample Application</strong></li> <li>Click <strong>Install App</strong>, <strong>Next</strong> and <strong>Install App</strong>.</li> <li>Click the Run button.</li> </ol> <p>It&#39;s that simple.&nbsp; You&#39;ll need to login with the credentials of your Application Express account, which you would have setup when you first logged into your workspace.&nbsp; The sample application is unlocked so you can examine how the JavaScript &amp; Python code is used within the app.</p> &nbsp; Where can you access additional documentation? <p>The <a href="https://oracle.github.io/oracle-db-mle/releases/0.2.7/js/callouts/" target="_blank">Github MLE repository contains documentation</a> for the SQL driver which is built into MLE. It is automatically exposed in the mle.sql JavaScript namespace within APEX. The Help tab of the APEX Page Designer contains additional code examples, when you&#39;re editing the JavaScript or Python code attribute in the Property Editor.</p> &nbsp; How do you provide feedback?&nbsp; Where can you get support? <p>This hosted early adopter program is not supported by Oracle Support.&nbsp; It is not intended for production applications.&nbsp; You will not be able to import the APEX applications developed on this site into any other APEX installation.&nbsp; It is only intended for evaluation and to get your feedback and suggestions.&nbsp; We welcome any and all feedback, in the <a href="https://community.oracle.com/community/groundbreakers/database/developer-tools/multilingual-engine/content" target="_blank">MLE discussion forum</a> in the Oracle Database Developer community.</p> <p>&nbsp;</p> <p>If you have any questions, please let us know in the <a href="http://community.oracle.com/community/groundbreakers/database/developer-tools/multilingual-engine/content" target="_blank">MLE discussion forum</a>.&nbsp; We look forward to your feedback.&nbsp; We are excited about the future with Oracle Database, APEX and MLE!</p> Joel Kallman https://blogs.oracle.com/apex/oracle-database-%2B-apex-%2B-javascriptpython-%3D-awesome Thu Nov 01 2018 11:50:00 GMT-0400 (EDT) Oracle Database + APEX + JavaScript/Python = Awesome! https://blogs.oracle.com/apex/oracle-database-%2B-apex-%2B-javascriptpython-%3D-awesome <p>The <a href="https://www.oracle.com/technetwork/database/multilingual-engine/overview/index.html" target="_blank">Oracle Database Multilingual Engine (MLE)</a> is an exciting new feature, targeted for a future release in <a href="https://www.oracle.com/database/index.html" target="_blank">Oracle Database</a>.&nbsp; This feature will enable the inclusion of other programming languages for execution inside the database.&nbsp; While the native procedural language of Oracle Database will remain the ever-powerful and elegant <a href="https://www.oracle.com/technetwork/database/features/plsql/index.html" target="_blank">PL/SQL</a>, extending the database with support for other languages opens up the creation of Oracle Database powered applications to a plethora of developers with other skill sets.</p> <p>The Oracle Database Multilingual Engine is based on the work done for <a href="https://www.graalvm.org/" target="_blank">GraalVM</a>, a high-performance virtual machine developed by the researchers at <a href="https://labs.oracle.com" target="_blank">Oracle Labs</a>.&nbsp; GraalVM is an <a href="https://github.com/oracle/graal" target="_blank">open source</a> project which is already used with success at many high-profile companies around the world (<a href="https://www.youtube.com/watch?v=OSyvidFXL7M" target="_blank">Twitter</a>, for example).</p> <p>The Oracle Labs, Oracle Database &amp; <a href="https://apex.oracle.com" target="_blank">Oracle APEX</a> teams have collaborated to provide an online, free preview of what this integration will look like.&nbsp; Beginning today and running through December 2018, anyone can sign up for a free hosted preview (&quot;early adopter&quot;) at <a href="https://apexea.oracle.com" target="_blank">https://apexea.oracle.com</a>.&nbsp; The purpose of this site is to offer our many Oracle Database and Oracle APEX customers a glimpse of what the future holds, as well as obtain your feedback and suggestions.</p> <p>&nbsp;</p> How do you get started? <p>To get started, you first need to sign up for a workspace at <a href="https://apexea.oracle.com" target="_blank">https://apexea.oracle.com</a>.&nbsp; Click the <strong>Request a Workspace</strong> button and complete the 3 short steps.&nbsp; Within a minute, you should receive an email with a link to verify your account and create your workspace.&nbsp; Upon first login, you&#39;ll also be prompted to setup a password for your associated APEX account credentials.&nbsp; These credentials will only be necessary if you create or install an APEX application.</p> <p>&nbsp;</p> You don&#39;t know anything about APEX.&nbsp; How can you test MLE? <p>Simple.&nbsp; Once you have successfully logged into your workspace, click the green <strong>SQL Workshop</strong> icon and then click <strong>SQL Commands</strong>.&nbsp; This is a SQL command processor, just like you would find with <a href="https://www.oracle.com/database/technologies/appdev/sqlcl.html" target="_blank">sqlcl</a> or <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/sqpug/SQL-Plus-quick-start.html#GUID-BF1995BD-EF9B-4EA2-9B32-7BFACDEB79DA">SQL*Plus</a>.&nbsp; Using this command interface, you can execute SQL &amp; PL/SQL.&nbsp; You can create and drop tables.&nbsp; You can issue any SELECT statement.&nbsp; You can now also execute JavaScript and Python from the command processor.&nbsp; As a quick example, select Language = JavaScript and enter the following code:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> console.log(<span style="color: #BA2121">&quot;hello world!&quot;</span>); </div> <p><br /> and click the <strong>Run</strong> button.&nbsp; The output should be displayed in the Results region at the bottom.</p> <p>To try out Python (Python support is experimental, at this stage), select Language = Python and execute the following code:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">datetime</span> <span style="color: #008000; font-weight: bold">import</span> date today <span style="color: #666666">=</span> <span style="color: #008000">str</span>(date<span style="color: #666666">.</span>today()) <span style="color: #008000; font-weight: bold">print</span>(today) </div> <p>&nbsp;</p> <p>Let&#39;s try another simple example.&nbsp; Enter the following code in the SQL Command processor with Language = JavaScript:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">var</span> currentDate <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> <span style="color: #008000">Date</span>(), day <span style="color: #666666">=</span> currentDate.getDate(), month <span style="color: #666666">=</span> currentDate.getMonth() <span style="color: #666666">+</span> <span style="color: #666666">1</span>, year <span style="color: #666666">=</span> currentDate.getFullYear(); console.log(day <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;/&quot;</span> <span style="color: #666666">+</span> month <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;/&quot;</span> <span style="color: #666666">+</span> year) </div> <p><br /> click the <strong>Run</strong> button, and the current date will be printed in the results.</p> <p>For the next example, you will need to create some sample database objects in your workspace.&nbsp; Click the <strong>SQL Workshop </strong>tab, then go to <strong>Utilities</strong> -&gt; <strong>Sample Datasets</strong>.&nbsp; Install the EMP / DEPT sample dataset, which will create both tables and insert sample data into them.&nbsp; After creating the sample tables, navigate back to <strong>SQL Commands</strong>.</p> <p>To show the integration between the SQL engine and JavaScript, ensure that the Language select list is set to JavaScript and enter the following code:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">for</span> (<span style="color: #008000; font-weight: bold">var</span> row of mle.sql.execute(<span style="color: #BA2121">&quot;SELECT EMPNO, ENAME FROM EMP ORDER BY EMPNO&quot;</span>).rows) { console.log(<span style="color: #BA2121">&quot;[&quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">0</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;, &quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">1</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;]&quot;</span>) }; </div> <p><br /> This will use the MLE engine to execute the SQL query, and then in JavaScript, iterate through the results and print them.&nbsp; But what if you wanted to include a bind variable in your query?&nbsp; It&#39;s actually quite easy with the SQL driver for JavaScript.&nbsp; You simply need to provide an array of the bind values following the SQL statement, with the position in the array corresponding to the position of the bind variable in the SQL statement.&nbsp; As a complete example:</p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">for</span> (var row of mle<span style="color: #666666">.</span>sql<span style="color: #666666">.</span>execute(<span style="color: #BA2121">&quot;SELECT EMPNO, ENAME FROM EMP WHERE SAL &gt; :sal AND DEPTNO = :deptno ORDER BY EMPNO&quot;</span>, [ <span style="color: #666666">1000</span>, <span style="color: #666666">30</span> ])<span style="color: #666666">.</span>rows) { console<span style="color: #666666">.</span>log(<span style="color: #BA2121">&quot;[&quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">0</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;, &quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">1</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;]&quot;</span>) }; </div> <p><br /> In this example, the value 1000 will be bound to bind variable :sal and 30 will be bound to bind variable :deptno.</p> <p>For more information on the SQL driver for JavaScript in MLE, please refer to the <a href="https://oracle.github.io/oracle-db-mle/releases/0.2.7/js/callouts/" target="_blank">Callouts section of the MLE documentation</a>.</p> <p>It is also possible to dynamically execute JavaScript or Python from PL/SQL, using the PL/SQL package DBMS_MLE.&nbsp; Data can be exchanged both ways, between JavaScript and PL/SQL.&nbsp; In SQL Commands, set the Language to &quot;SQL and PL/SQL&quot; and execute the following code:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">declare</span> l_script_source <span style="color: #008000; font-weight: bold">clob</span>; l_script_handle dbms_mle.script_handle_t; l_script_result <span style="color: #008000">number</span>; <span style="color: #008000; font-weight: bold">begin</span> l_script_source :<span style="color: #666666">=</span> q<span style="color: #BA2121">&#39;~</span> <span style="color: #BA2121"> mle.binds.totalsal = 0;</span> <span style="color: #BA2121"> for (var row of mle.sql.execute(&quot;SELECT SAL FROM EMP WHERE SAL &gt; &quot; + mle.binds.salary).rows) {</span> <span style="color: #BA2121"> mle.binds.totalsal += row[0];</span> <span style="color: #BA2121"> }</span> <span style="color: #BA2121"> ~&#39;</span>; l_script_handle :<span style="color: #666666">=</span> dbms_mle.create_script( l_script_source, <span style="color: #BA2121">&#39;JS&#39;</span> ); dbms_mle.bind_variable( l_script_handle, <span style="color: #BA2121">&#39;salary&#39;</span>, <span style="color: #666666">1000</span> ); dbms_mle.execute_script( l_script_handle ); dbms_mle.variable_value( l_script_handle, <span style="color: #BA2121">&#39;totalsal&#39;</span>, l_script_result ); dbms_mle.drop_script( l_script_handle ); dbms_output.put_line( <span style="color: #BA2121">&#39;Total Salary: &#39;</span> <span style="color: #666666">||</span> l_script_result ); <span style="color: #008000; font-weight: bold">end</span>; </div> <p>&nbsp;</p> <p>In this block of PL/SQL, you are creating a script handle for the JavaScript code, binding a value for salary (represented as mle.binds.salary in the JavaScript code), executing the script, which will execute the query and then iterate through the results, computing a sum of the salaries, and then retrieving the output value which was assigned in the script (i.e., mle.binds.totalsal).</p> &nbsp; Where can you use JavaScript or Python in an APEX application? <p>If you are knowledgable with APEX, you&#39;ll be able to appreciate the combination of APEX + MLE, as this is where the integration of these two technologies really shines.&nbsp; JavaScript is available in the APEX application definition, in page processes, validations, computations.&nbsp; You can author JavaScript functions returning SQL queries as the dynamic source for classic reports, calendars &amp; charts.&nbsp; And you can use Python for page processes and validations.</p> <p>When used within an APEX context, you are able to reference the value of page items (to both get and set the item values) using mle.binds.<em>PAGE_ITEM</em>.&nbsp; For example, the following code could be used in a page validation of type &quot;JavaScript Function Body (returning Boolean)&quot;:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">var</span> l <span style="color: #666666">=</span> mle.binds.P3_NAME.length; <span style="color: #008000; font-weight: bold">return</span> l <span style="color: #666666">&gt;=</span> <span style="color: #666666">3</span> <span style="color: #666666">&amp;&amp;</span> l <span style="color: #666666">&lt;=</span> <span style="color: #666666">20</span>; </div> <p><br /> The length of the value of page item P3_NAME is referenced via mle.binds.P3_NAME.length.&nbsp; The function body then returns the boolean result of the expression, if the length is greater than or equal to 3 and less than or equal to 20.</p> <p>Binding of page item values to bind variables in a SQL statement is similar to the PL/SQL example above, but you have to remember that the page item values will be available via mle.binds.<em>PAGE_ITEM</em>.&nbsp; Assuming you had page 2 in your APEX application with page items for salary and department number, an example would be:</p> <p></p> <div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <span style="color: #008000; font-weight: bold">for</span> (<span style="color: #008000; font-weight: bold">var</span> row of mle.sql.execute(<span style="color: #BA2121">&quot;SELECT EMPNO, ENAME FROM EMP WHERE SAL &gt; :sal AND DEPTNO = :deptno ORDER BY EMPNO&quot;</span>, [ mle.binds.P2_SAL, mle.binds.P2_DEPTNO ]).rows) { console.log(<span style="color: #BA2121">&quot;[&quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">0</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;, &quot;</span> <span style="color: #666666">+</span> row[<span style="color: #666666">1</span>] <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;]&quot;</span>) }; </div> <p>&nbsp;</p> <p>For APEX developers, the easiest way to get started is to install the APEX + MLE Sample Application.&nbsp; To do this:</p> <ol> <li>Login to your workspace</li> <li>Click <strong>App Gallery</strong></li> <li>Click&nbsp;<strong>MLE + APEX Sample Application</strong></li> <li>Click <strong>Install App</strong>, <strong>Next</strong> and <strong>Install App</strong>.</li> <li>Click the Run button.</li> </ol> <p>It&#39;s that simple.&nbsp; You&#39;ll need to login with the credentials of your Application Express account, which you would have setup when you first logged into your workspace.&nbsp; The sample application is unlocked so you can examine how the JavaScript &amp; Python code is used within the app.</p> &nbsp; Where can you access additional documentation? <p>The <a href="https://oracle.github.io/oracle-db-mle/releases/0.2.7/js/callouts/" target="_blank">Github MLE repository contains documentation</a> for the SQL driver which is built into MLE. It is automatically exposed in the mle.sql JavaScript namespace within APEX. The Help tab of the APEX Page Designer contains additional code examples, when you&#39;re editing the JavaScript or Python code attribute in the Property Editor.</p> &nbsp; How do you provide feedback?&nbsp; Where can you get support? <p>This hosted early adopter program is not supported by Oracle Support.&nbsp; It is not intended for production applications.&nbsp; You will not be able to import the APEX applications developed on this site into any other APEX installation.&nbsp; It is only intended for evaluation and to get your feedback and suggestions.&nbsp; We welcome any and all feedback, in the <a href="https://community.oracle.com/community/groundbreakers/database/developer-tools/multilingual-engine/content" target="_blank">MLE discussion forum</a> in the Oracle Database Developer community.</p> <p>&nbsp;</p> <p>If you have any questions, please let us know in the <a href="http://community.oracle.com/community/groundbreakers/database/developer-tools/multilingual-engine/content" target="_blank">MLE discussion forum</a>.&nbsp; We look forward to your feedback.&nbsp; We are excited about the future with Oracle Database, APEX and MLE!</p> Joel Kallman https://blogs.oracle.com/apex/oracle-database-%2B-apex-%2B-javascriptpython-%3D-awesome Thu Nov 01 2018 11:50:00 GMT-0400 (EDT) Lazy Loading Menu Count http://www.grassroots-oracle.com/2018/11/lazy-loading-menu-orclapex.html I've been using the lazy loading concept demonstrated in <a href="http://max-tremblay.blogspot.com/2018/05/lazy-loading-report.html" target="_blank">Maxime's post</a>&nbsp;quite a lot recently, I'd love to see this as a declarative feature one day.<br /><br />I also wondered if I could apply this concept to the badge count in the side menu - not slow the page load by a longer running query that populates the count.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-6V_CDwYpwyc/W9sU7I_V7zI/AAAAAAAAUBY/UWe7oz62-LM-d_Zv0Xb6WrLtFz4V2Zo1wCLcBGAs/s1600/menu_cnt.png" imageanchor="1"><img border="0" data-original-height="51" data-original-width="184" src="https://4.bp.blogspot.com/-6V_CDwYpwyc/W9sU7I_V7zI/AAAAAAAAUBY/UWe7oz62-LM-d_Zv0Xb6WrLtFz4V2Zo1wCLcBGAs/s1600/menu_cnt.png" /></a></div><br />Turns out it wasn't that hard, particularly since I already had the jQuery I needed from a previous requirement.<br /><br />We first need to add a unique class to the link definition, so we can identify the menu item that needs updating.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-6ZIIKJMapXM/W9sU7D1Hk5I/AAAAAAAAUBc/AKWkLFzs3RUyoF98URWVUtVm4riq24WVQCLcBGAs/s1600/lazy_menu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="318" data-original-width="442" src="https://1.bp.blogspot.com/-6ZIIKJMapXM/W9sU7D1Hk5I/AAAAAAAAUBc/AKWkLFzs3RUyoF98URWVUtVm4riq24WVQCLcBGAs/s1600/lazy_menu.png" /></a></div><br />The label contains the substitution string reference to an application item called LAZY_MENU, that is just computed to zero on each page load.<br />Surrounded by square brackets, this turns it into the count badge.<br /><br />Add a dynamic action that executes PL/SQL on Page Load, probably to the global page, though <a href="https://apex.oracle.com/pls/apex/f?p=32532:15" target="_blank">this demo</a> only fires when on page 15.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-aBdSA90dCO4/W9sU7DjEmhI/AAAAAAAAUBU/2QmGJ0TtPEU9xw10GTHRj2nP0_WLrpxMACLcBGAs/s1600/lazy_plsql.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="235" data-original-width="408" src="https://4.bp.blogspot.com/-aBdSA90dCO4/W9sU7DjEmhI/AAAAAAAAUBU/2QmGJ0TtPEU9xw10GTHRj2nP0_WLrpxMACLcBGAs/s1600/lazy_plsql.png" /></a></div><br />The demo populates the item based on a query that counts how many columns in my schema, plus a random number, so we can see it change each time.<br /><br />A subsequent JavaScript action is where the real action is at<br /><pre class="brush:javascript">$('#t_TreeNav span.lazy-menu')<br /> .closest('div.a-TreeView-content')<br /> .find('span.a-TreeView-badge')<br /> .text($v('P15_COUNT'));</pre>The selector identifies the menu item based on the <code>lazy-menu</code> class entered in the link definition, then traverses the tree to locate the relevant badge, which is then updated to the page item.<br /><br />A more complete solution may also update LAZY_MENU application item, ready to have reasonably fresh information for the next page load.<br /><br />Or we could make our queries faster ;p Scott Wesley tag:blogger.com,1999:blog-4818542164384221282.post-1863007960792340377 Thu Nov 01 2018 11:20:00 GMT-0400 (EDT) Toad Data Modeler Reverse Engineering & Convert Model Wizards http://feedproxy.google.com/~r/DescubriendoElMundoDeOracle/~3/NZldA-si510/toad-data-modeler-reverse-engineering.html <div style="background-color: white; box-sizing: border-box; color: #222222; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 16px; margin-bottom: 1rem;">We can easily create a data model of an existing database schema using the&nbsp;<span style="box-sizing: border-box; font-weight: bolder;">Toad Data Modeler Reverse Engineering wizard</span>&nbsp;and then using the&nbsp;<span style="box-sizing: border-box; font-weight: bolder;">Convert Model Wizard</span>&nbsp;to convert that model to another database platform.</div><div style="background-color: white; box-sizing: border-box; color: #222222; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 16px; margin-bottom: 1rem;">For this demonstration I have a schema called&nbsp;<span style="box-sizing: border-box; font-weight: bolder;">quest</span>&nbsp;in an Oracle 11g R2 database; below we can see its data model.</div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-aac4Flb5HR4/W9pK8HLb7-I/AAAAAAAAMUM/pcD4K7du0iEENYdM49yVzIfqMPl4d_MgwCLcBGAs/s1600/img01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="467" data-original-width="1179" height="157" src="https://1.bp.blogspot.com/-aac4Flb5HR4/W9pK8HLb7-I/AAAAAAAAMUM/pcD4K7du0iEENYdM49yVzIfqMPl4d_MgwCLcBGAs/s400/img01.jpg" width="400" /></a></div><div style="background-color: white; box-sizing: border-box; color: #222222; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 16px; margin-bottom: 1rem;"><em style="box-sizing: border-box;">Figure 1. Data model for our example schema</em></div><h2 style="background-color: white; box-sizing: border-box; color: #222222; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 2rem; font-weight: 300; line-height: 1.2; margin-bottom: 1.25rem; margin-top: 0px;">Reverse Engineering Wizard</h2><div style="background-color: white; box-sizing: border-box; color: #222222; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 16px; margin-bottom: 1rem;">Before using the wizard that will allow us to create the data model of the existing database, it’s very important to know which database systems are supported by the Reverse Engineering tool.</div><div style="background-color: white; box-sizing: border-box; color: #222222; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 16px; margin-bottom: 1rem;">Seguir leyendo <a href="https://blog.toadworld.com/toad-data-modeler-reverse-engineering-convert-model-wizards" target="_blank">AQUI</a></div><div style="background-color: white; box-sizing: border-box; color: #222222; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Arial, sans-serif; font-size: 16px; margin-bottom: 1rem;"><br /></div><img src="http://feeds.feedburner.com/~r/DescubriendoElMundoDeOracle/~4/NZldA-si510" height="1" width="1" alt=""/> Clarisa J. Maman Orfali tag:blogger.com,1999:blog-1315583943401206186.post-573407774013254416 Wed Oct 31 2018 20:39:00 GMT-0400 (EDT) Instalación de Oracle and Reports 11gR2 en Windows 10 http://feedproxy.google.com/~r/DescubriendoElMundoDeOracle/~3/IhjIju96xqg/instalacion-de-oracle-and-reports-11gr2.html En este artículo vamos a aprender a instalar Oracle Forms and Reports por defecto en Windows 10.<br /><br />Al descomprimir los archivos "ofm_frmrpts_win_11.1.2.2.0_32_disk1_1of2.zip" y "ofm_frmrpts_win_11.1.2.2.0_32_disk1_2of2.zip" se generarán 4 directorios (Disk1, Disk, Disk3 y Disk4).<br /><br />Antes de iniciar la instalación, seleccionamos el ejecutable “Setup.exe” dentro del directorio Disk1 y con el botón derecho del mouse abrimos las propiedades del archivo.<br /><br />En la ficha Compatibility, seleccionamos que sea compatible con Windows 7.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-HNG3IU9CGOI/W9o3I48bSOI/AAAAAAAAMUA/M-oeBf9xOyQgnMgzw0z44IKJyJCTW_AtwCLcBGAs/s1600/img00.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="533" data-original-width="397" height="320" src="https://3.bp.blogspot.com/-HNG3IU9CGOI/W9o3I48bSOI/AAAAAAAAMUA/M-oeBf9xOyQgnMgzw0z44IKJyJCTW_AtwCLcBGAs/s320/img00.JPG" width="238" /></a></div>Seguir leyendo <a href="https://clartechacademy.com/instalacion-de-oracle-and-reports-11gr2-en-windows-10/" target="_blank">AQUI</a><img src="http://feeds.feedburner.com/~r/DescubriendoElMundoDeOracle/~4/IhjIju96xqg" height="1" width="1" alt=""/> Clarisa J. Maman Orfali tag:blogger.com,1999:blog-1315583943401206186.post-3241042939901652092 Wed Oct 31 2018 19:14:00 GMT-0400 (EDT) ODTUG October News https://www.odtug.com/p/bl/et/blogaid=835&source=1 Announcing the 2018–2019 ODTUG Leadership Program Class! ODTUG is pleased to announce its sixth ODTUG Leadership Program, a program dedicated to enhancing the leadership skills of ODTUG members. ODTUG https://www.odtug.com/p/bl/et/blogaid=835&source=1 Wed Oct 31 2018 10:25:26 GMT-0400 (EDT) Instalación de Weblogic Server 11g R1 (10.3.6) en Windows (64-bit) http://feedproxy.google.com/~r/DescubriendoElMundoDeOracle/~3/W5gFRdfUiHc/instalacion-de-weblogic-server-11g-r1.html En este artículo quiero compartir como realizar la instalación por defecto de Oracle WebLogic Server 11gR1 con la intención de que usemos Oracle Forms and Reports 11gR2 Developer.<br /><br />En esta primera parte veremos como instalar WebLogic y en otro articulo veremos como instalar Oracle Forms 11gR2.<br /><br />&nbsp;Para descargar WebLogic vamos al siguiente link: <a href="https://www.oracle.com/technetwork/middleware/ias/downloads/wls-main-097127.html%20Instalaci%C3%B3n">https://www.oracle.com/technetwork/middleware/ias/downloads/wls-main-097127.html Instalación</a><br /><br /> Primero configuramos la variable de entorno Windows JAVA_HOME con la ruta del JDK7 set JAVA_HOME="C:\Program Files\Java\jdk1.7.0_79"<br /><br />Ejecutamos el archivo: oepe-wls-indigo-installer-11.1.1.8.0.201110211138-10.3.6-win32.exe como un administrador.<br /><br />Se inicia el asistente presentando la pantalla de Bienvenida.<br /><br /><div class="separator" style="clear: both; text-align: center;"></div>Ingresamos la ubicación del directorio home del middleware por ejemplo en: c:\app\oracle\middleware, luego hacemos click en el botón Next.<br /><br />Ingresamos nuestras credenciales del soporte de Oracle, o podemos destildar el checkbox si no queremos recibir información sobre actualizaciones de seguridad. Hacemos click en el botón Next y aceptamos todos los mensajes de advertencia acerca de permanecer desinformado de actualizaciones de seguridad. <br /><br />Seguir leyendo <a href="https://clartechacademy.com/instalacion-de-weblogic-server-11g-r1-10-3-6-en-windows-64-bit/" target="_blank">AQUI</a><br /><br /><img src="http://feeds.feedburner.com/~r/DescubriendoElMundoDeOracle/~4/W5gFRdfUiHc" height="1" width="1" alt=""/> Clarisa J. Maman Orfali tag:blogger.com,1999:blog-1315583943401206186.post-175316523640312865 Wed Oct 31 2018 00:48:00 GMT-0400 (EDT) Oracle XE 18 Docker Image http://www.talkapex.com/2018/10/oracle-xe-18-docker-image/ <p>Last week <a href="https://twitter.com/GeraldVenzl" target="_blank" rel="noopener">Gerald Venzl</a> announced on his <a href="https://geraldonit.com/2018/10/20/oracle-database-18c-express-edition-is-generally-available/" target="_blank" rel="noopener">blog</a> that Oracle XE 18c was available. You can download Oracle XE at <a href="http://oracle.com/xe" target="_blank" rel="noopener">oracle.com/xe</a>.</p><p>Since it was announced <a href="https://twitter.com/fuzziebrain" target="_blank" rel="noopener">Adrian Png</a> created a Docker image and I’ve been working with him help ensure that the data files can be preserved even when the container is destroyed.</p><img src="/2018/10/oracle-xe-18-docker-image/appdev_database-xe-alt_detailed.png"><p>Using the new <a href="https://github.com/fuzziebrain/docker-oracle-xe" target="_blank" rel="noopener">Oracle XE 18c Docker</a> script you can now build your own Docker image and run your Oracle XE as a container. I recommend that anyone planning to use Oracle XE on their laptop look at using this Docker image rather installing locally or a VM (more on this in a future article). </p><p>In the future Oracle may release its own official Docker image for Oracle XE. I will update this post when such an image is available.</p> Martin Giffy D'Souza http://www.talkapex.com/2018/10/oracle-xe-18-docker-image/ Sat Oct 27 2018 11:31:04 GMT-0400 (EDT) Eine verrückte Zeit endet... https://www.apex-at-work.com/2018/10/eine-verruckte-zeit-endet.html Hallo zusammen,<br /><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal" style="tab-stops: 138.0pt;">ich habe leider eine schlechte Nachricht zu verkünden. Ich trete als Leitungskraft innerhalb der DOAG NextGen-Community zurück. Das kommt leider nicht nur für euch überraschend, und glaubt mir, dieser Schritt ist mir nicht leichtgefallen, weil ich weiß, dass ihr da draußen auf das, was die NextGen geleistet hat, vertraut und mit Freude die Entwicklung und den Spirit mitverfolgt habt.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-B_LqKMo7bfA/W9NXRv_gxCI/AAAAAAAACBw/dHRa_0B2eQgztWbH6W9NhxgghHJU6c0ZwCLcBGAs/s1600/farewell-3258939_1920.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="812" data-original-width="1600" height="323" src="https://3.bp.blogspot.com/-B_LqKMo7bfA/W9NXRv_gxCI/AAAAAAAACBw/dHRa_0B2eQgztWbH6W9NhxgghHJU6c0ZwCLcBGAs/s640/farewell-3258939_1920.jpg" width="640" /></a></div></div><div class="MsoNormal" style="tab-stops: 138.0pt;">Leider gab es vor kurzem mehrere Vorstandsbeschlüsse, die ein weiteres Engagement für mich praktisch unmöglich machen. Diese Beschlüsse betreffen die grundsätzliche Ausrichtung der NextGen-Community innerhalb der DOAG.</div><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal" style="tab-stops: 138.0pt;">Beschluss 1:</div><div class="MsoNormal" style="tab-stops: 138.0pt;">„Die #NextGen-Community soll nur Themen behandeln, die NICHT bereits durch Themenverantwortliche in anderen Communitys abgedeckt werden.“</div><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal" style="tab-stops: 138.0pt;">Heißt, die Technologie APEX darf nicht mehr mit der NextGen in Verbindung gebracht werden.</div><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal" style="tab-stops: 138.0pt;">Beschluss 2:</div><div class="MsoNormal" style="tab-stops: 138.0pt;">„Für die Nachwuchsförderung bei bestehenden Themen sollen die jeweiligen Themenverantwortlichen der jeweiligen Communitys verantwortlich sein, nicht die #NextGen. Eine Zusammenarbeit und Einbindung in die #NextGen kann bestehen bleiben.“</div><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal" style="tab-stops: 138.0pt;">Heißt für die Technologie APEX, dass Niels aus der Development-Community für APEX für den Nachwuchs verantwortlich ist.</div><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal" style="tab-stops: 138.0pt;">Was macht die NextGen dann zukünftig?</div><div class="MsoNormal" style="tab-stops: 138.0pt;">Die DOAG verfolgt das Ziel, sich neuen, auch Oracle-unabhängigen Technologien zu öffnen und genau hier soll, denke ich, die NextGen in Zukunft der Treiber sein. Weitere Details dazu dann von der NextGen auf der DOAG K+A.</div><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal" style="tab-stops: 138.0pt;">Was bedeutet das für die APEX-Community?</div><div class="MsoNormal" style="tab-stops: 138.0pt;">Ganz ehrlich, zunächst einmal einen großen Rückschlag. Die Leute, die im APEX Umfeld sind und gleichzeitig das gemocht haben, was die NextGen bisher verkörpert hat, diesen jungen Tech Enthusiasts muss die DOAG Development-Community nun schnell und einfach den Einstieg in deren Community bereiten, ansonsten werden diese Leute abspringen und sich anderweitig engagieren. Ich rede hier nicht von mir, sondern von denen die ich auf meiner Reise getroffen und schätzen gelernt habe:</div><div class="MsoNormal" style="tab-stops: 138.0pt;">Jonas, Charlotte, Pierre, Caro, Matthias, Jan, Davide, Ali, Philipp, Felix, Louisa, Rebecca, Maximilian, Victoria, Sebastian, Steven, Christopher, Abby, Florian, um nur einige zu nennen.</div><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal" style="tab-stops: 138.0pt;">Und meine Zukunft?</div><div class="MsoNormal" style="tab-stops: 138.0pt;">Ich werde meinen Spirit und meinem Community-Fokus beibehalten und über andere Wege das Besondere tun um diese einzigartige Community zu bereichern.</div><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal" style="tab-stops: 138.0pt;">Das Ergebnis werdet ihr auf der APEX Connect 2019 sehen, weil ich ab der APEX Connect 2019 für den Track APEX die Verantwortung innehabe. Und hier gibt es natürlich nur ein Ziel: den Community-Spirit an die Spitze zu treiben und mit möglichst vielen APEX-Enthusiasten eine unvergessliche Konferenz auf die Beine zu stellen.</div><div class="MsoNormal" style="tab-stops: 138.0pt;"><br /></div><div class="MsoNormal">Außerdem unterstütze ich das FABE Projekt (<u><span style="color: blue; font-family: &quot;times new roman&quot;; mso-fareast-font-family: &quot;Times New Roman&quot;; mso-fareast-language: DE;">forallabeautiful.earth</span></u>) von Steven Feuerstein und Vincent Morneau aus Sicht der Datenmodellierung.</div><div class="MsoNormal"><br /></div><div class="MsoNormal">Der NextGen-Community selbst kann ich nur alles Gute und viel Erfolg auf dem neuen Weg wünschen. Mir werden diese besonderen Momente immer im Herzen erhalten bleiben und ich bin sehr dankbar dafür solch einen Community-Spirit erlebt haben zu dürfen. Menschen wie Carolin Hagemann, Davide Groppuso, Jonas Gassenmeyer, Matthias Nöll und viele Andere die dem Wort "Community" den Spirit eingehaucht haben den ich geliebt habe.</div><div class="MsoNormal"><br /></div><div class="MsoNormal">Danke für eine GEILE Zeit! Und auch Danke Ingo Sobik für das unterstützen von verrückten Aktionen und dem ganzen DOAG Office diese Aktionen dann am Ende gemeinsam auch in die Tat umgesetzt zu haben.</div><div class="MsoNormal"><br /></div><div class="MsoNormal"><span lang="EN-US" style="mso-ansi-language: EN-US;">Never forget: #POUGTrip, #nextGENrocks #NextGENTrip18 #Roadshow # CommunitySpirit</span></div><div class="MsoNormal"><br /></div><br /><blockquote class="twitter-tweet" data-lang="en"><div dir="ltr" lang="de">Nicht nur das Wetter ist hier fantastisch. Viele Grüße von der <a href="https://twitter.com/hashtag/poug17?src=hash&amp;ref_src=twsrc%5Etfw">#poug17</a> <a href="https://twitter.com/hashtag/pougtrip?src=hash&amp;ref_src=twsrc%5Etfw">#pougtrip</a> Für mehr Insights, klickt auf die Links in den Kommentaren <a href="https://t.co/QaxFR9D4kc">pic.twitter.com/QaxFR9D4kc</a></div>— DOAG NextGen (@DoagNextGen) <a href="https://twitter.com/DoagNextGen/status/903594431298883584?ref_src=twsrc%5Etfw">September 1, 2017</a></blockquote><script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script> <br /><blockquote class="twitter-tweet" data-lang="en"><div dir="ltr" lang="de">Die <a href="https://twitter.com/DoagNextGen?ref_src=twsrc%5Etfw">@DoagNextGen</a>-Community auf einen Blick bei der <a href="https://twitter.com/hashtag/apexconn18?src=hash&amp;ref_src=twsrc%5Etfw">#apexconn18</a>! Vielen Dank, dass Ihr dabei seid! Vielen Dank an die <a href="https://twitter.com/hashtag/Community?src=hash&amp;ref_src=twsrc%5Etfw">#Community</a> für Eure Unterstützung! <a href="https://twitter.com/hashtag/doagnextgen?src=hash&amp;ref_src=twsrc%5Etfw">#doagnextgen</a> <a href="https://twitter.com/hashtag/nextgenrocks?src=hash&amp;ref_src=twsrc%5Etfw">#nextgenrocks</a> <a href="https://twitter.com/hashtag/orclapex?src=hash&amp;ref_src=twsrc%5Etfw">#orclapex</a> <a href="https://twitter.com/hashtag/CommunityEngagement?src=hash&amp;ref_src=twsrc%5Etfw">#CommunityEngagement</a> <a href="https://t.co/glTIsLFTre">pic.twitter.com/glTIsLFTre</a></div>— Jens Krüger (@Stakkatto) <a href="https://twitter.com/Stakkatto/status/989119362496958464?ref_src=twsrc%5Etfw">April 25, 2018</a></blockquote><script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script> <br /><blockquote class="twitter-tweet" data-lang="en"><div dir="ltr" lang="en">The <a href="https://twitter.com/OracleAPEX?ref_src=twsrc%5Etfw">@OracleAPEX</a> Nordic Tour 2018 concludes in stunning Stockholm with an incredible turnout for the second annual <a href="https://twitter.com/hashtag/orclapex?src=hash&amp;ref_src=twsrc%5Etfw">#orclapex</a> day.<br /><br />Thanks to <a href="https://twitter.com/sweoug?ref_src=twsrc%5Etfw">@sweoug</a>, <a href="https://twitter.com/mathiasmag?ref_src=twsrc%5Etfw">@mathiasmag</a> and <a href="https://twitter.com/dan_ekb?ref_src=twsrc%5Etfw">@dan_ekb</a> for making this brilliantly organized event possible!<a href="https://twitter.com/hashtag/APEXday2018?src=hash&amp;ref_src=twsrc%5Etfw">#APEXday2018</a> <a href="https://twitter.com/hashtag/bringitin?src=hash&amp;ref_src=twsrc%5Etfw">#bringitin</a> <a href="https://twitter.com/hashtag/LetsWreckThisTogether?src=hash&amp;ref_src=twsrc%5Etfw">#LetsWreckThisTogether</a> <a href="https://t.co/caXKuXJV8f">pic.twitter.com/caXKuXJV8f</a></div>— Shakeeb Rahman (@shakeeb) <a href="https://twitter.com/shakeeb/status/1033033615750385665?ref_src=twsrc%5Etfw">August 24, 2018</a></blockquote><script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script> Tobias Arnhold tag:blogger.com,1999:blog-6481483192141562388.post-240884475891097415 Fri Oct 26 2018 14:10:00 GMT-0400 (EDT) When SDO_GEOM.SDO_AREA returns a negative value http://oraclequirks.blogspot.com/2018/10/when-sdogeomsdoarea-returns-negative.html Byte64 tag:blogger.com,1999:blog-18037024.post-7478898757835928669 Fri Oct 26 2018 11:14:00 GMT-0400 (EDT) First thoughts about Oracle 18XE db https://svenweller.wordpress.com/2018/10/25/first-thoughts-about-oracle-18xe-db/ <p>On the 20th october the new free Oracle database version 18XE (Express Edition) was anounced (<a href="https://blogs.oracle.com/oracle-database/oracle-database-18c-xe-now-available" rel="nofollow">https://blogs.oracle.com/oracle-database/oracle-database-18c-xe-now-available</a>).</p> <p>I had a first quick look at the database but mostly at the documentation. And here are my thoughts about it.</p> <h2>Restrictions</h2> <ul> <li>Up to 12 GB of user data (previously 11 GB)</li> <li>Up to 2 GB of database RAM (previously 1 GB) &#8211; that is SGA + PGA combined.</li> <li>Up to 2 CPU threads (previously 1 CPU &#8211; but multiple threads?!)</li> <li>Up to 3 Pluggable Databases (this is new)</li> </ul> <p>Not much of an improvement.</p> <p>Previously there was a restriction of only 1 XE per computer (not per VM). The license guide does not mention this restriction anymore. I think it means that we can have multiple XEs on the same machine, but they need to be in different VMs. In the area of cloud based installations, we might not even know if another XE is on the same server. So this is very good news.</p> <h2>missing and included features</h2> <p>The following list does not claim to be complete. But those are features that I find interesting to consider.</p> <p><span style="color:#00ff00;"><strong><span class="glyph">✓ </span></strong></span>multi tenant (up to 3 PDBs)<br /> <span style="color:#ff0000;"><strong><span class="glyph">−</span></strong></span> no plug / unplug into all other databases<br /> <span style="color:#00ff00;"><strong><span class="glyph">✓ </span></strong></span>partitioning<br /> <span style="color:#ff0000;"><strong><span class="glyph">−</span></strong></span> no sharding<br /> <span style="color:#00ff00;"><strong><span class="glyph">✓ </span></strong></span> in-memory column store<br /> <span style="color:#00ff00;"><strong><span class="glyph">✓ </span></strong></span>compression<br /> <span style="color:#00ff00;"><strong><span class="glyph"><span style="color:#ff0000;">−</span> </span></strong></span>no active session history (ASH) and other performance related diagnostics<br /> <span style="color:#00ff00;"><strong><span class="glyph">✓ </span></strong></span>spatial &amp; graph support<br /> <span style="color:#00ff00;"><strong><span class="glyph">✓ </span></strong></span> encryption and redaction<br /> <span style="color:#00ff00;"><strong><span class="glyph">✓ </span></strong></span>Database Vault, FGA<br /> <span style="color:#00ff00;"><strong><span class="glyph"><span style="color:#ff0000;">−</span> </span></strong></span>RAC</p> <p>&nbsp;</p> <p>In general everything that works is allowed! This is different from 11gXE!</p> <p>&nbsp;</p> <h2>Thoughts</h2> <h3>Server/VM limitations</h3> <p>11g XE was limited to one installation per machine. This was specified in the <a href="https://www.oracle.com/technetwork/licenses/database-11g-express-license-459621.html" target="_blank" rel="noopener">11gXE license agreement</a>.</p> <blockquote><p>Any use of the Oracle Database Express Edition is subject to the following limitations;<br /> 1. Express Edition is limited to a single instance<strong> on any server</strong>;<br /> &#8230;</p></blockquote> <p>18cXE is limited to one installation per VM (my interpretation).</p> <p>The restriction that was previously in the license guide is gone, however the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/xeinl/oracle-database-xe-installation-and-execution-restrictions.html" target="_blank" rel="noopener">install guide for linux</a>, still has this passage</p> <header> <blockquote><p><strong><span class="enumeration_section">4.2 </span>Oracle Database XE Installation and Execution Restrictions</strong></p> <p>Only <strong>one installation</strong> of Oracle Database XE can be performed <strong>on a single environment</strong>. &#8230;<br /> To run more than one Oracle Database instance or install more than <strong>one copy of the database software</strong>, upgrade to Oracle Database 18c Personal Edition, Oracle Database 18c Standard Edition 2, or Oracle Database 18c Enterprise Edition.</p></blockquote> </header> <p>The word server was replaced by environment. I interpret that so, that on a single server with multiple environments (e.g. VM images) we can have multiple XE installations.</p> <p>The other restricting factor is that the oracle SID is fixed to XE: I first thought it is hardcoded, but I seen one trustworthy report, where the claim was made that this can be changed. But even if that is possible, it is not clear whether that is allowed.</p> <p>This might be problematic for upgrade scenarios (from 18XE to 19XE). We can not have two active DBs one old 18XE and the new 19XE on the same environment. Maybe not even if one is shut down (because of the only one copy of the db software issue).</p> <p>There is a section in the installation guide, that seems to support this impression: <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/xeinl/exporting-and-importing-data-non-apex-users.html" target="_blank" rel="noopener">Exporting and Importing Data for non-APEX Users</a>. It describes an upgrade scenario via datapump. It specifically mentions to deinstall 11cXE.</p> <blockquote><p>2. Deinstall Oracle Database XE 11.2 if installation of Oracle Database XE 18c is planned on the same system. See <a title="When you deinstall Oracle Database XE, all components, including data files, the database, and the software, are removed." href="https://docs.oracle.com/en/database/oracle/oracle-database/18/xeinl/deinstalling-oracle-database-xe-software-linux.html">Deinstalling Oracle Database XE</a> for more information</p></blockquote> <p>There certainly is some clarification with regards to possible upgrade scenarios needed in the future. For now, only one XE <em>installation</em> on a single virtual box/machine.</p> <h3>Ressource restrictions</h3> <p>The <em>2 CPU threads</em> might be one of the more limiting factors. It feels like a downgrade from the previous version. With hyperthreading a CPU could support easily up to 4 or even 8 threads. This is now limited to two threads. Oracle tries to make sure that we can not trick the limitations by useing advanced hardware.</p> <p>This reminds my of the restriction introduced when switching to SE2 (standard edition 2). SE2 is limited to 16 (user) threads. Which essentially means, we should disable hyperthreading and just use normal CPU power.</p> <p>Especially for web based applications the thread limit seems severe. In APEX we typcially have connection pools that serve up to 10 concurrent connections. Sometimes multiple connections pools (apex, apex_al, apex_pu, apex_rt). We need to rethink the default apex and ords settings. A thread on a CPU usually does not resemble a user process 1:1 but it can serve as a crude first estimation.</p> <p>The <em>12 GB user data</em> means we can not store many document files in the database. For most well structured data this should be reasonably enough. As long as no video, audio or very large photo collections are used. This still leaves the option to store documents as BFILE directly in the file system. This would avoid the data being used for the limited user table space. I&#8217;m not sure if temp and undo space is included in that limit. Main question seems to be, what exactly is measured.</p> <p>Also note that system tablespace is not included in that 12 GB limit.  Unfortunatly I can&#8217;t find the source anymore where I read about this.</p> <p>This query might help measureing how much space is used.</p> <pre class="brush: sql; title: ; notranslate"> select nvl(tablespace_name,' - Total - ') tablespace_name, round(sum(bytes)/1024/1024/1024,1) as size_in_GB from dba_segments where tablespace_name not in ('SYSAUX','SYSTEM') group by rollup(tablespace_name) order by size_in_GB desc; </pre> <p>I think that restriction is quite ok. Although the improvement from 11gXE is only marginal.</p> <h3>In-memory</h3> <p>Since we are only able to use 2 GB RAM in-memory column storage is not really useful. It can be nice to test out this feature or maybe use it on very tiny databases.<br /> It might also be useful in combination with partitioning. I&#8217;m not sure if that is possible, but if we load only the relevant (e.g. current) partitions into memory we might be able to stay within the 2GB limit even when data sizes grow.</p> <p>More of a marketing stunt, that in-memory option is included.</p> <h3>Compression</h3> <p>There is basic and advanced compression. Could be highly useful, especially to save up on disk space. However if you ever plan to upgrade to a Standard Edition, don&#8217;t depend on compression. This also is an EE feature.</p> <p>On the other hand compression might be used to lower the pressure on the 12 GB user data limit. Using advanced compression it should be easily possible to double the size of the user data without reaching the limit.</p> <h3>APEX</h3> <p>APEX is not preinstalled. This is in line with the current 18c db situation. In 11g/12cR1 APEX was preinstalled in the CDB, which was generally considered bad practice. It was changed with 18c (i believe) and XE behaves the same way. Still it would be nice to have an option during install that gives us ORDS and APEX in a PDB.</p> <p>In general APEX (and ORDS) update their versions more frequently than the database,<br /> This might change with the new release cycles of the database however. 19XE is supposed to come out with the 19.3 db version.</p> <h3>upgrade thoughts</h3> <p>We can not directly upgrade from 11gXE to 18cXE. Nor will we be able to upgrade from 18cXE to 19XE. The way to upgrade is to export the data and import it into the new DB.</p> <h3>multitenant</h3> <p>We got 3 PDBs to use. This is very nice. Remember SE2 (standard edition 2) only allows one plugged PDB (+the seed PDB). I still would only put one PDB into major use. But it might become much easier to clone a PDB to try out a few things there, without the need to shut the original PDB down.</p> <p>Unfortunatly it is not possible to plug the XE PDB into a SE2 database. It is possible to plug it into an EE database or even into a Oracle Cloud Db. I believe the SE restriction has to do with the problem that several EE features are available in the XE, which are not available in SE/SE2.</p> <h3>database links</h3> <p>So far I do not know if it is is possible to create a DB link on an XE. I totally expect that it will work. The whole CDB/PDB concept uses DB links.</p> <h3>backup</h3> <p>It is now possible to use RMAN to backup a XE. Recommended!</p> <h3>Tuning and diagnostic tools</h3> <p>At first I heared that ASH and AWR reports will not be possible in XE. But in <a href="https://community.oracle.com/thread/4126673?start=0&amp;tstart=0" target="_blank" rel="noopener">this thread</a> from July 2018 Gerald Venzl explained otherwise</p> <blockquote><p>Will it be legal to use all these options like DIAGNOSTIC+TUNING, ADDM, AWR, ASH in production systems?</p> <p>&#8211;&gt; Yes</p></blockquote> <p>Meanwhile Gerald clarified that the feature did not make it into 18XE. It is now planned for 19XE.</p> <p>The license guide has a detailed <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/xelic/licensing-information.html#GUID-3BD43E8F-53C3-42F0-BBBD-B743FD41F951" target="_blank" rel="noopener">chapter</a> showing which options are available and which not.</p> <p>It would be great to have it. Performance troubleshooting is a topic on any production system. I don&#8217;t expect XE to be an exception.</p> <p>&nbsp;</p> <h3>production ready and other usages</h3> <p>Can we use it for production environments?</p> <p>From a pure license standpoint it is ok. See the quote from the <a href="https://www.oracle.com/database/technologies/appdev/xe/faq.html#prod" target="_blank" rel="noopener">faq</a></p> <blockquote> <h4>Can I use Oracle 18c XE in production?</h4> <div class="cb105w2"> <p>Oracle Database Express Edition does <strong>not restrict in which environment</strong> it can be deployed. However, Oracle Database Express Edition is not supported and does not receive any patches, including security patches. Oracle recommends to run production deployments on fully supported Oracle Database editions or Cloud Services.</p> </div> </blockquote> <p>So &#8211; yes we can! But <em>should</em> we use it in production? Yes and no. For non-critical applications (like if you want to manage your local club data via a XE + apex) that is certainly fine. Although the cloud based alternatives are interesting.  However we will not receive any security fixes and don&#8217;t have oracle support (we are not paying for it, so that is fair). This might be a risk. And that&#8217;s why I wouldn&#8217;t recommend XE for mission critical stuff.</p> <p>The other thing people already speculated, is to use an XE for testing purposes. If it is feature testing, then this we can already do with an EE (enterprise edition) using the OTN Developer  license. Just recently the oracle prebuild developer-vm was upgraded to 18c. If you just want the database then you can use a vagrant-box to to provision the installation: <a href="https://github.com/oracle/vagrant-boxes/tree/master/OracleDatabase/18.3.0" target="_blank" rel="noopener">Oracle DB 18.3</a> . Since XE will not receive any patches, we will not be able to test the newest version of a feature on it. So for pure testing purposes it would be a bad choice.</p> <p>It might be an exellent tool to demonstrate the capability of an oracle database to critical customers however. If you are an ISV you could even use it to give your potential customer a trial version of your software running on an XE.</p> <h2>Conclusion</h2> <p>I&#8217;m very excited that 18cXE finally made it. I&#8217;m also happy that a lot of EE features are available. For demos, talks and presentations I will probably stay with the preconfigured Developer-VM and an EE version of the database. For long-running small side projects, I consider to setup one or two XEs. Additionally it is a great counter argument for all those &#8220;Oracle DB is (too) expensive&#8221; opinions.</p> <h2>useful links</h2> <p>XE Quick Start: <a href="https://www.oracle.com/database/technologies/appdev/xe/quickstart.html" target="_blank" rel="noopener">https://www.oracle.com/database/technologies/appdev/xe/quickstart.html</a></p> <p>XE licensing information: <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/xelic/licensing-information.html#GUID-0F2574A6-360F-4237-8098-17B02FFC3BB3" target="_blank" rel="noopener">https://docs.oracle.com/en/database/oracle/oracle-database/18/xelic/licensing-information.html#GUID-0F2574A6-360F-4237-8098-17B02FFC3BB3</a></p> <p>XE Forum: <a href="https://community.oracle.com/community/groundbreakers/database/developer-tools/oracle_database_express_edition_xe" target="_blank" rel="noopener">https://community.oracle.com/community/groundbreakers/database/developer-tools/oracle_database_express_edition_xe</a></p> <p>Oracle Vagrant-Boxes: <a href="https://blogs.oracle.com/developers/announcing-the-oracle-vagrant-boxes-github-repository" target="_blank" rel="noopener">https://blogs.oracle.com/developers/announcing-the-oracle-vagrant-boxes-github-repository</a></p> <p>Jonathan Lewis about compression: <a href="https://www.red-gate.com/simple-talk/sql/oracle/compression-oracle-basic-table-compression/" target="_blank" rel="noopener">https://www.red-gate.com/simple-talk/sql/oracle/compression-oracle-basic-table-compression/</a></p> svenweller http://svenweller.wordpress.com/?p=7908 Thu Oct 25 2018 15:23:13 GMT-0400 (EDT) Announcing the 2019-2020 ODTUG Board of Directors https://www.odtug.com/p/bl/et/blogaid=834&source=1 Congratulations to the Newly Elected 2019–2020 ODTUG Board of Directors! ODTUG https://www.odtug.com/p/bl/et/blogaid=834&source=1 Thu Oct 25 2018 12:47:57 GMT-0400 (EDT) Maintaining APEX Tree Region Expansion State: UPDATED! http://douggault.com/2018/10/25/maintaining-apex-tree-region-expansion-state-updated/ <p>After my<a href="http://douggault.com/2018/10/15/maintaining-apex-tree-region-expansion-state/"> initial post</a> about this, I had a discussion with John Snyders of <a href="http://hardlikesoftware.com/weblog/" target="_blank" rel="noopener">HardLikeSoftware</a> fame, and it turns out there is a better and more efficient way to maintain the tree state. While what I outlined definitely works, what follows is the &#8220;preferred method&#8221; as it uses more of the built in interfaces. I have therefore implemented this version of the code for APEX 19.1.</p> <p><em><strong>Note: Because the code in this post uses the region.call method and the JavaScript Initialization Attribute, it is likely not to work with versions of APEX  prior to 18.2. </strong></em></p> <h3>The Setup</h3> <p>A couple of house keeping items to mention first.</p> <ul> <li>Make sure you give the tree a <em><strong>unique and meaningful static id</strong></em>. This is just general good practice for any region, but especially if you&#8217;re going to be using any type of JavaScript to control it. It also makes your code more readable.</li> <li>Make sure the tree region has a <em><strong>Node Value Column assigned that is a unique key</strong></em>. The reason for this is two-fold: <ul> <li>If the Node Value is not unique you&#8217;ll get into a situation where the actual nodes and their state may clash. For instance, if two nodes have the same Value and one is expanded and the other isn&#8217;t,  when you save and then reinstate the tree state, you may get unexpected results.</li> <li>If the Node Value is not set at all, then the NodeAdapter will not be able to identify a given node and save/reinstate its state.</li> </ul> </li> </ul> <h3>Saving the Expansion State</h3> <p>As before, the first step is to save the current expansion state of the tree any time you navigate away from the page containing it. Do so by creating a Dynamic Action triggered on Page Unload and execute the following JavaScript:</p> <pre class="brush: jscript; title: ; notranslate">var ids = apex.region(&quot;emp&quot;).call(&quot;getExpandedNodeIds&quot;).join(&quot;:&quot;); apex.storage.getScopedSessionStorage({usePageId: true, useAppId: true}).setItem(&quot;treeExpansionState&quot;, ids); </pre> <ul> <li><strong>Line 1:</strong> Notice that this time, we&#8217;re going to be using the <strong><span style="font-family: terminal, monaco, monospace;">apex.region</span></strong> interface to get a handle on the tree using its static id. Once we have a handle on the tree object, we call the <strong><span style="font-family: terminal, monaco, monospace;">getExpandedNodeIds</span></strong> method and then join the elements of that array into a single string using a colon (&#8216;:&#8217;).<br /> <em style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;"><strong>Note: </strong> The character you use to join the elements of the array should be chosen carefully. Don&#8217;t use a character that might appear as part of the Node Value.</em></li> <li><strong>Line 2:</strong> We&#8217;re still using the <strong style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;"><span style="font-family: terminal, monaco, monospace;">apex.storage</span></strong><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;"> namespace to save the values to the browser, but instead of setting the cookie directly, it uses the </span><a style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;" href="https://docs.oracle.com/database/apex-18.2/AEAPI/apex-storage-namespace.htm#AEAPI-GUID-58C57C6F-C28B-4692-B3C6-77F5CA3C5E82" target="_blank" rel="noopener"><strong><span style="font-family: terminal, monaco, monospace;">getScopedSessionStorage</span></strong></a><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;"> wrapper.  In the code above, the call is using both </span><strong style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;"><span style="font-family: terminal, monaco, monospace;">PageId</span></strong><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;"> and </span><strong style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;"><span style="font-family: terminal, monaco, monospace;">AppId</span></strong><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;"> to prefix the session key named </span><span style="font-family: terminal, monaco, monospace;"><strong>treeExpansionState</strong></span><span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;">.  Assuming we are running an application with an ID of 1234 and the tree exists on page 100, the session storage variable name would appear as: </span></li> </ul> <p><code>100.1234.treeExpansionState</code></p> <p>Something to note though; If your tree is defined on a global page and displayed on various other pages (as is the case with the APEX ORDS REST Workshop), you&#8217;ll want to set <strong><span style="font-family: terminal, monaco, monospace;">usePageId: false</span></strong>. Otherwise, even though the tree state is being saved, its context will be page specific and will only be reinstated when viewing the tree component from that page. Setting the value to false will omit the page id from the key name so that it will not be page specific.</p> <h3>Reinstating the Expansion State</h3> <p>In my prior example I used an onLoad Dynamic Action to reinstate the tree to its former expansion state. While this is perfectly viable, it&#8217;s not the most efficient. Instead it&#8217;s preferable to us the JavaScript Initialization Code for the tree object. To do this, navigate to the Attributes section of the tree region and use the following code in the Advanced &gt; JavaScript Initialization Code region:</p> <pre class="brush: jscript; title: ; notranslate"> function(options) { options.makeNodeAdapter = function(data, types, hasIdentity) { var a, ids = apex.storage.getScopedSessionStorage( { usePageId: true, useAppId: true} ).getItem(&quot;treeExpansionState&quot;); if ( ids ) { ids = ids.split(&quot;:&quot;); } a = $.apex.treeView.makeDefaultNodeAdapter( data, types, hasIdentity, ids ); return a; } return options; }</pre> <p>The Initialization Code block takes in an <span style="font-family: terminal, monaco, monospace;"><strong>options</strong></span> object for the tree, modifies it and then returns it. In our case, we&#8217;re modifying the default NodeAdapter.</p> <ul> <li><strong>Line 2</strong> sets up the function to that will be called to return the NodeAdapter</li> <li><strong>Line 3</strong> creates a variable that will hold the finished adapter</li> <li><strong>Line 4</strong> uses <strong><span style="font-family: terminal, monaco, monospace;">apex.storage</span></strong> to retrieve the value of the <strong><span style="font-family: terminal, monaco, monospace;">treeExpansionState</span></strong> key.</li> <li><strong>Lines 5-7</strong> check to see if the the Key actually contained anything, and if it does, splits the string back into an array that will be used by the NodeAdapter</li> <li><strong>Line 8</strong> creates the NodeAdapter by using the details passed into the function as well as the array <strong><span style="font-family: terminal, monaco, monospace;">ids</span></strong> which holds the list of expanded nodes</li> <li><strong>Line 9</strong> returns the adaptor</li> <li><strong>Line 11</strong> returns the <strong><span style="font-family: terminal, monaco, monospace;">options</span></strong> object back to the tree</li> </ul> <p>By using the Advanced JavaScript Initialization Code, the tree state is set as the tree is drawn instead being a second step after the page is &#8220;ready&#8221;. Doing it this way, you can integrate it with any other logic that might affect the tree&#8217;s options object.</p> <p>I hope by making this second post I haven&#8217;t confused the issue. As I said &#8211; Both should work but this version is cleaner and more efficient.</p> Doug Gault http://douggault.com/?p=526 Thu Oct 25 2018 12:44:09 GMT-0400 (EDT) APEX client side error messages - apex.message.showErrors https://www.apex-at-work.com/2018/10/apex-client-side-error-messages.html Since APEX 5.1 we have the ability to create client side messages without the requirement to use a plugin or custom code to create nice looking client side messages.<br /><br />For that requirement the APEX team created the <a href="https://docs.oracle.com/database/apex-5.1/AEAPI/apex-message-namespace.htm" target="_blank"><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">apex.message</span></a> library.<br /><br />This library provides the same look and feel as if you would create a message out of your Page Designer &gt; Validation Area.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-2w5woivmwr0/W9Fw86NADGI/AAAAAAAACBc/ikr0STXvmc09saC_3jKgNvvrT55oO2wrQCLcBGAs/s1600/Page_Designer-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="584" data-original-width="465" height="400" src="https://4.bp.blogspot.com/-2w5woivmwr0/W9Fw86NADGI/AAAAAAAACBc/ikr0STXvmc09saC_3jKgNvvrT55oO2wrQCLcBGAs/s400/Page_Designer-2.png" width="317" /></a></div><br /><br />In this example I will tell you something about a more advanced way to use the client side error messages.<br /><br />As the documentation says this is the default way to create a client side error message:<br /><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">/* General page error message */ </span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">apex.message.showErrors([</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">{</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">type: "error",</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">location: "page",</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">message: "Page error has occurred!",</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">unsafe: false</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">}</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">]);</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">&nbsp; /* Item error message */ apex.message.showErrors([</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">{</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">type: "error",</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">location: [ "page", "inline" ],</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">pageItem: "P1_ITEM",</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">message: "Value is required!",</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">unsafe: false</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">}</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">]); </span><br /><br />Example for a page error message:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-rdF1jv6mVeY/W9FvB0LEtjI/AAAAAAAACBM/_T0QfhSws2MADzloTgrbnDJUWttB75FpgCLcBGAs/s1600/Page_Designer1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="334" data-original-width="893" height="236" src="https://4.bp.blogspot.com/-rdF1jv6mVeY/W9FvB0LEtjI/AAAAAAAACBM/_T0QfhSws2MADzloTgrbnDJUWttB75FpgCLcBGAs/s640/Page_Designer1.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-GcZ-zmUJAPs/W9FvB2IlVMI/AAAAAAAACBI/QZQ_izUIfusNbROz2sWgogHyWeyWgWKoACLcBGAs/s1600/Page_Designer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="458" data-original-width="950" height="307" src="https://1.bp.blogspot.com/-GcZ-zmUJAPs/W9FvB2IlVMI/AAAAAAAACBI/QZQ_izUIfusNbROz2sWgogHyWeyWgWKoACLcBGAs/s640/Page_Designer.png" width="640" />&nbsp;</a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-mW7m-e0hBZ0/W9FxaqKurSI/AAAAAAAACBk/RHvU_OUSHH85uHfrowp9A0rXKabaZo55gCLcBGAs/s1600/test.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="211" data-original-width="534" height="157" src="https://4.bp.blogspot.com/-mW7m-e0hBZ0/W9FxaqKurSI/AAAAAAAACBk/RHvU_OUSHH85uHfrowp9A0rXKabaZo55gCLcBGAs/s400/test.png" width="400" /></a></div><br />In my example I want to check more then one item. For that I created an array including all item names I wanted to check. Within a "FOR" loop I run through every item and created an error message if the value was NULL. If no error occurred I run another custom dynamic action.<br /><br /><pre><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">apex.message.clearErrors();<br /><br />var chkErr = 0;<br />var arr = [<br /> 'P1_STRASSE', <br /> 'P1_HAUS_NR',<br /> 'P1_PLZ', <br /> 'P1_ORT', <br /> 'P1_ITEM_XYZ'<br />];<br /><br />for (var i in arr) {<br /> if ($v(arr[i]).length == 0) {<br /> apex.message.showErrors([<br /> {<br /> type: apex.message.TYPE.ERROR,<br /> location: ["inline"],<br /> pageItem: arr[i],<br /> message: "</span><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">Value is required!</span>",<br /> unsafe: false<br /> }<br /> ]);<br /> chkErr = 1;<br /> } <br />}<br /><br />if ( chkErr == 0 ) {&nbsp;<br /> /* Custom dynamic action call when no error occurred */<br /> apex.event.trigger(document, 'customDA', [{customAttribute:'1'}]); <br />}<br /></span></pre>You want to know more? Check out the documentation and this series of blog posts by Martin D'Souza:<br /><a href="https://www.talkapex.com/2018/03/custom-apex-notification-messages/">https://www.talkapex.com/2018/03/custom-apex-notification-messages/</a><br /><a href="https://www.talkapex.com/2018/03/how-to-save-page-data-but-show-errors-in-apex/">https://www.talkapex.com/2018/03/how-to-save-page-data-but-show-errors-in-apex/</a> Tobias Arnhold tag:blogger.com,1999:blog-6481483192141562388.post-6939470450599211435 Thu Oct 25 2018 03:03:00 GMT-0400 (EDT) Expose your Local Development Environment to the outside world with Ngrok http://feedproxy.google.com/~r/TechnologyRedefinedToTheBeyond/~3/BDVcH7RY_40/expose-your-local-development.html <div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-VKzJyxGK0Ys/W9EyN8Y-H_I/AAAAAAAAQKY/UFxr1dwLUeMd4wB1Obha93KVscElC6jsQCLcBGAs/s1600/ngrok.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="500" data-original-width="1000" height="320" src="https://1.bp.blogspot.com/-VKzJyxGK0Ys/W9EyN8Y-H_I/AAAAAAAAQKY/UFxr1dwLUeMd4wB1Obha93KVscElC6jsQCLcBGAs/s640/ngrok.jpg" width="640" /></a></div><div style="background-color: white; box-sizing: border-box; color: rgba(35, 37, 40, 0.7); font-family: &quot;Noto Serif&quot;, &quot;Times New Roman&quot;, serif; font-size: 19px; line-height: 35px; margin-bottom: 45px; padding: 0px;">When we develop on localhost, we usually use some kind of simple HTTP server like node, our Oracle database,APIs, webhooks, Callback Urls or whatever.<br />This is all good and we are all pretty happy about that. We have access to our app using our fancy&nbsp;<code style="background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; box-sizing: border-box; color: #24292e; font-family: monospace, monospace; font-size: 1em; padding: 0px;">http://localhost</code>&nbsp;url. We are happy, but&nbsp;<span style="box-sizing: border-box; font-weight: 600;">alone</span>.</div><div style="background-color: white; box-sizing: border-box; line-height: 35px; margin-bottom: 45px; margin-top: 45px; padding: 0px;"><div style="color: rgba(35, 37, 40, 0.7); font-family: &quot;noto serif&quot;, &quot;times new roman&quot;, serif; font-size: 19px;">What if you would like to share your app to a colleague that is not on the same network as yours ? What if you need to check your app on an SSL connection? What if you wanted an external system to pass you a process invoked by a method ?</div><div style="color: rgba(35, 37, 40, 0.7); font-family: &quot;noto serif&quot;, &quot;times new roman&quot;, serif;"><span style="font-size: x-large;">ngrok to the rescue</span></div><div style="color: rgba(35, 37, 40, 0.7); font-family: &quot;noto serif&quot;, &quot;times new roman&quot;, serif; font-size: 19px;"><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif;"><a href="https://ngrok.com/" target="_blank">Ngrok</a>&nbsp;</span><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif;">is a simple “free” service that can help you with that. Here’s some of the features that it provides:</span></div><ol style="box-sizing: border-box; font-family: &quot;Noto Serif&quot;, &quot;Times New Roman&quot;, serif; font-size: 19px; line-height: 35px; margin: 45px 0px 45px 70px; padding: 0px;"><li style="box-sizing: border-box; color: rgba(35, 37, 40, 0.7); margin: 0px 0px 20px; padding: 0px 15.75px;">Expose your locally hosted app/website to the outside world by providing you a&nbsp;<code style="background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; box-sizing: border-box; color: #24292e; font-family: monospace, monospace; font-size: 1em; padding: 0px;">http(s)://{something}.ngrok.io</code>&nbsp;url.</li><li style="box-sizing: border-box; color: rgba(35, 37, 40, 0.7); margin: 0px 0px 20px; padding: 0px 15.75px;">Allows you to have an SSL connection to your localhost environment.</li><li style="box-sizing: border-box; color: rgba(35, 37, 40, 0.7); margin: 0px 0px 20px; padding: 0px 15.75px;">Inspect/replay the requests made to your local environment</li><li style="box-sizing: border-box; color: rgba(35, 37, 40, 0.7); margin: 0px 0px 20px; padding: 0px 15.75px;">Custom subdomain (required a premium account)</li><li style="box-sizing: border-box; color: rgba(35, 37, 40, 0.7); margin: 0px 0px 20px; padding: 0px 15.75px;">Password protect your exposed service</li><li style="box-sizing: border-box; color: rgba(35, 37, 40, 0.7); margin: 0px 0px 20px; padding: 0px 15.75px;"><a href="https://ngrok.com/product" target="_blank">And more...</a></li></ol><div style="color: rgba(35, 37, 40, 0.7);"><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: x-large;">Installing</span><br /><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;">To install, you have different options to choose from</span></div><div style="color: rgba(35, 37, 40, 0.7);"><ol style="box-sizing: border-box; font-family: &quot;Noto Serif&quot;, &quot;Times New Roman&quot;, serif; font-size: 19px; line-height: 35px; margin: 45px 0px 45px 70px; padding: 0px;"><li style="box-sizing: border-box; margin: 0px 0px 20px; padding: 0px 15.75px;"><a href="https://ngrok.com/download" target="_blank">The official way</a>: Downloading a zip file and unzip it</li><li style="box-sizing: border-box; margin: 0px; padding: 0px 15.75px;">Using NPM/Yarn :&nbsp;<code style="background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; box-sizing: border-box; color: #24292e; font-family: monospace, monospace; font-size: 1em; padding: 0px;">npm install ngrok -g</code>. Package information <a href="https://www.npmjs.com/package/ngrok" target="_blank">here</a></li></ol></div></div><div><div style="background-color: white; box-sizing: border-box; color: rgba(35, 37, 40, 0.7); font-family: &quot;Noto Serif&quot;, &quot;Times New Roman&quot;, serif; font-size: 19px; line-height: 35px; margin-bottom: 45px; margin-top: 45px; padding: 0px;">It’s a good idea here to create a free account in order to increase the connections rate limit from 20 to 40. The process is quick and really easy.</div><div style="background-color: white; box-sizing: border-box; color: rgba(35, 37, 40, 0.7); line-height: 35px; margin-bottom: 45px; margin-top: 45px; padding: 0px;"><div style="font-family: &quot;noto serif&quot;, &quot;times new roman&quot;, serif;"><span style="font-size: x-large;">Exposing our localhost:8080(can be any port) port</span></div><div class="separator" style="clear: both; font-family: &quot;noto serif&quot;, &quot;times new roman&quot;, serif; text-align: center;"><a href="https://4.bp.blogspot.com/-M_2Myemde1Y/W9E5IKrtvZI/AAAAAAAAQKk/ba7lRuFUgekiUecWGkAYoRDqdjDLhnRXgCLcBGAs/s1600/ngrok_demo.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="431" data-original-width="605" height="452" src="https://4.bp.blogspot.com/-M_2Myemde1Y/W9E5IKrtvZI/AAAAAAAAQKk/ba7lRuFUgekiUecWGkAYoRDqdjDLhnRXgCLcBGAs/s640/ngrok_demo.gif" width="640" /></a></div><div style="font-family: &quot;noto serif&quot;, &quot;times new roman&quot;, serif;"><span style="font-size: large;"><br /></span></div><div style="box-sizing: border-box; font-family: &quot;Noto Serif&quot;, &quot;Times New Roman&quot;, serif; font-size: 19px; line-height: 35px; margin-bottom: 45px; margin-top: 45px; padding: 0px;">You can see that ngrok gives us now access to 3 urls:</div><div style="font-family: &quot;noto serif&quot;, &quot;times new roman&quot;, serif;"><span style="font-size: large;"></span></div><ol style="box-sizing: border-box; font-family: &quot;Noto Serif&quot;, &quot;Times New Roman&quot;, serif; font-size: 19px; line-height: 35px; margin: 45px 0px 45px 70px; padding: 0px;"><li style="box-sizing: border-box; margin: 0px 0px 20px; padding: 0px 15.75px;">http://4fc79cf7.ngrok.io : Our webapp on standard http protocol</li><li style="box-sizing: border-box; margin: 0px 0px 20px; padding: 0px 15.75px;">https://4fc79cf7.ngrok.io : Our webapp on secure https protocol</li><li style="box-sizing: border-box; margin: 0px; padding: 0px 15.75px;">http://127.0.0.1:4040 : A nice web interface to inspect our tunnel</li></ol><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: x-large;">Password protect our tunnel</span></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;">Here’s how you can add a username/password authentication to your tunnel</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-fP80sUOWahc/W9E6QVH_zmI/AAAAAAAAQKw/iao8C_UAPHMyWrRCSBm6LvTZLX4y7vFOQCLcBGAs/s1600/Screen%2BShot%2B2018-10-25%2Bat%2B3.35.57%2BAM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="55" data-original-width="304" height="72" src="https://1.bp.blogspot.com/-fP80sUOWahc/W9E6QVH_zmI/AAAAAAAAQKw/iao8C_UAPHMyWrRCSBm6LvTZLX4y7vFOQCLcBGAs/s400/Screen%2BShot%2B2018-10-25%2Bat%2B3.35.57%2BAM.png" width="400" /></a></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;"><br /></span></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;">This will protect your tunnel with the login&nbsp;</span><span style="box-sizing: border-box; font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px; font-weight: 600;">hello</span><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;">&nbsp;and password&nbsp;</span><span style="box-sizing: border-box; font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px; font-weight: 600;">world</span></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: x-large;">Exposing SSH server on port 22</span></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;">Here’s how you can expose your local machine SSH port to the world. Pretty dangerous but do that if you know what you’re doing.</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-m7oIhxnC9xU/W9E6vHr67VI/AAAAAAAAQK4/tL6m7pQw4CQ5UOSolHhhN6Ga5_-B471OQCLcBGAs/s1600/Screen%2BShot%2B2018-10-25%2Bat%2B3.38.19%2BAM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="66" data-original-width="239" height="110" src="https://3.bp.blogspot.com/-m7oIhxnC9xU/W9E6vHr67VI/AAAAAAAAQK4/tL6m7pQw4CQ5UOSolHhhN6Ga5_-B471OQCLcBGAs/s400/Screen%2BShot%2B2018-10-25%2Bat%2B3.38.19%2BAM.png" width="400" /></a></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;"><br /></span></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: x-large;">What about using Virtual Hosts?</span></div><div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;">You just need to include the host-header flag&nbsp;</span></div></div><div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;">For example, if I wanna expose the virtual host/docker: <i><b>demo.local.vh:80</b></i>&nbsp;</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-hdTJevn7GBg/W9E87YeSFLI/AAAAAAAAQLY/1g--xNxLNYIGwZatGMPRHlXmNVTYVR-fgCLcBGAs/s1600/Screen%2BShot%2B2018-10-25%2Bat%2B3.47.37%2BAM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="63" data-original-width="310" height="81" src="https://2.bp.blogspot.com/-hdTJevn7GBg/W9E87YeSFLI/AAAAAAAAQLY/1g--xNxLNYIGwZatGMPRHlXmNVTYVR-fgCLcBGAs/s400/Screen%2BShot%2B2018-10-25%2Bat%2B3.47.37%2BAM.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;"><br /></span></div><div><div><span style="font-family: &quot;noto&quot; serif , &quot;times new roman&quot; , serif; font-size: x-large;">More information?</span></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;">You can access to the <a href="https://ngrok.com/docs" target="_blank">docs</a> or read <a href="https://ngrok.com/docs#faq" target="_blank">FAQs</a></span></div><div><span style="font-family: &quot;noto serif&quot;, &quot;times new roman&quot;, serif; font-size: 19px;"><i>Free user plan:</i></span></div><div><ol style="box-sizing: border-box; font-family: &quot;Noto Serif&quot;, &quot;Times New Roman&quot;, serif; font-size: 19px; line-height: 35px; margin: 45px 0px 45px 70px; padding: 0px;"><li style="box-sizing: border-box; margin: 0px 0px 20px; padding: 0px 15.75px;">HTTP/TCP tunnels on random URLs/ports</li><li style="box-sizing: border-box; margin: 0px 0px 20px; padding: 0px 15.75px;">1 online ngrok process&nbsp;</li><li style="box-sizing: border-box; margin: 0px 0px 20px; padding: 0px 15.75px;">4 tunnels per ngrok process</li><li style="box-sizing: border-box; margin: 0px 0px 20px; padding: 0px 15.75px;">40 connections / minute (error 429)&nbsp;</li></ol><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: x-large;">Conclusion</span><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: large;">&nbsp;</span></div></div><div><span style="font-family: &quot;noto serif&quot; , &quot;times new roman&quot; , serif; font-size: 19px;">Ngrok is a powerful tool to expose your local services through secure tunnels.You can use it to expose web servers,API Rest,SSH, databases&nbsp; and many others for free.</span></div><div><span style="font-family: &quot;noto&quot; serif , &quot;times new roman&quot; , serif;"><span style="font-size: 19px;">Happy Apexing.!</span></span></div><div></div></div></div></div></div><img src="http://feeds.feedburner.com/~r/TechnologyRedefinedToTheBeyond/~4/BDVcH7RY_40" height="1" width="1" alt=""/> TopNedd tag:blogger.com,1999:blog-6696745355942763636.post-110880385028717958 Thu Oct 25 2018 00:23:00 GMT-0400 (EDT) Custom software development – possible and desirable, with the right tools https://insum.ca/custom-software-development-possible-desirable-right-tools/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/10/Custom-software-development-possible-desirable-right-tools-100x100.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Custom software development possible and desirable with the right tools" srcset="https://insum.ca/wp-content/uploads/2018/10/Custom-software-development-possible-desirable-right-tools-100x100.png 100w, https://insum.ca/wp-content/uploads/2018/10/Custom-software-development-possible-desirable-right-tools-150x150.png 150w, https://insum.ca/wp-content/uploads/2018/10/Custom-software-development-possible-desirable-right-tools-600x600.png 600w, https://insum.ca/wp-content/uploads/2018/10/Custom-software-development-possible-desirable-right-tools-300x300.png 300w, https://insum.ca/wp-content/uploads/2018/10/Custom-software-development-possible-desirable-right-tools-50x50.png 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p>In any company, one of IT’s primary responsibilities is to continually increase the profitability of the organization’s information. In that perspective, IT innovation is vital to the company’s future. Innovation is necessary for survival, and sometimes, custom software development is the fastest way to achieve what’s necessary.</p> <h2>ERPs can’t do it all</h2> <p>Back office infrastructure is one of the areas that constantly needs IT innovation.  Most large companies have sophisticated Enterprise Resource Planning systems (ERPs). But, it’s unlikely that the needs of such companies are 100% met by their ERP system.  Not that I’ve seen at least. There is always tweaking. Given the right tools, custom software development by internal staff, possibly aided by an experienced consulting firm can be a shortcut that avoids expensive overhaul or purchase and licensing of new software.</p> <p>Not everything needs to be changed, of course. Accounting functions like general ledger don’t really change over time. But things like accounts receivable and accounts payable, frequently need extra development to meet new business needs. Just as an example, at some point in time, a company’s accounts payable typically requires interfaces with banks to do EFT (Electronic Fund Transfers).</p> <p>This is nothing exceptional, just normal evolution. But it is something that the ERP may not be able to handle, and that custom software development can.</p> <h2>Resistance</h2> <p>But, developmental changes to extend the capabilities of the ERP, inevitably come up against some resistance. Understandably so. Administrators in some companies are signing checks for millions annually just for licensing costs. Whether it’s for SAP, Oracle E-business Suite or others, these administrators are saying, “we’ve paid all this out in licensing fees, why do have to pay more for more development?”</p> <p>To that, I would answer that as businesses develop they become specialized, more and more unique. These are their strengths, their unique differentiating factors. The internal workings of a business must reflect that, otherwise, how can a business stay competitive? This is an area in which a generic system can’t always give you what you need. Sometimes what needs to be changed seems very simple and logical, yet the system still can’t provide for it.</p> <h2>An Example</h2> <p>One manufacturing company I developed for couldn’t work with the ERP’s Manufacturer’s screens. This particular series of screens didn’t fit the client&#8217;s needs. They were too complex for the simple operations required. When one of their products got to the end of the production line, it simply had to be scanned to indicate that its treatment was completed. This would close the work order to prepare for product expedition. This is pretty standard, but the scanning part made it incompatible with the ERP. In this particular case, the System was Oracle E-business Suite (EBS). Originally, they had developed a workaround with an older application development platform called Oracle Forms, but when the time came to upgrade their version of ERP, that Form could not be upgraded.</p> <h2>Custom Application Development With Oracle APEX</h2> <p>I recommended redoing the screen in Oracle APEX, the web-based application development platform that comes with all versions of the Oracle Database. They were pleased with the suggestion because it meant they didn’t have to buy additional software or pay out new licensing. Furthermore, Oracle APEX enables you to very quickly develop a proof of concept. I had a working version ready for them within a week.</p> <p>APEX was also a good fit for this IT team.  They were used to developing in PL/SQL, which APEX is based on, and had some knowledge of JavaScript. Experienced in EBS and Oracle Forms development, they understood the principles behind APEX and eagerly used it to try new things on other projects they had waiting.</p> <p>It does sometimes happen that companies will brush off APEX as a solution. Once, I even get this surprising objection from a company running an EBS system: “well, we already support several development technologies, and we are not going to support another”. I didn’t laugh, but it took some effort.</p> <h2>Conclusion</h2> <p>APEX is web-based and ideally suited to custom software development needs. You can use it to create extensions or brand-new applications that can help your company achieve their business goals without an extravagant investment in time or capital.</p> <p>Oracle APEX really is an application development platform that deserves your attention.</p> <p>Find out more about Oracle APEX &#8211; read &#8220;<a href="https://insum.ca/top-5-questions-people-ask-about-apex/">Top 5 Questions People Ask About APEX</a>&#8221;</p> <p>Develop in EBS? Read &#8220;<a href="https://insum.ca/top-use-cases-e-business-suite-oracle-apex/">Top 3 use cases of EBS Extensions With Oracle APEX</a>&#8221;</p> <p>Develop in Oracle Forms? read our series on <a href="https://insum.ca/oracle-forms-and-reports-modernization-forms-challenges/">Oracle Forms Modernization</a></p> <p>Want to learn more? <a href="https://insum.ca/contact/">Contact Us!</a></p> <p>The post <a rel="nofollow" href="https://insum.ca/custom-software-development-possible-desirable-right-tools/">Custom software development &#8211; possible and desirable, with the right tools</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Jocelyn Coté https://insum.ca/?p=13371 Tue Oct 23 2018 10:36:12 GMT-0400 (EDT) Instalacja Oracle XE 18c na Linuxie http://apex.dbe.pl/2018/10/instalacja-oracle-xe-18c-na-linuxie.html Na tą chwilę Oracle udostępnił instalki tylko i wyłącznie na linuxa. Nie jest to nic odosobnionego. Taka sytuacja powtarza się przy każdym wypuście wersji XE. Użytkownicy Windowsa będą musieli poczekać jeszcze kilka miesięcy.<br /> Podczas instalacji użyłem CentOS-a w wersji 7.5 <br /> <br /> <br /> <br /> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://4.bp.blogspot.com/-RT2n0KlIcZI/W87y1jD_N0I/AAAAAAAANIE/1Uxj4VYSnKYtCC2ttATFLuNHRDZtzUSFQCLcBGAs/s1600/xe18c.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="319" data-original-width="341" height="299" src="https://4.bp.blogspot.com/-RT2n0KlIcZI/W87y1jD_N0I/AAAAAAAANIE/1Uxj4VYSnKYtCC2ttATFLuNHRDZtzUSFQCLcBGAs/s320/xe18c.png" width="320" /></a></div> <br /> <br /> <br /> <b>Wymagania:</b><br /> Minimum 1GB RAM zalecane 2GB<br /> Minimum 10GB miejsca na dysku<br /> Pamięć SWAP minimum 2GB lub dwykrotność pamięci RAM (należy wybrać mniejszą wartość)<br /> Parametry kernela. Lista <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/xeinl/server-component-kernel-parameter-requirements.html">tutaj</a>. Zbytnio się nimi nie musimy przejmować ustawią się same podczas instalacji.<br /> Systemy operacyjne -&gt; <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/ladbi/operating-system-checklist-for-oracle-database-installation-on-linux.html#GUID-E5C0A90E-7750-45D9-A8BC-C7319ED934F0">tutaj </a>lista<br /> <br /> <b>Kroki instalacji</b><br /> <br /> 1. Instalację Oracle XE 18C wykonujemy z pozycji uzytkownika, który posiada możliwość uruchamiania programów jako sudo<br /> <br /> 2. Tworzymy folder install.<br /> <pre style="background-color: #bbbbbb;">mkdr /install #wejscie do stworzonego flderu cd /install </pre> <br /> 3. Ze strony <a href="https://www.oracle.com/technetwork/database/database-technologies/express-edition/downloads/index.html">https://www.oracle.com/technetwork/database/database-technologies/express-edition/downloads/index.html</a> pobieramy wersję instalacyjną Oracle Database 18c Express Edition for Linux x64<br /> <br /> 4. Pobieranie bazy prekonfiguracyjnej.<br /> <pre style="background-color: #bbbbbb;">curl -o oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm https://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm </pre> 5. Instalacja pobranej bazy.<br /> Chodzi o to, że przed instalacją system musi sprawdzić zależności i stan niezbędnych bibliotek w razie potrzeby je doinstalować. Dodatkowo paczka ta tworzy niezbędnych użytkowników i wymagane grupy.<br /> <pre style="background-color: #bbbbbb;">yum -y localinstall oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm </pre> 6. Właściwa instalacja.<br /> <pre style="background-color: #bbbbbb;">yum -y localinstall oracle-database-xe-18c-1.0-1.x86_64.rpm </pre> 7. Usuwanie pobranej wcześniej instalki<br /> <pre style="background-color: #bbbbbb;">rm oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm rm oracle-database-xe-18c-1.0-1.x86_64.rpm </pre> 8. Tworzenie i konfiguracja bazy<br /> Jeżeli uruchomimy domyślną instalację to instalator zbuduje CDB o nazwie XE z dodatkową jedną PDB o nazwie XEPDB1 z listenerem nasłuchującym na porcie 1521 oraz Enterprise Managerem Express na porcie 5500<br /> Jeżeli coś chcielibyśmy zmienić to w tym pliku /etc/sysconfig/oracle—xe–18c.conf można niektóre elementy dostosować.<br /> Proponuję zastosować domyślną instalację. W tym celu uruchamiamy następującą komendę:<br /> <pre style="background-color: #bbbbbb;">/etc/init.d/oracle-xe-18c configure </pre> W odpowiedzi dostajemy pytanie o hasło dla użytkowników SYS, SYSTEM i PDBADMIN. Tak więc wprowadzamy TAJNE_HASLO a następnie je potwierdzamy.<br /> Po kilku minutach proces tworzenia i konfiguracji bazy się kończy<br /> <br /> 9. Podłączenie do bazy.<br /> Aby tego dokonać użytkownik linuxowy z którego będzie próba podłączenia musi posiadać niezbędne zmienne środowiskowe. Aby je przypisać należy w terminalu wprowadzić następujące komendy: <br /> <pre style="background-color: #bbbbbb;">export ORACLE_SID=XE export ORAENV_ASK=NO . /opt/oracle/product/18c/dbhomeXE/bin/oraenv ORACLE_HOME = [] ? /opt/oracle/product/18c/dbhomeXE </pre> Docelowo proponuję aby dodać do .bash_profile odpowiednie wpisy aby po restarcie komputera wszystko było ustawione. <br /> <pre style="background-color: #bbbbbb;">export ORACLE_SID=XE export ORAENV_ASK=NO export ORACLE_HOME=/opt/oracle/product/18c/dbhomeXE . /opt/oracle/product/18c/dbhomeXE/bin/oraenv PATH=$PATH:$ORACLE_HOME/bin </pre> 10. Ustawienie autostartu Oracle po restarcie systemu.<br /> Jeżeli chcemy aby nasza baza wstawała wraz systemem należy włączyć odpowiedni serwis. W tym celu uruchamiamy następującą komendę: <br /> <pre style="background-color: #bbbbbb;">systemctl daemon-reload systemctl enable oracle-xe-18c </pre> 11. Próba podłączenia się do bazy przez SQLPLUS-a: <br /> <pre style="background-color: #bbbbbb;">sqlplus sys/TAJNE_HASLO as sysdba </pre> Jeżeli widzisz znak zchęty sql&gt; to znaczy że wszystko zostało poprawnie zrobione : ) ) tag:blogger.com,1999:blog-7531463720728239813.post-1365791882872894626 Tue Oct 23 2018 06:13:00 GMT-0400 (EDT) Installing Oracle Apex 18.2 into my container http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/GSTiHTzeWE4/installing-oracle-apex-182-into-my.html <h2>Go docker, go... </h2>I run this installation from inside the docker container. The reason for this decision is, that I always face some issues when updateing the images from a windows system. So I open a bash shell in the container and navigate to the apex directory. You have missed something earlier, if there is no Apex directory in your container.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-iWa80fmggDk/W8yDdmEyjlI/AAAAAAAAJW8/b2iO_NjWLGwCjtt93z2PspMALJzz1hIGACLcBGAs/s1600/apexdir.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="179" data-original-width="770" height="92" src="https://1.bp.blogspot.com/-iWa80fmggDk/W8yDdmEyjlI/AAAAAAAAJW8/b2iO_NjWLGwCjtt93z2PspMALJzz1hIGACLcBGAs/s400/apexdir.png" width="400" /></a></div><br />All installation related information can be found <a href="https://docs.oracle.com/database/apex-18.1/HTMIG/toc.htm" target="_blank">here</a>.<br /><br />I want to install apex into a pdb. So I start <b>sqlplus</b>, connect to the dba as <b>sys</b> role <b>sysdba</b> and switch to the pdb.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-zi162ERUEhc/W8yEg-6rUHI/AAAAAAAAJXI/PGWB5N1aQuUhcc2dvyynN2Nc0w2HI24tACLcBGAs/s1600/login.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="295" data-original-width="794" height="147" src="https://3.bp.blogspot.com/-zi162ERUEhc/W8yEg-6rUHI/AAAAAAAAJXI/PGWB5N1aQuUhcc2dvyynN2Nc0w2HI24tACLcBGAs/s400/login.png" width="400" /></a></div><br />I install a development environment and I stick to the documentation, because I don't want to add some additional effort.<br /><br /><pre dir="ltr"><i><b>@apexins.sql SYSAUX SYSAUX TEMP /i/</b></i></pre><pre dir="ltr"><b>&nbsp;</b></pre><div dir="ltr">This takes a while. Done!!</div><div dir="ltr"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-avYQ-3Uq-d0/W8yOP19rO-I/AAAAAAAAJXU/FlMF-h-kKKE6n1NAoRikuU8wSCsmhrvOACLcBGAs/s1600/done.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="578" data-original-width="1126" height="205" src="https://2.bp.blogspot.com/-avYQ-3Uq-d0/W8yOP19rO-I/AAAAAAAAJXU/FlMF-h-kKKE6n1NAoRikuU8wSCsmhrvOACLcBGAs/s400/done.png" width="400" /></a></div><div dir="ltr"><br /></div><h2 dir="ltr">Configuring the Embedded PL/SQL Gateway</h2><div dir="ltr">For now I use the embedded pl/sql gateway, so I run the command</div><div dir="ltr"><br /></div><pre dir="ltr"><i><b>@apex_epg_config.sql /opt/oracle</b></i></pre><pre dir="ltr"><i><b>&nbsp;</b></i></pre><div dir="ltr">because my apex directory is located in this directory.<i><b> </b></i></div><div dir="ltr"><i><b><br /></b></i></div><div dir="ltr">Pssst... don't forget to unlock the ANONYMOUS schema!<i><b></b></i></div><div dir="ltr"><i><b><br /></b></i></div><div dir="ltr"><i><b>ALTER USER ANONYMOUS ACCOUNT UNLOCK;</b></i></div><br /><h3 class="sect2" id="HTMIG-GUID-25F94A9C-24AF-4204-BB99-97037A4B2057">Verifying the Port Assigned to HTTP on the Oracle XML DB HTTP Server</h3><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/--TINHf3psRE/W8yYfWfQ7oI/AAAAAAAAJXk/yLqIswWs7GIYpOdekPR4FHrrAHdr0n6EwCLcBGAs/s1600/httpport.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="380" data-original-width="502" height="302" src="https://2.bp.blogspot.com/--TINHf3psRE/W8yYfWfQ7oI/AAAAAAAAJXk/yLqIswWs7GIYpOdekPR4FHrrAHdr0n6EwCLcBGAs/s400/httpport.png" width="400" /></a></div><h3 class="sect2" id="HTMIG-GUID-25F94A9C-24AF-4204-BB99-97037A4B2057">&nbsp;</h3><h3 class="sect2" id="HTMIG-GUID-25F94A9C-24AF-4204-BB99-97037A4B2057">The password....</h3><div class="sect2" id="HTMIG-GUID-25F94A9C-24AF-4204-BB99-97037A4B2057">Okay, maybe we should set a password for the user as well...</div><div class="sect2" id="HTMIG-GUID-25F94A9C-24AF-4204-BB99-97037A4B2057"><br /></div><div class="sect2" id="HTMIG-GUID-25F94A9C-24AF-4204-BB99-97037A4B2057"><i><b>@apxchpwd.sql</b></i></div><div class="sect2" id="HTMIG-GUID-25F94A9C-24AF-4204-BB99-97037A4B2057"><br /></div><h3 class="sect2" id="HTMIG-GUID-25F94A9C-24AF-4204-BB99-97037A4B2057">And than there was this authorization issue...</h3><div class="sect2" id="HTMIG-GUID-25F94A9C-24AF-4204-BB99-97037A4B2057">While connecting to Apey <b>http://<hostname>:8080/apex/apex_admin</hostname></b> (Portforwarding!) I received the following dialog. </div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-p4XSWUwRYlU/W8yh1wrPK4I/AAAAAAAAJX0/FXu5M_oNyngqAQZOOD6-oI_cCF_gOgrzwCEwYBhgL/s1600/xdb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="490" data-original-width="1000" height="195" src="https://1.bp.blogspot.com/-p4XSWUwRYlU/W8yh1wrPK4I/AAAAAAAAJX0/FXu5M_oNyngqAQZOOD6-oI_cCF_gOgrzwCEwYBhgL/s400/xdb.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: left;">OK this time unlocking the ANONYMOUS in the CDB schema solved the issue.</div><h3 class="separator" style="clear: both; text-align: left;">And here we go</h3><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-5SfxEYL_0v8/W8yjO0y3I0I/AAAAAAAAJX8/Ai1b2COOYDc3s8NulL-ETfDkXgJ27ERQgCLcBGAs/s1600/apex.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="388" data-original-width="1565" height="79" src="https://1.bp.blogspot.com/-5SfxEYL_0v8/W8yjO0y3I0I/AAAAAAAAJX8/Ai1b2COOYDc3s8NulL-ETfDkXgJ27ERQgCLcBGAs/s320/apex.png" width="320" /></a></div><h3 class="separator" style="clear: both; text-align: left;"></h3><img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/GSTiHTzeWE4" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-8678016789631491236 Sun Oct 21 2018 12:03:00 GMT-0400 (EDT) Oracle Forms Modernization, Forms-APEX Similarities https://insum.ca/oracle-forms-apex-similarities/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/10/Oracle-Forms-Modernization-Forms-APEX-Similarities-100x100.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Oracle Forms Modernization, Forms-APEX Similarities" srcset="https://insum.ca/wp-content/uploads/2018/10/Oracle-Forms-Modernization-Forms-APEX-Similarities-100x100.jpg 100w, https://insum.ca/wp-content/uploads/2018/10/Oracle-Forms-Modernization-Forms-APEX-Similarities-150x150.jpg 150w, https://insum.ca/wp-content/uploads/2018/10/Oracle-Forms-Modernization-Forms-APEX-Similarities-600x600.jpg 600w, https://insum.ca/wp-content/uploads/2018/10/Oracle-Forms-Modernization-Forms-APEX-Similarities-300x300.jpg 300w, https://insum.ca/wp-content/uploads/2018/10/Oracle-Forms-Modernization-Forms-APEX-Similarities-50x50.jpg 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p>In this second installment of my series on Oracle Forms and Reports, I&#8217;ll explain why Oracle APEX is ideally suited for Forms Modernization (My first blog was about <a href="https://insum.ca/oracle-forms-and-reports-modernization-forms-challenges/">Forms Challenges</a>). APEX is a web-based Rapid Application Development tool that comes with the Oracle Database. If you already run an Oracle database, it is there for your company to use, right now, without extra licensing fees. Forms-APEX similarities run deep. This is why APEX represents the most cost-effective method to bring your Forms and Reports applications into the 21st century.</p> <h2>The Backbone and the Thorn in the Foot</h2> <p>Legacy Systems like Oracle Forms and Reports can be both the backbone and the thorn in the foot of an organization. On one hand, they&#8217;ve evolved over time to fit the needs of order processing, shipping, finance, and more. In many organizations, they are a model of efficiency. On the other hand, connecting them to the outside world and the needs of the modern business is increasingly difficult, sometimes impossible.</p> <p>Various options have been made available to modernize or replace Forms systems over the years. Among them:</p> <h2>-Open Source Technology</h2> <p>Some have chosen to replace Forms with open source technology. For example, the LAMP approach: Linux, Apache, MySQL, PHP. There is no integration with Forms and you are starting from scratch. Open source is free and without licensing fees. However, long-term support on these platforms is a question mark. Even the most popular open source software risks being superseded. The result can be fewer upgrades and dwindling support.</p> <p>It&#8217;s true that some open source software is supported by large manufacturers. For example, Oracle supports MySQL. Overall, however, open source tools often lack structure. The understanding and use of these tools will often depend on how well the specific technology suits the developer.</p> <h2>-ERP Systems (SAP, Oracle E-Business Suite, JD Edwards etc.)</h2> <p>These standardized platforms became very popular in the early 2000s. They&#8217;ve helped businesses grow, but they didn&#8217;t necessarily grow with all business needs. Companies using these systems are increasingly calling on software developers to extend their ERP&#8217;s capability. Each division of a large company can end up having custom needs outside the ERP’s parameters. This could come from managing new products, new technologies, new processes. ERPs may cover 80%-90% of your application needs, but that remaining 10%-20% is often what makes your business unique.</p> <p>All in all, the associated costs of ERPs are high. This can make sense if your business functions are covered by the new system. In my experience though, there is always something of Forms which isn&#8217;t. When this happens, we now use APEX to extend the ERP to integrate the necessary functionality.</p> <h2>-Object Oriented Development Technology</h2> <p>Some Businesses change over to a different technology entirely, such as Java or .NET. But does your development team have the time and talent to convert to a completely new application framework? Can your company get safely through such a transition? If not, it can become a job for 3rd party technologists with the costs that this entails.</p> <h2>-Custom Software</h2> <p>Many companies have application suites with Forms-like behavior created for them by 3rd parties using a combination of technologies. Just as with open source technology, you don&#8217;t know how that will turn out for you in the long term. You might end up with a system that is just as difficult to maintain as your Forms system was.</p> <p>All of the approaches above are basically &#8220;From Scratch&#8221;, where Forms and its efficiency get put aside. This where the Oracle APEX approach differs. It isn&#8217;t from scratch. In fact, it allows you to reuse much of what your company has painstakingly developed over the years with Forms.</p> <h2>Forms: the Thick Database Paradigm</h2> <p>The often-recommended best-practice approach with Forms was to have as much of the code as possible reside in the database, including business functions and security.  This can make migration or extension work with Forms easier. In this paradigm, Forms acts as a front-end to all this functionality while most of the business logic resides in the Database. This is the thick database Paradigm. This approach is secure, centralized, easy to maintain, easy to deploy, and makes for good performance. Forms is not always set up this way but it can be transferred fairly easily during a migration. Oracle APEX offers tools for such a transition.</p> <p>Another advantage of this paradigm is that you can reuse the same code. For example, if you have 15 order taking screens, you can have them all make the same call from the same code in the database. You won’t have to develop code for 15 different order-taking screens.   This not only makes development easier, but it also makes for better application performance.</p> <p>This is what Forms-APEX similarities stem from. APEX shares this exact same paradigm and much more.</p> <h2>APEX: Same Paradigm, Same Database Model, Same Programming Language</h2> <p>Forms is based on a relational data model, meaning most application screens or blocks of information are based on tables in the database. Often, these are management applications: Client management, order management, PL Management, etc. APEX uses this same relational data model.</p> <p>Another similarity: Forms development is procedural and not object-oriented such as with Java or .Net. So is APEX. Forms and APEX even share the same coding language, PL/SQL. There are, of course, many new functions in APEX, but the base is still the same. APEX even allows you to reuse much of the code you already have in Forms (that&#8217;s right, EXACTLY the same PL/SQL code!).</p> <p>Because of these similarities, your Forms developers will feel at home using APEX very rapidly. They&#8217;ll have a fast, efficient learning curve. Forms and APEX, after all, are both Oracle tools.</p> <h2>Moving From Forms to APEX</h2> <p>So, you have a data model, you have PL/SQL, you have Forms applications, you have business functions in your database, you have predefined security parameters. You’ve had all of this for years. It&#8217;s thoroughly debugged and proven. It is a stable and reliable backbone of your operations. All you need to do is position APEX alongside Forms and reuse the same database, the same SQL code, and the same business functions. The only thing that is really changing is the presentation layer, the User Interface, which also happens to be the one that is web-based. You can also partially or completely replace your Forms applications. It&#8217;s up to you.</p> <p>If you decide to go with another technology, you are basically throwing all of this away and starting over, with all that entails. With APEX you are leveraging the significant investments you’ve made in your Database. You are using the same server, the same personnel, the same developers the same knowledge, and the same IT structure.</p> <p>Why start from scratch when you can start from a large percentage of your existing investment?</p> <h2>APEX:  Rapid Application Development at the service of Forms Developers</h2> <p>Because Forms and APEX share the same developmental approach, the development methodology is the same as well.  Just like in Forms, you develop a logic model, create a physical model, then sit down with the customer/end user and establish a list of business functions and start development.</p> <p>The beauty of modernizing Forms with APEX is that it enables you to keep most of this backend programming.  This is because your backend processes don’t really change. You’ll always have customers, you’ll always products, you’ll always have shipping. You order process will remain the same.</p> <p>What&#8217;s different? These actions might be performed over the internet, on a mobile or tablet. They might be put into communication with <a href="https://insum.ca/so-does-my-business-need-rest-services/">web services</a>. This opens up so many possibilities. It allows connection to internal or external systems such as other departments, business process, business partners and customers.</p> <p>APEX&#8217;s Rapid Application development allows all this to happen quickly and smoothly. Plus, you can now use modern development approaches, like AGILE. This is a far cry from line-by-line Java coding. Suddenly, the move towards web-based applications becomes feasible.  Suddenly, those hundreds of  Forms your company has developed over the years can be moved into the 21<sup>st</sup> century within a reasonable timeframe and cost.</p> <h2>Conclusion</h2> <p>To recap, Forms and APEX have the same:</p> <ul> <li>Technology</li> <li>Database</li> <li>Maintenance</li> <li>Backup</li> <li>Recovery</li> <li>High availability</li> <li>Performance tuning</li> <li>Data model</li> <li>Methodology</li> <li>Development approach</li> </ul> <p>It&#8217;s no wonder they work so well together.</p> <p>In the next blog in this series, we&#8217;ll look at the advantages of Modernizing Oracle Forms with APEX.</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>Missed the first blog in this series on Oracle Forms Modernization? Read it now!   <a href="https://insum.ca/oracle-forms-and-reports-modernization-forms-challenges/">Forms and reports Modernization &#8211; Forms Challenges</a></p> <p>See also</p> <p><a href="https://insum.ca/oracle-forms-conversion-to-oracle-apex-where-to-start/">Oracle Forms Conversion to Oracle APEX &#8211; Where to Start</a></p> <p><a href="https://insum.ca/oracle-forms-modernization-journey/">The Oracle Forms Modernization Journey</a></p> <p><a href="https://insum.ca/time-modernize-oracle-forms-reports-application/">How You Know It&#8217;s Time To Modernize Your Oracle Forms &amp; Reports App</a></p> <p><a href="https://insum.ca/oracle-forms-keep-or-migrate/">Debating Whether to Keep Oracle Forms or to Migrate From It?</a></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>The post <a rel="nofollow" href="https://insum.ca/oracle-forms-apex-similarities/">Oracle Forms Modernization, Forms-APEX Similarities</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Francis Mignault https://insum.ca/?p=13273 Thu Oct 18 2018 08:01:17 GMT-0400 (EDT) ANSI Join: Left Join with an Inner Join http://www.talkapex.com/2018/10/ansi-join-left-join-with-an-inner-join/ <p>I finally caved in and started to write all my queries using ANSI format (<em>thanks <a href="https://twitter.com/vincentmorneau" target="_blank" rel="noopener">Vincent Morneau</a> for encouraging me to change to ANSI</em>). I recently came across a situation where I needed to join two tables then outer join the result with another table. I could easily do this using Oracle joins (with an inner <code>select</code> statement) but was never a fan of it and wanted to see if there was a “cleaner” way to do this using ANSI joins.</p><p>Before continuing it’s important to review some tables that are required for this demo:</p><ul><li><code>dept</code>: 4 departments</li><li><code>emp</code>: 14 rows that contain 3 of the departments (i.e. one department has no employees)</li></ul><p>When you do an outer join (as shown below), 15 rows are returned as one department isn’t referenced in the <code>emp</code> table.</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="keyword">count</span>(<span class="number">1</span>)</span><br><span class="line"><span class="keyword">from</span> dept d, emp e</span><br><span class="line"><span class="keyword">where</span> d.deptno = e.deptno(+)</span><br><span class="line">;</span><br><span class="line"></span><br><span class="line">COUNT(1)</span><br><span class="line"> 15</span><br></pre></td></tr></table></figure><p>For this demo, a new table is required called <code>dept_country</code>. This will be used to join with the <code>emp</code> table to show the country each employee lives in:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create</span> <span class="keyword">table</span> dept_country <span class="keyword">as</span></span><br><span class="line"><span class="keyword">select</span> </span><br><span class="line"> to_number(regexp_replace(<span class="keyword">column_value</span>,<span class="string">'(.*)-(.*)'</span>, <span class="string">'\1'</span>)) deptno,</span><br><span class="line"> regexp_replace(<span class="keyword">column_value</span>,<span class="string">'(.*)-(.*)'</span>, <span class="string">'\2'</span>) country</span><br><span class="line"><span class="keyword">from</span> </span><br><span class="line"> apex_string.split(<span class="string">'10-Can,20-USA,30-Ger,40-Esp'</span>,<span class="string">','</span>) x</span><br><span class="line">;</span><br><span class="line"></span><br><span class="line"><span class="keyword">select</span> *</span><br><span class="line"><span class="keyword">from</span> dept_country</span><br><span class="line">;</span><br><span class="line"></span><br><span class="line">DEPTNO COUNTRY</span><br><span class="line"> 10 Can</span><br><span class="line"> 20 USA</span><br><span class="line"> 30 Ger</span><br><span class="line"> 40 Esp</span><br></pre></td></tr></table></figure><p>If I try to “<code>join</code>“ <code>emp</code> and <code>dept_country</code> without any special handling it will give me invalid data. The following query returns <code>14</code> rows when it should return <code>15</code>:</p><p><em>Note for all the remaining examples the goal is to get <code>15</code> rows</em></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> d.deptno, d.dname, e.ename, dc.country</span><br><span class="line"><span class="keyword">from</span> </span><br><span class="line"> dept d,</span><br><span class="line"> emp e,</span><br><span class="line"> dept_country dc</span><br><span class="line"><span class="keyword">where</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">and</span> d.deptno = e.deptno(+)</span><br><span class="line"> <span class="keyword">and</span> e.deptno = dc.deptno</span><br><span class="line">;</span><br><span class="line"></span><br><span class="line">DEPTNO DNAME ENAME COUNTRY</span><br><span class="line"> 10 ACCOUNTING KING Can</span><br><span class="line"> 10 ACCOUNTING CLARK Can</span><br><span class="line"> 10 ACCOUNTING MILLER Can</span><br><span class="line"> 20 RESEARCH JONES USA</span><br><span class="line"> 20 RESEARCH SCOTT USA</span><br><span class="line"> 20 RESEARCH FORD USA</span><br><span class="line"> 20 RESEARCH SMITH USA</span><br><span class="line"> 20 RESEARCH ADAMS USA</span><br><span class="line"> 30 SALES BLAKE Ger</span><br><span class="line"> 30 SALES ALLEN Ger</span><br><span class="line"> 30 SALES WARD Ger</span><br><span class="line"> 30 SALES MARTIN Ger</span><br><span class="line"> 30 SALES TURNER Ger</span><br><span class="line"> 30 SALES JAMES Ger</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 14 rows (invalid)</span></span><br></pre></td></tr></table></figure><p>The correct way to write the query using Oracle join syntax is shown below. I’m not a fan of the “inner <code>select</code>“ technique as it takes more time to write and you need to list out all the columns that are required.</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> d.deptno, d.dname, e.ename, e.country</span><br><span class="line"><span class="keyword">from</span> dept d,</span><br><span class="line"> (</span><br><span class="line"> <span class="keyword">select</span> e.deptno, e.ename, dc.country</span><br><span class="line"> <span class="keyword">from</span> dept_country dc, emp e</span><br><span class="line"> <span class="keyword">where</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">and</span> dc.deptno = e.deptno(+)</span><br><span class="line"> ) e</span><br><span class="line"><span class="keyword">where</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">and</span> d.deptno = e.deptno(+)</span><br><span class="line">;</span><br><span class="line"></span><br><span class="line">DEPTNO DNAME ENAME COUNTRY</span><br><span class="line"> 10 ACCOUNTING KING Can</span><br><span class="line"> 30 SALES BLAKE Ger</span><br><span class="line"> 10 ACCOUNTING CLARK Can</span><br><span class="line"> 20 RESEARCH JONES USA</span><br><span class="line"> 20 RESEARCH SCOTT USA</span><br><span class="line"> 20 RESEARCH FORD USA</span><br><span class="line"> 20 RESEARCH SMITH USA</span><br><span class="line"> 30 SALES ALLEN Ger</span><br><span class="line"> 30 SALES WARD Ger</span><br><span class="line"> 30 SALES MARTIN Ger</span><br><span class="line"> 30 SALES TURNER Ger</span><br><span class="line"> 20 RESEARCH ADAMS USA</span><br><span class="line"> 30 SALES JAMES Ger</span><br><span class="line"> 10 ACCOUNTING MILLER Can</span><br><span class="line"> 40 OPERATIONS</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 15 rows (correct)</span></span><br><span class="line"><span class="comment">-- Note the extra row for OPERATIONS that has no employees</span></span><br></pre></td></tr></table></figure><p><em>For the rest of this article I won’t be showing the results of each query as they are the same for the 14 vs 15 rows as they are the results are the same as the two previous examples.</em></p><p>Replicating the same situation using ANSI joins the following query is incorrect since the <code>emp</code> is outer joined but <code>dept_country</code> is <code>inner join</code>ed, thus negating the <code>outer</code> join.</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> d.deptno, d.dname, e.ename, dc.country</span><br><span class="line"><span class="keyword">from</span> dual</span><br><span class="line"> <span class="keyword">join</span> dept d <span class="keyword">on</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">left</span> <span class="keyword">join</span> emp e <span class="keyword">on</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">and</span> e.deptno = d.deptno</span><br><span class="line"> <span class="keyword">join</span> dept_country dc <span class="keyword">on</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">and</span> e.deptno = dc.deptno</span><br><span class="line">;</span><br><span class="line"><span class="comment">-- 14 rows (invalid)</span></span><br></pre></td></tr></table></figure><p>ANSI allows for brackets around joins to explicitly specify <code>inner</code> and then <code>outer</code> joins as shown below. I like this syntax as it’s very clear to write, read, and for others to understand. It’s also better than the Oracle inner <code>select</code> format as we don’t need to list out all the columns in a separate <code>select</code> statement.</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> d.deptno, d.dname, e.ename, dc.country</span><br><span class="line"><span class="keyword">from</span> dual</span><br><span class="line"> <span class="keyword">join</span> dept d <span class="keyword">on</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">left</span> <span class="keyword">join</span> (</span><br><span class="line"> dual</span><br><span class="line"> <span class="keyword">join</span> emp e <span class="keyword">on</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">join</span> dept_country dc <span class="keyword">on</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">and</span> e.deptno = dc.deptno</span><br><span class="line"> ) <span class="keyword">on</span> <span class="number">1</span>=<span class="number">1</span></span><br><span class="line"> <span class="keyword">and</span> e.deptno = d.deptno</span><br><span class="line">;</span><br><span class="line"><span class="comment">-- 15 rows (correct)</span></span><br></pre></td></tr></table></figure> Martin Giffy D'Souza http://www.talkapex.com/2018/10/ansi-join-left-join-with-an-inner-join/ Tue Oct 16 2018 21:54:21 GMT-0400 (EDT) Oracle OpenWorld18 session suggestions https://insum.ca/oracle-openworld18-session-suggestions/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/10/Oracle-OpenWorld18-session-suggestions-100x100.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Oracle OpenWorld18 session suggestions" srcset="https://insum.ca/wp-content/uploads/2018/10/Oracle-OpenWorld18-session-suggestions-100x100.jpg 100w, https://insum.ca/wp-content/uploads/2018/10/Oracle-OpenWorld18-session-suggestions-150x150.jpg 150w, https://insum.ca/wp-content/uploads/2018/10/Oracle-OpenWorld18-session-suggestions-600x600.jpg 600w, https://insum.ca/wp-content/uploads/2018/10/Oracle-OpenWorld18-session-suggestions-300x300.jpg 300w, https://insum.ca/wp-content/uploads/2018/10/Oracle-OpenWorld18-session-suggestions-50x50.jpg 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p>Oracle OpenWorld18 is nigh. This year Insum’s own, Francis Mignault and I will be in attendance. We are looking forward to meeting with the Oracle Product Development teams, our wonderful partners and most importantly clients and potential clients.</p> <p>Still with tens of thousands of people in attendance it can be a challenge to locate people. To make it easy, drop us a email (<a href="mailto:fmignault@insum.ca">fmignault@insum.ca</a> or <a href="mailto:mlatiolais@insum.ca">mlatiolais@insum.ca</a>) or a tweet (@fr4ncis or @monty_latiolais). Let’s grab a cup of joe and chat APEX!!</p> <p>If you have not built your agenda by now, here are some suggestions.</p> <h2>MONDAY – OCTOBER 22</h2> <p><strong>Make AppDev Fun Again, with the Oracle RAD Stack [PRO4087]</strong></p> <p><strong>Michael Hichwa, Oracle</strong></p> <p><strong>Time: 9:00 – 9:45 a.m. Location: Moscone West &#8211; 3009</strong></p> <p><em>In this session learn how the RAD stack approach incorporates everything you need for a successful business application. REST is today’s dominant architectural style and the agreed-upon method for tying applications together. Oracle Database is the fastest and most versatile database in the world, available for free or for enterprise installations, on-premises or in Oracle Cloud. And Oracle Application Express, the fastest way to build responsive, flexible, and durable web applications for the Oracle Database. Attendees get a free t-shirt so you can look good tomorrow at the developer community happy hour and around the conference center.</em></p> <p><strong>Why Citizen Developers Should Be Your New Best Friend [TRN4091]</strong></p> <p><strong>David Peake, Oracle</strong></p> <p><strong>Time: 10:30 – 11:15 a.m. Location: Moscone West &#8211; 3009</strong></p> <p><em>You keep hearing how “low-code” tools are the next big thing in app development and how “citizen developers” are building their own apps using no-code and low-code tools. Oracle Application Express is very much a low-code tool, and even more so with Oracle Application Express 18.1. In this session learn how and why you as an IT professional should engage with these citizen developers to greatly improve productivity, engagement, and for the good of your organization. See how with Oracle Application Express 18.1 you can readily guide these citizen developers to become development stars.</em></p> <h2>TUESDAY – OCTOBER 23</h2> <p><strong>Maximizing the Value of Municipal Open Data APIs with Low-Code Development Tools [TRN4092]</strong></p> <p><strong>Mark Sewtz, Oracle</strong></p> <p><strong>Time: 4:45 – 5:30 p.m. Location: Moscone West &#8211; 3009</strong></p> <p><em>Many cities offer comprehensive open data portals, with APIs that provide information on various types of government activities. Making this data publicly available makes governments more accessible and accountable to the communities they serve. Given the right tools to mine and analyze this data, businesses and citizens just might develop new and innovative apps that take full advantage of the data provided. In this session explore a few of the more than 750 public data sets provided by the City of New York and see how anyone can use cloud-based low-code tools such as Oracle Application Express to easily build powerful data analysis tools that tap into data including expenditures, 311 service requests, and demographic and education data.</em></p> <h2>WEDNESDAY – OCTOBER 24</h2> <p><strong>Creating REST-Enabled SQL References and Web Services with Oracle Application Express [HOL6326]</strong></p> <p><strong>David Peake, Oracle</strong></p> <p><strong>Time: 9:30 – 10:30 a.m. Location: Marriott Marquis (Yerba Buena) Salon 3 &#8211; 4</strong></p> <p><em>One of the marquee features of Oracle Application Express 18.1 is the improved ability to consume external REST services and REST-enabled SQL. In this session learn how to reference external REST services as web source modules and how to create reports, charts, calendars, or other components using these. Remote Oracle Databases can be accessed as REST-enabled SQL services as well; learn to create an Oracle Application Express component driven by an SQL query and have it executed on a remote Oracle Database over a REST interface using HTTPS and JSON.</em></p> <p><strong>What Every DBA Needs to Know About Oracle Application Express [TIP1377]</strong></p> <p><strong>Francis Mignault, Insum</strong></p> <p><strong>Time: 3:45 – 4:30 p.m. Location: Moscone West, Room 3001</strong></p> <p><em>Once an enterprise starts using Oracle Application Express, many applications are rapidly created to help manage the business. DBAs start asking questions about managing Oracle Application Express and installing it in Oracle Databases, such as: How can I properly backup and recover Oracle Application Express applications? How do I integrate an Oracle Application Express installation with Oracle E-Business Suite? What are the different component required and supported for the middle tier? Those questions and much more are answered in this session.</em></p> <h2>THURSDAY – OCTOBER 25</h2> <p><strong>Low-Code Development with Oracle Application Express [HOL6327]</strong></p> <p><strong>David Peake, Oracle</strong></p> <p><strong>Time: 9:00 – 10:00 a.m. Location: Marriott Marquis (Yerba Buena) Salon 3 &#8211; 4</strong></p> <p><em>Oracle Application Express is a low-code development platform that enables you to build stunning, scalable, secure apps with world-class features that can be deployed anywhere. In this lab learn how to convert a spreadsheet into a multiuser, web-based, responsive Oracle Application Express application in minutes—no prior experience with Oracle Application Express is needed. See how to rapidly prototype a data model and then create and deploy a feature-rich responsive application against this data model in minutes. Learn how you can use Oracle Application Express to solve many of your business problems that are going unsolved today.</em></p> <p><strong>Oracle Application Express 18.1 New Features [TRN4090]</strong></p> <p><strong>Joel Kallman, Oracle</strong></p> <p><strong>Time: 10:00 – 10:45 a.m. Location: Moscone West, Room 3010</strong></p> <p><em>Oracle Application Express 18.1 focuses on declaratively integrating data sources from remote databases and extending applications running on the cloud via REST. A new Create Application Wizard enables you to add components and features to new and existing applications. Upgrading to the latest Oracle JavaScript Extension Toolkit and jQuery JavaScript libraries will further allow Oracle Application Express to take advantage of new and improved data visualizations and widgets. In this session see those new capabilities and some of the numerous enhancements to Oracle JavaScript Extension Toolkit charts and the interactive grid.</em></p> <h2>Meet us at Oracle OpenWorld18 too?</h2> <p>Aside from the sessions mentioned above, we can likely be found at the Oracle APEX kiosk located in The Exchange (Area 133) in Moscone South…as best I can determine.</p> <p>We’ll also be supporting the ODTUG APEX Community Tuesday night at Johnny Foley’s.  (<a href="https://www.meetup.com/ODTUGers/events/255055562/">https://www.meetup.com/ODTUGers/events/255055562/</a>) Get there early. This place will fill up!!</p> <p>OK. That about does it. Let’s get packing!!</p> <p><em>Monty Latiolais</em></p> <p>The post <a rel="nofollow" href="https://insum.ca/oracle-openworld18-session-suggestions/">Oracle OpenWorld18 session suggestions</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Monty Latiolais https://insum.ca/?p=13308 Tue Oct 16 2018 08:35:44 GMT-0400 (EDT) Maintaining APEX Tree Region Expansion State http://douggault.com/2018/10/15/maintaining-apex-tree-region-expansion-state/ <p>As soon as I was finished with the first incarnation of the ORDS REST Workshop for release in APEX 18.1, I had a list as long as my arm of things that I wanted to do to improve it. Some small, some large.</p> <p>One of the things that bugs me the most is that the APEX Tree region on the left side of the page doesn&#8217;t, by default, remember its expansion state. Originally that meant that every time you clicked a node and navigated to a new page, it would fully collapse on itself.  Thinking that I would have time to come back and fix it later, I implemented a quick fix to make the tree fully expand every time. The problem was that, while working on the other, more esoteric functionality, I let too much time slip by and I wan&#8217;t able to go back and implement a proper solution before it was time for UI freeze.</p> <p>If you&#8217;re working with a relatively small number of RESTful services, this doesn&#8217;t pose too much of a problem. However, if you&#8217;re working with more than just a few, having the tree fully expended with every page refresh very quickly starts to get annoying.</p> <p>So, for APEX 19.1 one of my first priorities was to fix this. Little did I know how simple the fix really was.</p> <h3>Documentation to the Rescue</h3> <p>One of the things that has improved in the more recent versions of APEX has been the <a href="https://docs.oracle.com/database/apex-18.2/AEXJS/index.html" target="_blank" rel="noopener">JavaScript API documentation</a>. Included therein is documentation on the treeVeiw object used by the APEX Tree Region.</p> <p>A quick peruse of the <a href="https://docs.oracle.com/database/apex-18.2/AEXJS/treeView.html#methods-section" target="_blank" rel="noopener">methods</a> shows that there are a a number of ways we could approach the problem but after a little reading I landed on the technique outlined below.</p> <p>I&#8217;m sure there are other ways to do this and probably at least 50% of them will be better than my way, but it works and its simple. Two criteria I try to let guide my coding!</p> <h3>A Tree, Two Dynamic Actions and a Cookie</h3> <p>Creating the tree is the easy part. In <a href="https://apex.oracle.com/pls/apex/f?p=72614:2:111479899179369::NO:::" target="_blank" rel="noopener">my example</a> I used a simple tree over the EMP table. Just for fun I hooked it up to a classic report that shows the direct reports of the person selected in the tree. Single-clicking on a tree node would navigate back to the same page, passing the EMPNO of the user you selected so that it could be used in the report.</p> <p>For maintaining the Tree&#8217;s sate, the first problem to attack was that of getting and saving the trees expanded state so that it can be reinstated when you come back to the page.</p> <p>For this I chose to use the <a href="https://docs.oracle.com/database/apex-18.2/AEXJS/treeView.html#getExpandedNodeIds" target="_blank" rel="noopener">getExpandedNodeIds</a> method. This method returns an array of node ids from the associated data model for each expanded node.<br /> Because I wanted to save the tree state, regardless of what caused the navigation, I chose to create a Dynamic Action triggered on Page Unload.</p> <figure class="wp-block-image"><img data-attachment-id="471" data-permalink="http://douggault.com/2018/10/15/maintaining-apex-tree-region-expansion-state/screen-shot-2018-10-12-at-1-41-44-pm/" data-orig-file="https://i2.wp.com/douggault.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-12-at-1.41.44-PM.png?fit=481%2C296" data-orig-size="481,296" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Screen Shot 2018-10-12 at 1.41.44 PM" data-image-description="" data-medium-file="https://i2.wp.com/douggault.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-12-at-1.41.44-PM.png?fit=300%2C185" data-large-file="https://i2.wp.com/douggault.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-12-at-1.41.44-PM.png?fit=481%2C296" class="wp-image-471" src="https://i2.wp.com/douggault.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-12-at-1.41.44-PM.png?w=761" alt="" data-recalc-dims="1" /></figure> <p>The True action of the Dynamic Action would be to execute the following JavaScript:</p> <pre class="brush: jscript; title: ; notranslate"> // Get a handle on the tree using regionStaticID_tree. Then use the treeView to get the expanded Nodes var exp$ = $(&quot;#empTree_tree&quot;).treeView(&quot;getExpandedNodeIds&quot;); // Create a cookie and store the nodes that are expanded // The toString will change the array into a comma separated string. apex.storage.setCookie('myTreeState', exp$.toString()); </pre> <ul> <li>Line 2 gets the selected nodes and stores them in the array named <strong>exp$</strong></li> <li>Line 6 uses the apex.storage.setCookie javascript function to store the selected nodes in the users&#8217;s browser. the exp$.toString() function basically takes the array and creates a comma separated string that is easy to store</li> </ul> <p>When navigating away from the page for any reason, the values of the selected nodes are now stored in a browser cookie called <strong>myTreeState.</strong></p> <p>Now all we need to do is restore that state when we&#8217;re going the other direction. For this we&#8217;ll use another Dynamic Action triggered On Page Load.</p> <figure class="wp-block-image"><img data-attachment-id="472" data-permalink="http://douggault.com/2018/10/15/maintaining-apex-tree-region-expansion-state/screen-shot-2018-10-12-at-1-54-47-pm/" data-orig-file="https://i2.wp.com/douggault.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-12-at-1.54.47-PM.png?fit=474%2C298" data-orig-size="474,298" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Screen Shot 2018-10-12 at 1.54.47 PM" data-image-description="" data-medium-file="https://i2.wp.com/douggault.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-12-at-1.54.47-PM.png?fit=300%2C189" data-large-file="https://i2.wp.com/douggault.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-12-at-1.54.47-PM.png?fit=474%2C298" class="wp-image-472" src="https://i2.wp.com/douggault.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-12-at-1.54.47-PM.png?w=761" alt="" data-recalc-dims="1" /></figure> <p>The True action of the Dynamic Action would be to execute the following JavaScript:</p> <p>&nbsp;</p> <pre class="brush: jscript; title: ; notranslate"> // Get a handle on the tree using regionStaticID_tree var tree$ = $(&quot;#empTree_tree&quot;); // Get the value of the cookie named myTreeState var myTreeState = apex.storage.getCookie(&quot;myTreeState&quot;); // If the Cookie is not null then loop through and expand the tree if (myTreeState) { // Split the value of the cookie and make an array var $expNodes = myTreeState.split(&quot;,&quot;); // Loop Through the array and for each entry $expNodes.forEach(function (id) { // Identify the Tree Nodes that relate to the saved values var node$ = tree$.treeView(&quot;find&quot;,{ depth : -1, findAll: false, match: function(node){ return node.id == id } }) // Expand those nodes. tree$.treeView(&quot;expand&quot;, node$) }) } </pre> <ul> <li>Line 2 gets a handle on the tree itself and assigns it to tree$</li> <li>Line 4 uses apex.storage.getCookie to retrieve any values from the user&#8217;s browser into the variable myTreeState</li> <li>Line 6 checks to see if there were any values to retrieve. If there weren&#8217;t then there is no need to reinstate them.</li> <li>Line 9 splits the string that was stored and creates an array of node ids called $expNodes</li> <li>Line 11 loops through each item in the array</li> <li>Lines 13 through 19 identify the tree nodes that match the values we saved and creates an array of node$</li> <li>Line 21 accesses the treeView of tree$ and expands the nodes held in the array.</li> </ul> <p>The end result is that the tree will be set back to its previous state after having navigated away and then back.</p> <p>I hope that someone finds this useful and that it shows just how simple it can be to interact with the APEX JavaScript APIs now that there is good documentation.</p> Doug Gault http://douggault.com/?p=469 Mon Oct 15 2018 09:05:28 GMT-0400 (EDT) Export from APEX 5.1 after you have upgraded to APEX 18.2 https://oracleinsights.blogspot.com/2018/10/export-from-apex-51-after-you-have.html <div dir="ltr" style="text-align: left;" trbidi="on"> I just wrapped up an upgrade for one of the development environments from APEX 5.1 to APEX 18.2 when the phone rang:<br /> <br /> <blockquote class="tr_bq"> I need to export some changes I was doing in APEX 5.1, an issue has suddenly changed from low priority to high priority. The work in only in DEV, and I don't have a recent export!!&nbsp; Is APEX 18.2 backwardly compatible with APEX 5.1?</blockquote> &nbsp;I wouldn't like to try exporting from APEX 18.2 back to APEX 5.1 - that's fraught with danger.<br /> But it is possible to do an export from an old APEX schema provided you haven't dropped the schema, here's how..<br /> <br /> <pre style="border: 1px solid rgba(0, 0, 0, 0.0980392); box-sizing: border-box; color: #2b2b2b; font-family: monospace, serif; font-size: 15px; hyphens: none; line-height: 1.6; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 12px; vertical-align: baseline; word-wrap: normal;"><code style="border: 0px; font-family: monospace, serif; font-style: inherit; font-weight: inherit; hyphens: none; line-height: 1.6; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">variable name varchar2(255) variable contents clob declare l_files apex_050100.wwv_flow_t_export_files; begin l_files := apex_050100.wwv_flow_export_api.get_application(p_application_id =&gt; &amp;APPLICATION_ID. ); :name := l_files(1).name; :contents := l_files(1).contents; end; / set feed off echo off head off flush off termout off trimspool on set long 100000000 longchunksize 32767 col name new_val name select :name name from sys.dual; spool &amp;name. print contents spool off </code></pre> Surprisingly easy!!!<br /> So now the developer imports the application into the TEST environment, which is still APEX 5.1, finalizes the change and make an emergency release to promote to UAT and PROD.</div> Mark Lancaster tag:blogger.com,1999:blog-869579236085438805.post-1219514244854657450 Sun Oct 14 2018 23:05:00 GMT-0400 (EDT) Announcing Oracle APEX Static Resources on Content Delivery Network https://blogs.oracle.com/apex/announcing-oracle-apex-static-resources-on-oracle-content-delivery-network <p>We are pleased to announce the availability of <a href="https://apex.oracle.com" target="_blank">APEX</a> static resources on a Content Delivery Network (CDN).&nbsp;&nbsp;</p> <p>As defined in&nbsp;<a href="https://en.wikipedia.org/wiki/Content_delivery_network" target="_blank">Wikipedia</a>, &quot;a content delivery network or content distribution network (CDN) is a geographically distributed network of proxy servers and their data centers. The goal is to distribute service spatially relative to end-users to provide high availability and high performance.&quot;&nbsp; If you have an application which is used by an audience geographically distributed around the globe, you can improve the overall performance of your application by having some of the content delivered from servers physically closer to the end-user.&nbsp;</p> <p>For example, if I have an application running on the free site <a href="https://apex.oracle.com" target="_blank">https://apex.oracle.com</a> (which is running in a data center in Austin, Texas USA), and a user in Vinnytsia, Ukraine runs my application, they will need to wait for the static files associated with my APEX application to be physically transmitted from Texas to Ukraine.&nbsp; There is greater network transmission time and higher risk of latency the further away you are from the source.&nbsp; This results in degraded performance, and is especially perceptible on mobile devices.&nbsp; But with a CDN, the files may be delivered from a server which is physically closer to the client, and it&#39;s all done transparently.</p> <p>The Oracle APEX 18.1 and APEX 18.2 static resources are available via the following paths:</p> https://static.oracle.com/cdn/apex/18.1.0.00.45/ https://static.oracle.com/cdn/apex/18.2.0.00.12/ <p>&nbsp;</p> <p>It is really easy to make use of this.</p> <p>1) If you want to convert the entire APEX instance to use the static resources from the CDN, you will want to reset the APEX image prefix for your instance.&nbsp; You should <strong>not</strong> do this on a live system, as this process will invalidate many objects in the APEX schema and they will need to be recompiled.&nbsp; Again - don&#39;t do this on a live system.&nbsp; To accomplish this:</p> <ul> <li>Locate your APEX distribution</li> <li>Navigate to the apex/utilities subdirectory</li> <li>Connect to your database as user SYS</li> <li>Run:&nbsp; <span style="font-family:courier;">@reset_image_prefix.sql</span><br /> and when prompted for the image prefix, enter the correct path, like:<br /> <span style="font-family:courier;">https://static.oracle.com/cdn/apex/18.2.0.00.12/</span></li> </ul> <p>If you&#39;re using <a href="https://www.oracle.com/database/technologies/appdev/rest.html" target="_blank">Oracle REST Data Services (ORDS)</a> with APEX, you will need to restart ORDS after resetting the image prefix.</p> <p>&nbsp;</p> <p>2) If you simply want to use the CDN-hosted resources in a single APEX application:</p> <ul> <li>In Application Builder, edit your application and click <strong>Shared Components</strong></li> <li>Click <strong>User Interface Attributes</strong></li> <li>In the <strong>Image Prefix</strong> attribute, enter the correct path:&nbsp;&nbsp;<span style="font-family:courier;">https://static.oracle.com/cdn/apex/18.2.0.00.12/</span></li> <li>Click <strong>Apply Changes</strong>.&nbsp; That&#39;s all there is to it!</li> </ul> <p>&nbsp;</p> <p>Anyone on the planet is welcome to use the APEX resources available via the Content Delivery Network.&nbsp; If you have an application that is used around the world, you should consider using the CDN.&nbsp; If you have an application which is only used within a specific geography or only within your company, it may remain faster to have the APEX static resources served by your infrastructure.&nbsp; Testing can prove this.</p> <p>We will be updating the free site <a href="https://apex.oracle.com" target="_blank">https://apex.oracle.com</a> to make use of the CDN.</p> Joel Kallman https://blogs.oracle.com/apex/announcing-oracle-apex-static-resources-on-oracle-content-delivery-network Fri Oct 12 2018 11:52:00 GMT-0400 (EDT) Announcing Oracle APEX Static Resources on Content Delivery Network https://blogs.oracle.com/apex/announcing-oracle-apex-static-resources-on-oracle-content-delivery-network <p>We are pleased to announce the availability of <a href="https://apex.oracle.com" target="_blank">APEX</a> static resources on a Content Delivery Network (CDN).&nbsp;&nbsp;</p> <p>As defined in&nbsp;<a href="https://en.wikipedia.org/wiki/Content_delivery_network" target="_blank">Wikipedia</a>, &quot;a content delivery network or content distribution network (CDN) is a geographically distributed network of proxy servers and their data centers. The goal is to distribute service spatially relative to end-users to provide high availability and high performance.&quot;&nbsp; If you have an application which is used by an audience geographically distributed around the globe, you can improve the overall performance of your application by having some of the content delivered from servers physically closer to the end-user.&nbsp;</p> <p>For example, if I have an application running on the free site <a href="https://apex.oracle.com" target="_blank">https://apex.oracle.com</a> (which is running in a data center in Austin, Texas USA), and a user in Vinnytsia, Ukraine runs my application, they will need to wait for the static files associated with my APEX application to be physically transmitted from Texas to Ukraine.&nbsp; There is greater network transmission time and higher risk of latency the further away you are from the source.&nbsp; This results in degraded performance, and is especially perceptible on mobile devices.&nbsp; But with a CDN, the files may be delivered from a server which is physically closer to the client, and it&#39;s all done transparently.</p> <p>The Oracle APEX 18.1 and APEX 18.2 static resources are available via the following paths:</p> https://static.oracle.com/cdn/apex/18.1.0.00.45/ https://static.oracle.com/cdn/apex/18.2.0.00.12/ <p>&nbsp;</p> <p>It is really easy to make use of this.</p> <p>1) If you want to convert the entire APEX instance to use the static resources from the CDN, you will want to reset the APEX image prefix for your instance.&nbsp; You should <strong>not</strong> do this on a live system, as this process will invalidate many objects in the APEX schema and they will need to be recompiled.&nbsp; Again - don&#39;t do this on a live system.&nbsp; To accomplish this:</p> <ul> <li>Locate your APEX distribution</li> <li>Navigate to the apex/utilities subdirectory</li> <li>Connect to your database as user SYS</li> <li>Run:&nbsp; <span style="font-family:courier;">@reset_image_prefix.sql</span><br /> and when prompted for the image prefix, enter the correct path, like:<br /> <span style="font-family:courier;">https://static.oracle.com/cdn/apex/18.2.0.00.12/</span></li> </ul> <p>If you&#39;re using <a href="https://www.oracle.com/database/technologies/appdev/rest.html" target="_blank">Oracle REST Data Services (ORDS)</a> with APEX, you will need to restart ORDS after resetting the image prefix.</p> <p>&nbsp;</p> <p>2) If you simply want to use the CDN-hosted resources in a single APEX application:</p> <ul> <li>In Application Builder, edit your application and click <strong>Shared Components</strong></li> <li>Click <strong>User Interface Attributes</strong></li> <li>In the <strong>Image Prefix</strong> attribute, enter the correct path:&nbsp;&nbsp;<span style="font-family:courier;">https://static.oracle.com/cdn/apex/18.2.0.00.12/</span></li> <li>Click <strong>Apply Changes</strong>.&nbsp; That&#39;s all there is to it!</li> </ul> <p>&nbsp;</p> <p>Anyone on the planet is welcome to use the APEX resources available via the Content Delivery Network.&nbsp; If you have an application that is used around the world, you should consider using the CDN.&nbsp; If you have an application which is only used within a specific geography or only within your company, it may remain faster to have the APEX static resources served by your infrastructure.&nbsp; Testing can prove this.</p> <p>We will be updating the free site <a href="https://apex.oracle.com" target="_blank">https://apex.oracle.com</a> to make use of the CDN.</p> Joel Kallman https://blogs.oracle.com/apex/announcing-oracle-apex-static-resources-on-oracle-content-delivery-network Fri Oct 12 2018 11:52:00 GMT-0400 (EDT) A PL/SQL package for handling the MailChimp API https://insum.ca/pl-sql-package-mailchimp-api/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/10/A-PL-SQL-package-for-handling-the-MailChimp-API-100x100.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="PL SQL package for MailChimp API" srcset="https://insum.ca/wp-content/uploads/2018/10/A-PL-SQL-package-for-handling-the-MailChimp-API-100x100.jpg 100w, https://insum.ca/wp-content/uploads/2018/10/A-PL-SQL-package-for-handling-the-MailChimp-API-150x150.jpg 150w, https://insum.ca/wp-content/uploads/2018/10/A-PL-SQL-package-for-handling-the-MailChimp-API-600x600.jpg 600w, https://insum.ca/wp-content/uploads/2018/10/A-PL-SQL-package-for-handling-the-MailChimp-API-300x300.jpg 300w, https://insum.ca/wp-content/uploads/2018/10/A-PL-SQL-package-for-handling-the-MailChimp-API-50x50.jpg 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p>What’s the optimal technical solution for sending do-not-reply / marketing / notification / batch emails? Is it wiser to in-house or outsource the service? What are my options if I’m considering outsourcing?</p> <p>These questions are difficult and I don’t propose to answer any of them with much thoroughness. They are, however, the questions that I was asking myself as I was considering upgrading the email notification mechanics for my blog <u><a href="https://2122.io">2122.io</a></u> and ultimately led me to write a <u><a href="https://github.com/hhudson/mailchimp_plsql_api">PL/SQL package for handling MailChimp&#8217;s API</a></u>.</p> <p>If, like me, you are (1) wary of maintaining an email server and (2) interested in an email solution that has easy-to-implement attractive templates and in-depth reporting, this blog post may be of interest to you.</p> <h2>Sending Email Is Easy / Ensuring Receipt Is Tricky</h2> <p>Configuring an MTA (Mail Transfer Agent) on your server, like Postfix, is simple enough. You can set yourself up to send mail in a matter of hours (including testing). However, I am persuaded that correctly installing the MTA software is the easy part.</p> <p>You may now be able to send email but getting the email to reach its destination is a greater challenge. You must now acquire and maintain a  knowledge of:</p> <ul> <li>The <u><a href="https://www.ftc.gov/tips-advice/business-center/guidance/can-spam-act-compliance-guide-business">CAN-SPAM</a></u> Act</li> <li><u><a href="https://www.cloudns.net/wiki/article/40/">Reverse PTR records</a></u></li> <li><u><a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail">Domain Keys Identified Mail</a></u></li> <li><u><a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework">SPF records</a></u></li> <li>etc</li> </ul> <p>All of these topics may be relevant to debugging why your emails aren’t reaching their intended recipients. More on these headaches <u><a href="https://blog.codinghorror.com/so-youd-like-to-send-some-email-through-code">here</a></u>.</p> <p>These challenges of course, don’t include those of:</p> <ul> <li>Styling your email templates</li> <li>Reporting on your campaign history (open rate, unsubscribes, etc)</li> </ul> <p>All in all, in-housing your do-not-reply / marketing emails can be an ambitious project.</p> <h2>Give Yourself a Break &#8211; Outsource Your Email</h2> <p>For a modest monthly fee (or free if you don’t mind 3rd party branding in your email), you can plug in a 3rd party API and <strong>simplify</strong> your batch emailing process.</p> <p>Below, I’ve tabulated some of the options I’m aware of (accurate as of the time of this writing). There are many metrics by which to compare these services &#8211; for my purposes, I’ve zeroed in on starting price and the quality of the API documentation:</p> <p><img class="alignnone wp-image-13239 size-large" src="https://insum.ca/wp-content/uploads/2018/10/Outsourcing-Your-Email-to-Mailchimp-600x331.jpg" alt="MailChimp API and competitor APIs" width="600" height="331" srcset="https://insum.ca/wp-content/uploads/2018/10/Outsourcing-Your-Email-to-Mailchimp-600x331.jpg 600w, https://insum.ca/wp-content/uploads/2018/10/Outsourcing-Your-Email-to-Mailchimp-300x165.jpg 300w, https://insum.ca/wp-content/uploads/2018/10/Outsourcing-Your-Email-to-Mailchimp-768x423.jpg 768w, https://insum.ca/wp-content/uploads/2018/10/Outsourcing-Your-Email-to-Mailchimp-450x248.jpg 450w, https://insum.ca/wp-content/uploads/2018/10/Outsourcing-Your-Email-to-Mailchimp.jpg 869w" sizes="(max-width: 600px) 100vw, 600px" /></p> <p>All of these platforms would serve my modest intentions (hooking up email notification to a blog). They all have well-documented APIs and reasonable pricing. As a 1st cut, I can narrow in on the 3 services that would be sustainably free for my purposes: MailChimp, SendinBlue and Zoho. Among these 3, MailChimp, in my opinion, stands out for its richness of features and modernity of feel.</p> <p>With this analysis, I assembled the following GitHub repo with the hope that others may find my work useful: <u><a href="https://github.com/hhudson/mailchimp_plsql_api">https://github.com/hhudson/mailchimp_plsql_api</a></u>. I wrote it for APEX 5.1.4 or higher with a 12.2 database.</p> <h2>Description Of My MailChimp API GIT Repo</h2> <p>The MailChimp API is vast  &#8211; I did not build an interface for all of it. I did, however, capture what I consider some of its most essential features:</p> <ul> <li>Creating and Modifying Email Recipient Lists</li> <li>Creating and Modifying Email Templates</li> <li>Sending Your Email (obviously)</li> <li>Reviewing Your Email History</li> <li>And more</li> </ul> <p>I provide examples and instructions here: <u><a href="https://github.com/hhudson/mailchimp_plsql_api">https://github.com/hhudson/mailchimp_plsql_api</a></u></p> <p>You&#8217;ll need to create a MailChimp account and pass in some global variables (like the API Key and the path to your wallet) to get started.</p> <h2>My experience coding this package</h2> <p>Writing this API was both easier and more difficult than I had anticipated.</p> <p>On the ‘Easier Than Expected’ front, I want to thank <u><a href="https://www.getpostman.com/">Postman</a></u> for being an invaluable tool for experimenting with API Calls. Added to that, I want to reiterate my praise for the <u><a href="https://developer.mailchimp.com/documentation/mailchimp/reference/overview/">MailChimp API</a></u>, which includes many helpful examples.</p> <p>On the ‘Harder Than Expected’ front, I was challenged by the new ‘https_host’ parameter in the APEX_WEB_SERVICE.MAKE_REQUEST function, introduced in the 12.2 database. It took a bit of head-scratching to figure out what this parameter was asking for. I documented my resolution to this challenge in my git repo: <u><a href="https://github.com/hhudson/mailchimp_plsql_api/blob/master/docs/Certificate_of_the_remote_server_does_not_match_the_target_address.md">ORA-29024: Certificate of the remote server does not match the target address</a></u></p> <h2>Sign off</h2> <p>Do you agree with my analysis? Let me know if you think I’ve missed anything or if you can think of directions you’d like to see my project go. Drop me a comment below 🙂<u></u></p> <p>&nbsp;</p> <p><em>Hayden Hudson</em></p> <p>The post <a rel="nofollow" href="https://insum.ca/pl-sql-package-mailchimp-api/">A PL/SQL package for handling the MailChimp API</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Hayden Hudson https://insum.ca/?p=13238 Fri Oct 12 2018 08:35:47 GMT-0400 (EDT) Relational to JSON with SQL https://jsao.io/2018/10/relational-to-json-with-sql/ <p>Oracle started adding JSON support to Oracle Database with version 12.1.0.2. The earliest support was targeted at storing, indexing, and querying JSON data. Version 12.2 rounded out that support by adding features for generating, exploring, and processing JSON data. See the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/adjsn/index.html">JSON Developer&#8217;s Guide</a> for a comprehensive overview of what&#8217;s now available. In this post, I&#8217;ll leverage the new SQL operators for JSON generation to convert the relational data to meet the goal.<br /> <span id="more-3195"></span></p> <div class="alert alert-info" role="alert"> <strong>Please Note:</strong> This post is part of <a href="https://jsao.io/2015/07/relational-to-json-in-oracle-database">a series on generating JSON from relational data in Oracle Database</a>. See that post for details on the solution implemented below as well as other options that can be used to achieve that goal. </div> <h4>Solution</h4> <p>The 12.2+ SQL functions available for JSON generation are:</p> <ul> <li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/adjsn/generation.html#GUID-1084A518-A44A-4654-A796-C1DD4D8EC2AA">JSON_OBJECT</a> &#8211; single-row function, creates an object for each row.</li> <li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/adjsn/generation.html#GUID-F942D202-E4BB-4ED8-997E-AEBD6D8ED8C1">JSON_ARRAY</a> &#8211; single-row function, creates an array for each row.</li> <li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/adjsn/generation.html#GUID-E4DDB4E8-A4B9-4EA9-BC26-1879AA661D37">JSON_OBJECTAGG</a> &#8211; aggregate function, creates an object based on groups of rows.</li> <li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/adjsn/generation.html#GUID-B0FA4582-762D-4C32-8A0C-265142BD347B">JSON_ARRAYAGG</a> &#8211; aggregate function, creates an array based on groups of rows.</li> </ul> <p>The following solution uses JSON_OBJECT and JSON_ARRAYAGG multiple times, nesting them as needed to produce the desired output.</p> <pre class="crayon-plain-tag">select json_object( 'id' is department_id, 'name' is department_name, 'location' is ( select json_object( 'id' is location_id, 'streetAddress' is street_address, 'postalCode' is postal_code, 'country' is ( select json_object( 'id' is country_id, 'name' is country_name, 'regionId' is region_id ) from countries where country_id = loc.country_id ) ) from locations loc where location_id = dept.location_id ), 'manager' is ( select json_object( 'id' is employee_id, 'name' is first_name || ' ' || last_name, 'salary' is salary, 'job' is ( select json_object( 'id' is job_id, 'title' is job_title, 'minSalary' is min_salary, 'maxSalary' is max_salary ) from jobs where job_id = man.job_id ) ) from employees man where employee_id = dept.manager_id ), 'employees' is ( select json_arrayagg( json_object( 'id' is employee_id, 'name' is first_name || ' ' || last_name, 'isSenior' is case when emp.hire_date &lt; to_date('01-01-2005', 'dd-mm-yyyy') then 'true' else 'false' end format json, 'commissionPct' is commission_pct, 'jobHistory' is ( select json_arrayagg( json_object( 'id' is job_id, 'departmentId' is department_id, 'startDate' is to_char(start_date, 'DD-MON-YYYY'), 'endDate' is to_char(end_date, 'DD-MON-YYYY') ) ) from job_history where employee_id = emp.employee_id ) ) ) from employees emp where department_id = dept.department_id ) ) as department from departments dept where department_id = :department_id</pre> <p>As was the case with the <a href="https://jsao.io/2015/07/relational-to-json-with-ords/">SQL query used for ORDS</a>, this is a fairly large query. But I love the control the new SQL operators provide! As an example, I&#8217;ve highlighted line 50, which uses the FORMAT JSON keywords to declare that the value is to be considered as JSON data. This allowed me to add Boolean values to the JSON output despite the fact that Oracle&#8217;s SQL engine doesn&#8217;t support Boolean. There are <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/adjsn/generation.html#GUID-C0F8F837-EE36-4EDD-9261-6E8A9245906C__OPTIONALBEHAVIORFORSQLJSONGENERATIO-022017DB">other optional keywords</a> to modify the behavior of the JSON generating functions.</p> <h4>Output</h4> <p>I&#8217;m happy to report that the solution above generates JSON that meets the goal 100%!</p> <pre class="crayon-plain-tag">{ &quot;id&quot;: 10, &quot;name&quot;: &quot;Administration&quot;, &quot;location&quot;: { &quot;id&quot;: 1700, &quot;streetAddress&quot;: &quot;2004 Charade Rd&quot;, &quot;postalCode&quot;: &quot;98199&quot;, &quot;country&quot;: { &quot;id&quot;: &quot;US&quot;, &quot;name&quot;: &quot;United States of America&quot;, &quot;regionId&quot;: 2 } }, &quot;manager&quot;: { &quot;id&quot;: 200, &quot;name&quot;: &quot;Jennifer Whalen&quot;, &quot;salary&quot;: 4400, &quot;job&quot;: { &quot;id&quot;: &quot;AD_ASST&quot;, &quot;title&quot;: &quot;Administration Assistant&quot;, &quot;minSalary&quot;: 3000, &quot;maxSalary&quot;: 6000 } }, &quot;employees&quot;: [ { &quot;id&quot;: 200, &quot;name&quot;: &quot;Jennifer Whalen&quot;, &quot;isSenior&quot;: true, &quot;commissionPct&quot;: null, &quot;jobHistory&quot;: [ { &quot;id&quot;: &quot;AD_ASST&quot;, &quot;departmentId&quot;: 90, &quot;startDate&quot;: &quot;17-SEP-1995&quot;, &quot;endDate&quot;: &quot;17-JUN-2001&quot; }, { &quot;id&quot;: &quot;AC_ACCOUNT&quot;, &quot;departmentId&quot;: 90, &quot;startDate&quot;: &quot;01-JUL-2002&quot;, &quot;endDate&quot;: &quot;31-DEC-2006&quot; } ] } ] }</pre> <p>However, when I ran this query on department 50 (which as the most employees) I received this error: ORA-40459: output value too large (actual: 4071, maximum: 4000). This is because each of the JSON generation functions has a default output of varchar2(4000). This is fine for many use cases, but it&#8217;s easily exceeded with the aggregate functions and deeply nested structures.</p> <p>The solution is to leverage the RETURNING clause to specify a different data type or size. See <a href="https://gist.github.com/dmcghan/127cdeaf770203d467f8354deb31a598">this gist</a> to get an idea of how the solution above could be modified to use the RETURNING clause. In 12.2, <a href="https://asktom.oracle.com/pls/apex/asktom.search?tag=sql-json-ora-40459-exception">there were some restrictions</a> on which functions could work with CLOBs, but they&#8217;ve been lifted in 18c.</p> <h4>Summary</h4> <p>This is my favorite solution of the series &#8211; by far! The JSON generation functions are very powerful and because they&#8217;re in the database it&#8217;s possible to leverage them from just about anywhere, including Node.js and ORDS.</p> danmcghan https://jsao.io/?p=3195 Fri Oct 12 2018 08:21:05 GMT-0400 (EDT) Web Source Modules and the Interactive Grid: Part 1 https://blogs.oracle.com/apex/web-source-modules-and-the-interactive-grid-part-1 <p><strong>by Andreea Dobre, Oracle Romania in Bucharest</strong></p> <p style="text-align: justify;">With Application Express 18.1, APEX introduced support for using REST Services directly in APEX components: Using <span><a href="https://blogs.oracle.com/apex/get-started-with-rest-services-in-application-express-52-ea-1">Web Source Modules</a></span>, reports, charts or calendar regions can work directly on top of a REST service - with no manual coding required.&nbsp;However, only &bdquo;read only&ldquo; components support REST Services, thus we can create an Interactive Report or a Chart page on top of a REST service, but not a form page or an Interactive Grid.&nbsp;</p> <p style="text-align: justify;">The good news is: With a Web Source Module and some custom PL/SQL code, using the <a href="https://docs.oracle.com/database/apex-18.1/AEAPI/APEX_EXEC.htm#AEAPI-GUID-3CF1D2DD-AEA4-4982-9857-548567AB7169" target="_blank">APEX_EXEC</a> package, you can REST-enable your Interactive Grid based on a REST Service today. The INSERT, UPDATE or DELETE operations of the interactive Grid will map to the POST, PUT and DELETE operations of a REST service.</p> <p style="text-align: justify;">This blog posting, which is the first part of a series on REST-Enabling the Interactive Grid, will show how this works. The well-known EMP table and a REST service on top of it will serve as an example. This first part will show ...</p> <ul> <li>how to create a Web Source Module on top of a REST service</li> <li>how to create an interactive grid (on a local table first)</li> <li>how to have the interactive grid invoke the REST service for SQL INSERT operations</li> </ul> <p style="text-align: justify;">Following blog postings will show how to complete that scenario, i.e. support other DML operations and have Interactive Grid actually&nbsp;<em>show</em> data from the REST service.</p&t; Prerequisites <p style="text-align: justify;">In order to have a proper environment where to start playing with REST Services, go to <a href="https://apex.oracle.com" target="_blank">apex.oracle.com</a> and sign up for a free workspace. Navigate to <strong>SQL Workshop &gt; RESTful Services</strong> and make sure to check <strong>ORDS Based RESTful Services</strong>.</p> <p style="text-align: justify;"><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/7f1edf4cc4f2aae196fe10d077a39507/restful_service_options.JPG" style="width: 1915px; height: 318px;" /><br /> <br /> The environment is now ready to go. First we need to REST-Enable the database schema, which is assigned to the APEX workspace. This can be done in <strong>SQL Workshop &gt; RESTful Services &gt; Register Schema with ORDS</strong>. As an alternative, you can do that with the following SQL statements in <strong>SQL Workshop &gt; SQL Commands</strong>.</p> <b>begin</b> <span style="background-color: #ffffff">ords</span>.<span style="background-color: #ffffff">enable_schema</span><span style="background-color: #ffffff">;</span> <b>end</b><span style="background-color: #ffffff">;</span> <p style="text-align: justify;">Next, we need to create a REST Endpoint for a table. The easiest way to achieve that is to simply &bdquo;REST-Enable&ldquo; the table as follows. REST-Enabling a table will create GET, POST, PUT and DELETE endpoints.</p> <b>begin</b> <span style="background-color: #ffffff">ords</span>.<span style="background-color: #ffffff">enable_object</span>( <span style="background-color: #ffffff">p_object</span> <b>=&gt;</b> &#39;EMP&#39; )<span style="background-color: #ffffff">;</span> <b>end</b><span style="background-color: #ffffff">;</span> <p style="text-align: justify;">Then navigate to <strong>SQL Workshop &gt;&nbsp;Restful Services</strong> and check if the <strong>EMP</strong> table was enabled within the schema.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/234f9fc4e861d2971779b634eeca319d/rest_enabled_objects.JPG" style="width: 1515px; height: 240px;" /></p> <p style="text-align: justify;">Use <strong>http://{server}/ords/{schema-alias}/emp/</strong> (adjust the URL to your environment and workspace) to check the response. You should have some data displayed.</p> Create Application and Web Source Module <p style="text-align: justify;">Create a new, empty application using the Create Application Wizard or navigate to an existing one. Within your application, navigate to <strong>Shared Components</strong> and look up <strong>Web Source Modules</strong>&nbsp;in the Data Sources category.&nbsp;Click on <strong>Create</strong> Button in order to create a new Web Source Module <strong>from Scratch</strong>.&nbsp;On the next step, choose <strong>Oracle REST Data Services</strong> as the Web Source <strong>Type</strong>, provide a name and the URL from above as the&nbsp;<strong>URL Endpoint</strong>. Click <strong>Next</strong>.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/18ad6d3774bfd3e29a9df174021fbaa9/create_web_source.JPG" style="width: 804px; height: 483px;" /></p> <p>Keep the default settings for <strong>Remote Server</strong> on the next step and click <strong>Next</strong>.&nbsp;</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/c8696b9cb084878b137c402160343224/create_remote_server.JPG" style="width: 801px; height: 481px;" /></p> <p>For our exercise we set the <strong>Authentication Required</strong> to <strong>No</strong> and click on <strong>Discover</strong>.&nbsp;</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/b1cc5e9e63a0552d81d57bc39b2c5c4a/authentication.JPG" style="width: 802px; height: 482px;" /></p> <p>You will see the data preview for REST Service. Click on <strong>Create Web Source</strong>.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/81a6e68022bef0d22bd1891e4819c4e7/web_source_discovery.JPG" style="width: 802px; height: 481px;" /></p> <p style="text-align: justify;">Once the Web Source Module is created, you will be redirected to the overview page on existing Web Source Modules. We now need to make a few changes in the Web Source Module we just have created. Click on the module name.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/6a01e5ade4f1f868dfbb4e694eb887a1/web_source_module_created.JPG" style="width: 1721px; height: 162px;" /></p> <p style="text-align: justify;">Click the <strong>Advanced</strong> tab and set the Static ID to <strong>WebSourceModule_on_EMP</strong>, as we will need it when calling the Web Source Module with PL/SQL later on.</p> <p style="text-align: justify;"><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/2a5657cb44eb0ef4873fb3ea26553e42/static_id.JPG" style="width: 1714px; height: 293px;" />Open the <strong>Operations</strong>&nbsp;tab and click the pencil to edit the <strong>POST</strong> operation. Use the following JSON template as the&nbsp;<strong>Request Body Template:</strong></p> {&quot;empno&quot;:#EMPNO#,&quot;ename&quot;:&quot;#ENAME#&quot;,&quot;job&quot;:&quot;#JOB#&quot;,&quot;hiredate&quot;:&quot;#HIREDATE#&quot;,&quot;sal&quot;:#SAL#,&quot;comm&quot;:#COMM#,&quot;deptno&quot;:#DEPTNO#,&quot;mgr&quot;:#MGR#} <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/de499a6834dc8a6d274517b0b7865a35/post_body_template.JPG" style="width: 1714px; height: 317px;" /></p> <p style="text-align: justify;">Click <strong>Apply Changes</strong>, then click the pencil corresponding to the POST operation again and on <strong>Add Parameter</strong>. Create the following parameters and use <strong>Request / Response Body</strong> as the parameter <strong>Type</strong> and keep the <strong>Direction</strong> as <strong>In</strong>.</p> <ul> <li>EMPNO</li> <li>ENAME</li> <li>JOB</li> <li>HIREDATE</li> <li>SAL</li> <li>COMM</li> <li>MGR</li> <li>DEPTNO</li> </ul> <p style="text-align: justify;"><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/222a25efb7acd7d467ebdef520596a85/edit_web_source_parameter.JPG" style="width: 1541px; height: 603px;" />Then create an additional parameter named&nbsp;<strong>Content-Type</strong>, use&nbsp;<strong>application/json&nbsp;</strong>as its&nbsp;<strong>Value</strong>&nbsp;and&nbsp;<strong>HTTP Header</strong>&nbsp;as&nbsp;<strong>Type</strong>. Set the&nbsp;<strong>Static</strong>&nbsp;switch to&nbsp;<strong>No</strong>&nbsp;for this parameter. Once finished, you should have 9 parameters as follows. Finally click the <strong>Apply Changes</strong> button.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/6b16c4faa9cb17283ea0086debc8efc3/operation_parameters.JPG" style="width: 1715px; height: 438px;" /></p> Create the Interactive Grid <p style="text-align: justify;">After creating the Web Source Module, you&#39;ll now use Page Designer to create a new Interactive Grid region. Navigate to Page Designer for an existing page or create a new empty page. Then drag a region of the Interactive Grid type to the page, name it <strong>WSM Interactive Grid</strong> and use <strong>select * from emp</strong> as the region source query.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/e45d039f19593ac9e2c207ab71ffda97/ig_region.JPG" style="width: 291px; height: 431px;" /></p> <p>Then, head over to the region attributes, enable <strong>Editing</strong> and, for now, only allow to <strong>Add Row.</strong></p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/261bc91331b98999c0745509b3f3571f/ig_attributes.JPG" style="width: 288px; height: 342px;" /></p> Replace Standard DML processes with custom PL/SQL code <p style="text-align: justify;">Since you have created the interactive grid region on a query selecting the EMP table, any changes would be written back to the EMP table as well. But we want to write our changes &quot;to the web source module&quot;.</p> <p style="text-align: justify;">So we need to replace the standard interactive grid DML functionality with our own PL/SQL code. This code will use the <a href="https://docs.oracle.com/database/apex-18.1/AEAPI/APEX_EXEC.htm#AEAPI-GUID-3CF1D2DD-AEA4-4982-9857-548567AB7169" target="_blank">APEX_EXEC</a> PL/SQL package in order to invoke the Web Source Module. Note that <a href="https://docs.oracle.com/database/apex-18.1/AEAPI/APEX_EXEC.htm#AEAPI-GUID-3CF1D2DD-AEA4-4982-9857-548567AB7169" target="_blank">APEX_EXEC</a> package will encapsulate all data processing and querying capabilities. We do not need to use JSON parsing or make request calls anymore. Navigate to the <strong>Page Processes</strong> of your page and look up the Int<strong>eractive Grid - Automatic Row Processing (DML)</strong> process.&nbsp;</p> <p style="text-align: justify;">Navigate to the process attributes and change the <strong>Target Type</strong> attribute to <strong>PL/SQL </strong>and provide the following PL/SQL code.</p> <b>declare</b> <span style="background-color: #ffffff">l_parameters</span> <span style="background-color: #ffffff">apex_exec</span><span style="background-color: #ffffff">.</span><span style="background-color: #ffffff">t_parameters</span><span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">l_dateval</span> <b>date</b><span style="background-color: #ffffff">;</span> <b>begin</b> <i>-- how to handle nulls on HIREDATE</i> <b>if</b> <b>:HIREDATE</b> <b>is</b> null <b>then</b> <span style="background-color: #ffffff">l_dateval</span> <b>:=</b> sysdate<span style="background-color: #ffffff">;</span> <b>else</b> <span style="background-color: #ffffff">l_dateval</span> <b>:=</b> to_date( <b>:HIREDATE</b> )<span style="background-color: #ffffff">;</span> <b>end if</b><span style="background-color: #ffffff">;</span> <i>-- in this case we take into account only the INSERT operation therefore the condition will be based on :APEX$ROW_STATUS = &#39;C&#39;</i> <i>-- APEX_EXEC.ADD_PARAMETER procedure adds an SQL parameter to the parameter collection</i> <b>if</b> <b>:APEX$ROW_STATUS</b> <b>=</b> &#39;C&#39; <b>then</b> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;ENAME&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> <b>:ENAME</b> )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;EMPNO&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> <b>:EMPNO</b> )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;JOB&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> <b>:JOB</b> )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;HIREDATE&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> to_char( <span style="background-color: #ffffff">l_dateval</span><span style="background-color: #ffffff">,</span> &#39;YYYY-MM-DD&#39; ) <b>||</b> &#39;T00:00:00Z&#39; )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;SAL&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> coalesce( <b>:SAL</b><span style="background-color: #ffffff">,</span> &#39;null&#39; ) )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;COMM&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> coalesce( <b>:COMM</b><span style="background-color: #ffffff">,</span> &#39;null&#39; ) )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;MGR&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> coalesce( <b>:MGR</b><span style="background-color: #ffffff">,</span> &#39;null&#39; ) )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;DEPTNO&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> coalesce( <b>:DEPTNO</b><span style="background-color: #ffffff">,</span> &#39;null&#39; ) )<span style="background-color: #ffffff">;</span> <b>end if</b><span style="background-color: #ffffff">;</span> <i>-- invoke Web Source Module for and select data</i> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">execute_web_source</span>( <span style="background-color: #ffffff">p_module_static_id</span> <b>=&gt;</b> &#39;WebSourceModule_on_EMP&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_operation</span> <b>=&gt;</b> <b>case</b> <b>:APEX$ROW_STATUS</b> <b>when</b> &#39;C&#39; <b>then</b> &#39;POST&#39; <b>end</b><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span> )<span style="background-color: #ffffff">;</span> <b>end</b><span style="background-color: #ffffff">;</span> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/3c58b6924d27eacf8f1beb746c8dbe42/pl_sql_code_process.JPG" style="width: 969px; height: 601px;" /></p> Test the functionality <p style="text-align: justify;">Now it&#39;s time to do a first test on the Interactive Grid. Save your changes and run the page. First, the Interactive Grid looks as follows:</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/5f917ee2a240dd4bc72d7d822fc4766d/initial_data.JPG" style="width: 1686px; height: 558px;" /></p> <p>Do a few changes and save the page ...</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/999f1655b9585abbfd132229d0193656/after_insert_data.JPG" style="width: 1677px; height: 572px;" /></p> <p style="text-align: justify;">When saving the changes to the interactive grid, you should notice that the actual DML operation takes a bit longer than usual. This is because interactive grid does now do a REST service invocation instead of simply executing SQL DML on a local table.&nbsp;</p> Adding validations to avoid error messages from the REST service <p style="text-align: justify;">However, depending on the actual data being entered, you won&#39;t see successful changes, but error messages instead:</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/b0da9fcb1219a2b6df42ac29b037465e/web_source_error.JPG" style="width: 450px; height: 155px;" /></p> <p style="text-align: justify;">This can happen when the entered data violates constraints being in place. Within the Oracle Database, we would see a clear ORA error message telling us what went wrong. However, a REST infrastructure does not know about databases and ORA error messages - REST is all about HTTP. A REST service responds with a HTTP status code, which is 200 for a successful operation and between 400 and 599 for error situations. The meanings of HTTP status codes are very generic - they have been made for HTTP and the web, not for interacting with a table in a database.</p> <p style="text-align: justify;">So, when the REST POST operation results in an error (because of table constraints), the REST service will just respond with either HTTP-500 (Internal Server Error) or HTTP-400 (Bad Request). To avoid end users running into these error messages, we should add&nbsp;<strong>Validations&nbsp;</strong>to the Interactive Grid columns - in order to make sure that only valid data is being posted to the REST Service. In Page Designer, navigate to the Interactive Grid, open the Columns node in the navigation tree on the left and add Validations to the columns as follows:</p> The manager EMPNO, being inserted, is already present in the table <p style="text-align: justify;">Create a validation on the <strong>MGR</strong> column,&nbsp;pick <strong>Rows Returned</strong> as the Validation type and use <strong>select 1 from emp where empno = :MGR</strong> as the SQL Query.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/2c9645e717f7012d7f64e4a1d8dd441d/check_manager_validation.JPG" style="width: 971px; height: 779px;" /></p> The Salary is a valid number and between 0 and 100000. <p style="text-align: justify;">Create a validation on the&nbsp;<strong>SAL</strong>&nbsp;column,&nbsp;pick&nbsp;<strong>Rows Returned</strong>&nbsp;as the Validation type and use&nbsp;<strong>select 1&nbsp;from dual&nbsp;where trunc(nvl(:SAL,0),2) &lt; 100000</strong> as the SQL Query.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/95213e8e9156cbf8d9c57b57286939ef/check_salary_validation.JPG" style="width: 969px; height: 780px;" /></p> Make sure that the DEPTNO value is existent in the DEPT table <p style="text-align: justify;">Create a validation on the&nbsp;<strong>DEPTNO</strong>&nbsp;column,&nbsp;pick&nbsp;<strong>Rows Returned</strong>&nbsp;as the Validation type and use&nbsp;<strong>select 1&nbsp;from dept&nbsp;where deptno = :DEPTNO</strong>&nbsp;as the SQL Query.</p> The Commission value is a valid number and between 0 and 100000. <p style="text-align: justify;">Create a validation on the&nbsp;<strong>COMM</strong>&nbsp;column,&nbsp;pick&nbsp;<strong>Rows Returned</strong>&nbsp;as the Validation type and use&nbsp;<strong>select 1&nbsp;from dual&nbsp;where trunc(nvl(:COMM,0),2) &lt; 100000</strong>&nbsp;as the SQL Query.</p> <p style="text-align: justify;">After these changes being applied, the interactive grid will not allow to post invalid values to the REST service any more. This concludes the first blog posting on REST-Enabling the Interactive Grid component. Subsequent postings will explain how to implement DELETE and UPDATE operations and how to have the interactive grid displaying data from the REST service as well.</p> p.p1 {margin: 0.0px 0.0px 8.0px 0.0px; font: 12.0px 'Times New Roman'; color: #000000; -webkit-text-stroke: #000000; min-height: 15.0px} p.p2 {margin: 0.0px 0.0px 8.0px 0.0px; font: 12.0px 'Times New Roman'; color: #000000; -webkit-text-stroke: #000000} span.s1 {font-kerning: none} Carsten Czarski https://blogs.oracle.com/apex/web-source-modules-and-the-interactive-grid-part-1 Fri Oct 12 2018 03:50:00 GMT-0400 (EDT) Web Source Modules and the Interactive Grid: Part 1 https://blogs.oracle.com/apex/web-source-modules-and-the-interactive-grid-part-1 <p><strong>by Andreea Dobre, Oracle Romania in Bucharest</strong></p> <p style="text-align: justify;">With Application Express 18.1, APEX introduced support for using REST Services directly in APEX components: Using <span><a href="https://blogs.oracle.com/apex/get-started-with-rest-services-in-application-express-52-ea-1">Web Source Modules</a></span>, reports, charts or calendar regions can work directly on top of a REST service - with no manual coding required.&nbsp;However, only &bdquo;read only&ldquo; components support REST Services, thus we can create an Interactive Report or a Chart page on top of a REST service, but not a form page or an Interactive Grid.&nbsp;</p> <p style="text-align: justify;">The good news is: With a Web Source Module and some custom PL/SQL code, using the <a href="https://docs.oracle.com/database/apex-18.1/AEAPI/APEX_EXEC.htm#AEAPI-GUID-3CF1D2DD-AEA4-4982-9857-548567AB7169" target="_blank">APEX_EXEC</a> package, you can REST-enable your Interactive Grid based on a REST Service today. The INSERT, UPDATE or DELETE operations of the interactive Grid will map to the POST, PUT and DELETE operations of a REST service.</p> <p style="text-align: justify;">This blog posting, which is the first part of a series on REST-Enabling the Interactive Grid, will show how this works. The well-known EMP table and a REST service on top of it will serve as an example. This first part will show ...</p> <ul> <li>how to create a Web Source Module on top of a REST service</li> <li>how to create an interactive grid (on a local table first)</li> <li>how to have the interactive grid invoke the REST service for SQL INSERT operations</li> </ul> <p style="text-align: justify;">Following blog postings will show how to complete that scenario, i.e. support other DML operations and have Interactive Grid actually&nbsp;<em>show</em> data from the REST service.</p> Prerequisites <p style="text-align: justify;">In order to have a proper environment where to start playing with REST Services, go to <a href="https://apex.oracle.com" target="_blank">apex.oracle.com</a> and sign up for a free workspace. Navigate to <strong>SQL Workshop &gt; RESTful Services</strong> and make sure to check <strong>ORDS Based RESTful Services</strong>.</p> <p style="text-align: justify;"><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/7f1edf4cc4f2aae196fe10d077a39507/restful_service_options.JPG" style="width: 1915px; height: 318px;" /><br /> <br /> The environment is now ready to go. First we need to REST-Enable the database schema, which is assigned to the APEX workspace. This can be done in <strong>SQL Workshop &gt; RESTful Services &gt; Register Schema with ORDS</strong>. As an alternative, you can do that with the following SQL statements in <strong>SQL Workshop &gt; SQL Commands</strong>.</p> <b>begin</b> <span style="background-color: #ffffff">ords</span>.<span style="background-color: #ffffff">enable_schema</span><span style="background-color: #ffffff">;</span> <b>end</b><span style="background-color: #ffffff">;</span> <p style="text-align: justify;">Next, we need to create a REST Endpoint for a table. The easiest way to achieve that is to simply &bdquo;REST-Enable&ldquo; the table as follows. REST-Enabling a table will create GET, POST, PUT and DELETE endpoints.</p> <b>begin</b> <span style="background-color: #ffffff">ords</span>.<span style="background-color: #ffffff">enable_object</span>( <span style="background-color: #ffffff">p_object</span> <b>=&gt;</b> &#39;EMP&#39; )<span style="background-color: #ffffff">;</span> <b>end</b><span style="background-color: #ffffff">;</span> <p style="text-align: justify;">Then navigate to <strong>SQL Workshop &gt;&nbsp;Restful Services</strong> and check if the <strong>EMP</strong> table was enabled within the schema.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/234f9fc4e861d2971779b634eeca319d/rest_enabled_objects.JPG" style="width: 1515px; height: 240px;" /></p> <p style="text-align: justify;">Use <strong>http://{server}/ords/{schema-alias}/emp/</strong> (adjust the URL to your environment and workspace) to check the response. You should have some data displayed.</p> Create Application and Web Source Module <p style="text-align: justify;">Create a new, empty application using the Create Application Wizard or navigate to an existing one. Within your application, navigate to <strong>Shared Components</strong> and look up <strong>Web Source Modules</strong>&nbsp;in the Data Sources category.&nbsp;Click on <strong>Create</strong> Button in order to create a new Web Source Module <strong>from Scratch</strong>.&nbsp;On the next step, choose <strong>Oracle REST Data Services</strong> as the Web Source <strong>Type</strong>, provide a name and the URL from above as the&nbsp;<strong>URL Endpoint</strong>. Click <strong>Next</strong>.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/18ad6d3774bfd3e29a9df174021fbaa9/create_web_source.JPG" style="width: 804px; height: 483px;" /></p> <p>Keep the default settings for <strong>Remote Server</strong> on the next step and click <strong>Next</strong>.&nbsp;</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/c8696b9cb084878b137c402160343224/create_remote_server.JPG" style="width: 801px; height: 481px;" /></p> <p>For our exercise we set the <strong>Authentication Required</strong> to <strong>No</strong> and click on <strong>Discover</strong>.&nbsp;</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/b1cc5e9e63a0552d81d57bc39b2c5c4a/authentication.JPG" style="width: 802px; height: 482px;" /></p> <p>You will see the data preview for REST Service. Click on <strong>Create Web Source</strong>.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/81a6e68022bef0d22bd1891e4819c4e7/web_source_discovery.JPG" style="width: 802px; height: 481px;" /></p> <p style="text-align: justify;">Once the Web Source Module is created, you will be redirected to the overview page on existing Web Source Modules. We now need to make a few changes in the Web Source Module we just have created. Click on the module name.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/6a01e5ade4f1f868dfbb4e694eb887a1/web_source_module_created.JPG" style="width: 1721px; height: 162px;" /></p> <p style="text-align: justify;">Click the <strong>Advanced</strong> tab and set the Static ID to <strong>WebSourceModule_on_EMP</strong>, as we will need it when calling the Web Source Module with PL/SQL later on.</p> <p style="text-align: justify;"><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/2a5657cb44eb0ef4873fb3ea26553e42/static_id.JPG" style="width: 1714px; height: 293px;" />Open the <strong>Operations</strong>&nbsp;tab and click the pencil to edit the <strong>POST</strong> operation. Use the following JSON template as the&nbsp;<strong>Request Body Template:</strong></p> {&quot;empno&quot;:#EMPNO#,&quot;ename&quot;:&quot;#ENAME#&quot;,&quot;job&quot;:&quot;#JOB#&quot;,&quot;hiredate&quot;:&quot;#HIREDATE#&quot;,&quot;sal&quot;:#SAL#,&quot;comm&quot;:#COMM#,&quot;deptno&quot;:#DEPTNO#,&quot;mgr&quot;:#MGR#} <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/de499a6834dc8a6d274517b0b7865a35/post_body_template.JPG" style="width: 1714px; height: 317px;" /></p> <p style="text-align: justify;">Click <strong>Apply Changes</strong>, then click the pencil corresponding to the POST operation again and on <strong>Add Parameter</strong>. Create the following parameters and use <strong>Request / Response Body</strong> as the parameter <strong>Type</strong> and keep the <strong>Direction</strong> as <strong>In</strong>.</p> <ul> <li>EMPNO</li> <li>ENAME</li> <li>JOB</li> <li>HIREDATE</li> <li>SAL</li> <li>COMM</li> <li>MGR</li> <li>DEPTNO</li> </ul> <p style="text-align: justify;"><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/222a25efb7acd7d467ebdef520596a85/edit_web_source_parameter.JPG" style="width: 1541px; height: 603px;" />Then create an additional parameter named&nbsp;<strong>Content-Type</strong>, use&nbsp;<strong>application/json&nbsp;</strong>as its&nbsp;<strong>Value</strong>&nbsp;and&nbsp;<strong>HTTP Header</strong>&nbsp;as&nbsp;<strong>Type</strong>. Set the&nbsp;<strong>Static</strong>&nbsp;switch to&nbsp;<strong>No</strong>&nbsp;for this parameter. Once finished, you should have 9 parameters as follows. Finally click the <strong>Apply Changes</strong> button.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/6b16c4faa9cb17283ea0086debc8efc3/operation_parameters.JPG" style="width: 1715px; height: 438px;" /></p> Create the Interactive Grid <p style="text-align: justify;">After creating the Web Source Module, you&#39;ll now use Page Designer to create a new Interactive Grid region. Navigate to Page Designer for an existing page or create a new empty page. Then drag a region of the Interactive Grid type to the page, name it <strong>WSM Interactive Grid</strong> and use <strong>select * from emp</strong> as the region source query.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/e45d039f19593ac9e2c207ab71ffda97/ig_region.JPG" style="width: 291px; height: 431px;" /></p> <p>Then, head over to the region attributes, enable <strong>Editing</strong> and, for now, only allow to <strong>Add Row.</strong></p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/261bc91331b98999c0745509b3f3571f/ig_attributes.JPG" style="width: 288px; height: 342px;" /></p> Replace Standard DML processes with custom PL/SQL code <p style="text-align: justify;">Since you have created the interactive grid region on a query selecting the EMP table, any changes would be written back to the EMP table as well. But we want to write our changes &quot;to the web source module&quot;.</p> <p style="text-align: justify;">So we need to replace the standard interactive grid DML functionality with our own PL/SQL code. This code will use the <a href="https://docs.oracle.com/database/apex-18.1/AEAPI/APEX_EXEC.htm#AEAPI-GUID-3CF1D2DD-AEA4-4982-9857-548567AB7169" target="_blank">APEX_EXEC</a> PL/SQL package in order to invoke the Web Source Module. Note that <a href="https://docs.oracle.com/database/apex-18.1/AEAPI/APEX_EXEC.htm#AEAPI-GUID-3CF1D2DD-AEA4-4982-9857-548567AB7169" target="_blank">APEX_EXEC</a> package will encapsulate all data processing and querying capabilities. We do not need to use JSON parsing or make request calls anymore. Navigate to the <strong>Page Processes</strong> of your page and look up the Int<strong>eractive Grid - Automatic Row Processing (DML)</strong> process.&nbsp;</p> <p style="text-align: justify;">Navigate to the process attributes and change the <strong>Target Type</strong> attribute to <strong>PL/SQL </strong>and provide the following PL/SQL code.</p> <b>declare</b> <span style="background-color: #ffffff">l_parameters</span> <span style="background-color: #ffffff">apex_exec</span><span style="background-color: #ffffff">.</span><span style="background-color: #ffffff">t_parameters</span><span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">l_dateval</span> <b>date</b><span style="background-color: #ffffff">;</span> <b>begin</b> <i>-- how to handle nulls on HIREDATE</i> <b>if</b> <b>:HIREDATE</b> <b>is</b> null <b>then</b> <span style="background-color: #ffffff">l_dateval</span> <b>:=</b> sysdate<span style="background-color: #ffffff">;</span> <b>else</b> <span style="background-color: #ffffff">l_dateval</span> <b>:=</b> to_date( <b>:HIREDATE</b> )<span style="background-color: #ffffff">;</span> <b>end if</b><span style="background-color: #ffffff">;</span> <i>-- in this case we take into account only the INSERT operation therefore the condition will be based on :APEX$ROW_STATUS = &#39;C&#39;</i> <i>-- APEX_EXEC.ADD_PARAMETER procedure adds an SQL parameter to the parameter collection</i> <b>if</b> <b>:APEX$ROW_STATUS</b> <b>=</b> &#39;C&#39; <b>then</b> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;ENAME&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> <b>:ENAME</b> )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;EMPNO&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> <b>:EMPNO</b> )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;JOB&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> <b>:JOB</b> )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;HIREDATE&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> to_char( <span style="background-color: #ffffff">l_dateval</span><span style="background-color: #ffffff">,</span> &#39;YYYY-MM-DD&#39; ) <b>||</b> &#39;T00:00:00Z&#39; )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;SAL&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> coalesce( <b>:SAL</b><span style="background-color: #ffffff">,</span> &#39;null&#39; ) )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;COMM&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> coalesce( <b>:COMM</b><span style="background-color: #ffffff">,</span> &#39;null&#39; ) )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;MGR&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> coalesce( <b>:MGR</b><span style="background-color: #ffffff">,</span> &#39;null&#39; ) )<span style="background-color: #ffffff">;</span> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">add_parameter</span>( <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_name</span> <b>=&gt;</b> &#39;DEPTNO&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_value</span> <b>=&gt;</b> coalesce( <b>:DEPTNO</b><span style="background-color: #ffffff">,</span> &#39;null&#39; ) )<span style="background-color: #ffffff">;</span> <b>end if</b><span style="background-color: #ffffff">;</span> <i>-- invoke Web Source Module for and select data</i> <span style="background-color: #ffffff">apex_exec</span>.<span style="background-color: #ffffff">execute_web_source</span>( <span style="background-color: #ffffff">p_module_static_id</span> <b>=&gt;</b> &#39;WebSourceModule_on_EMP&#39;<span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_operation</span> <b>=&gt;</b> <b>case</b> <b>:APEX$ROW_STATUS</b> <b>when</b> &#39;C&#39; <b>then</b> &#39;POST&#39; <b>end</b><span style="background-color: #ffffff">,</span> <span style="background-color: #ffffff">p_parameters</span> <b>=&gt;</b> <span style="background-color: #ffffff">l_parameters</span> )<span style="background-color: #ffffff">;</span> <b>end</b><span style="background-color: #ffffff">;</span> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/3c58b6924d27eacf8f1beb746c8dbe42/pl_sql_code_process.JPG" style="width: 969px; height: 601px;" /></p> Test the functionality <p style="text-align: justify;">Now it&#39;s time to do a first test on the Interactive Grid. Save your changes and run the page. First, the Interactive Grid looks as follows:</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/5f917ee2a240dd4bc72d7d822fc4766d/initial_data.JPG" style="width: 1686px; height: 558px;" /></p> <p>Do a few changes and save the page ...</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/999f1655b9585abbfd132229d0193656/after_insert_data.JPG" style="width: 1677px; height: 572px;" /></p> <p style="text-align: justify;">When saving the changes to the interactive grid, you should notice that the actual DML operation takes a bit longer than usual. This is because interactive grid does now do a REST service invocation instead of simply executing SQL DML on a local table.&nbsp;</p> Adding validations to avoid error messages from the REST service <p style="text-align: justify;">However, depending on the actual data being entered, you won&#39;t see successful changes, but error messages instead:</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/b0da9fcb1219a2b6df42ac29b037465e/web_source_error.JPG" style="width: 450px; height: 155px;" /></p> <p style="text-align: justify;">This can happen when the entered data violates constraints being in place. Within the Oracle Database, we would see a clear ORA error message telling us what went wrong. However, a REST infrastructure does not know about databases and ORA error messages - REST is all about HTTP. A REST service responds with a HTTP status code, which is 200 for a successful operation and between 400 and 599 for error situations. The meanings of HTTP status codes are very generic - they have been made for HTTP and the web, not for interacting with a table in a database.</p> <p style="text-align: justify;">So, when the REST POST operation results in an error (because of table constraints), the REST service will just respond with either HTTP-500 (Internal Server Error) or HTTP-400 (Bad Request). To avoid end users running into these error messages, we should add&nbsp;<strong>Validations&nbsp;</strong>to the Interactive Grid columns - in order to make sure that only valid data is being posted to the REST Service. In Page Designer, navigate to the Interactive Grid, open the Columns node in the navigation tree on the left and add Validations to the columns as follows:</p> The manager EMPNO, being inserted, is already present in the table <p style="text-align: justify;">Create a validation on the <strong>MGR</strong> column,&nbsp;pick <strong>Rows Returned</strong> as the Validation type and use <strong>select 1 from emp where empno = :MGR</strong> as the SQL Query.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/2c9645e717f7012d7f64e4a1d8dd441d/check_manager_validation.JPG" style="width: 971px; height: 779px;" /></p> The Salary is a valid number and between 0 and 100000. <p style="text-align: justify;">Create a validation on the&nbsp;<strong>SAL</strong>&nbsp;column,&nbsp;pick&nbsp;<strong>Rows Returned</strong>&nbsp;as the Validation type and use&nbsp;<strong>select 1&nbsp;from dual&nbsp;where trunc(nvl(:SAL,0),2) &lt; 100000</strong> as the SQL Query.</p> <p><img alt="" src="https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/fbd61610-2cfe-4a98-b117-958129af0c39/Image/95213e8e9156cbf8d9c57b57286939ef/check_salary_validation.JPG" style="width: 969px; height: 780px;" /></p> Make sure that the DEPTNO value is existent in the DEPT table <p style="text-align: justify;">Create a validation on the&nbsp;<strong>DEPTNO</strong>&nbsp;column,&nbsp;pick&nbsp;<strong>Rows Returned</strong>&nbsp;as the Validation type and use&nbsp;<strong>select 1&nbsp;from dept&nbsp;where deptno = :DEPTNO</strong>&nbsp;as the SQL Query.</p> The Commission value is a valid number and between 0 and 100000. <p style="text-align: justify;">Create a validation on the&nbsp;<strong>COMM</strong>&nbsp;column,&nbsp;pick&nbsp;<strong>Rows Returned</strong>&nbsp;as the Validation type and use&nbsp;<strong>select 1&nbsp;from dual&nbsp;where trunc(nvl(:COMM,0),2) &lt; 100000</strong>&nbsp;as the SQL Query.</p> <p style="text-align: justify;">After these changes being applied, the interactive grid will not allow to post invalid values to the REST service any more. This concludes the first blog posting on REST-Enabling the Interactive Grid component. Subsequent postings will explain how to implement DELETE and UPDATE operations and how to have the interactive grid displaying data from the REST service as well.</p> p.p1 {margin: 0.0px 0.0px 8.0px 0.0px; font: 12.0px 'Times New Roman'; color: #000000; -webkit-text-stroke: #000000; min-height: 15.0px} p.p2 {margin: 0.0px 0.0px 8.0px 0.0px; font: 12.0px 'Times New Roman'; color: #000000; -webkit-text-stroke: #000000} span.s1 {font-kerning: none} Carsten Czarski https://blogs.oracle.com/apex/web-source-modules-and-the-interactive-grid-part-1 Fri Oct 12 2018 03:50:00 GMT-0400 (EDT) ODC Appreciation Day: Old Blog Posts http://oradbdev.mathiasmagnusson.com/2018/10/11/odc-appreciation-day-old-blog-posts/ <p>FIrst of all, kudos to  <a href="https://twitter.com/oraclebase">Tim Hall</a><span class="username u-dir" dir="ltr">. This is one of the great times of the year when all these thankful blogs are posted in a day. If you read nothing else in the blogs all year, picking some of them would not be a bad choice.</span></p> <p>Speaking of which, I will talk about being thankful for blogs in general. No, not about the new ones explaining all the new features we get in new versions. While that is very fascinating and motivates me to play with new tech, it is not the great thing with blogs.</p> <p>What I think is great with blogs is old blogs. Yes, there may be few things as unsexy as old forgotten blog posts.</p> <p>When there is an issue to resolve or a concept to get up to speed on, there are few things better than the blogs written  a year or ten ago. But are not everyone experts on everything when some time has passed. Nope, not even one person is a specialist on every facet of Oracle database technology.</p> <p>Sometimes it is one thing one knows fairly well but needs a to understand edge cases, experiences, when not to use and so forth. Then a short google session generates a reading list as good as any book.</p> <p>A few examples of blogs I have stumbled on that was not published this year but that provided great information and input follows. They are just things from the top of my mind when thinking back about such blogs.</p> <p><a href="https://twitter.com/tobias_arnhold">Tobias Arnhold</a> wrote about <a href="https://www.apex-at-work.com/2012/07/getting-apex-views.html">views provided by APEX</a>. It shows a SQL listing all the views and shows the views hierarchical relationship. Not only was that useful, but a side effect was that I realized this was available as well as that the relationship could be found in metadata. It is a post over six years old, often thought of long forgotten. Still very applicable. In fact,  Tobias may even have forgotten the post himself, it is even more applicable today as there have been a lot of views added to the ones available back in 2012,</p> <p>Another  great one is <a href="https://connor-mcdonald.com/">Connor McDonalds</a> &#8211;<span class="username u-dir" dir="ltr"><a class="ProfileHeaderCard-screennameLink u-linkComplex js-nav" href="https://twitter.com/connor_mc_d">@<b class="u-linkComplex-target">connor_mc_d</b></a> &#8211;</span>post from early 2016 on <a href="https://blogs.oracle.com/oraclemagazine/a-fresh-look-at-auditing-row-changes">auditing row changes</a>. It is a great collection of all the things provided to uyou to avoid auditing columns, tables, triggers and so forth. Including a complete test case and demo from start to finish. Still two years old, but when needed it is a great start.</p> <p>Then there are of course classics like <a href="https://twitter.com/ToonKoppelaars">Toon Koppelaars</a> blog <a href="http://thehelsinkideclaration.blogspot.com/2009/03/helsinki-declaration-observation-1.html">The Helsinki Declaration (IT-Version) </a>that starts with the IT-version of it. If you have not read the four posts it consists of, you owe it to yourself to do so. Go back to the beginning. It should be mandatory reading for how to build database intensive applications.</p> <p>I leave it at those to not extend this post more than necessary. But it shows the value of the combined effort of the community to write down small and big things as we come across them. There is immense value in those posts long after they have been written. Some are even more valuable a few years later when the world and the technology has matured enough to make it mainstream.</p> <p>#ThanksODC</p> <p>&nbsp;</p> <p>&nbsp;</p> mathias http://oradbdev.mathiasmagnusson.com/?p=1001 Thu Oct 11 2018 16:17:03 GMT-0400 (EDT) OTN/ODC Appreciation Day 2018 – Thanks for the mutating table error! https://svenweller.wordpress.com/2018/10/11/odc-appreciation-day-2018-thanks-for-the-mutating-table-error/ <p><em>This is not sarcasm!</em></p> <h2>What is the mutating table error?</h2> <p>I firmly believe the mutating table error is a good thing. For anybody who does not know what I am talking about here is an example.</p> <p>There are various ways how the error can happen. A before row trigger is probably the most typical scenario.</p> <p><em>Since Halloween is getting close, I need a table to organize the personell for my evil lab. I setup a table that holds each member devided by departments. Only one labhead per department is allowed. This integrity rule is enforced by table triggers.</em><br /> <img data-attachment-id="7890" data-permalink="https://svenweller.wordpress.com/2018/10/11/odc-appreciation-day-2018-thanks-for-the-mutating-table-error/maniac_mansion_scientist/" data-orig-file="https://svenweller.files.wordpress.com/2018/10/maniac_mansion_scientist-e1539774236987.jpg?w=809" data-orig-size="480,272" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="maniac_mansion_scientist" data-image-description="" data-medium-file="https://svenweller.files.wordpress.com/2018/10/maniac_mansion_scientist-e1539774236987.jpg?w=809?w=300" data-large-file="https://svenweller.files.wordpress.com/2018/10/maniac_mansion_scientist-e1539774236987.jpg?w=809?w=480" src="https://svenweller.files.wordpress.com/2018/10/maniac_mansion_scientist-e1539774236987.jpg?w=809" alt="maniac_mansion_scientist" class="alignnone size-full wp-image-7890" srcset="https://svenweller.files.wordpress.com/2018/10/maniac_mansion_scientist-e1539774236987.jpg 480w, https://svenweller.files.wordpress.com/2018/10/maniac_mansion_scientist-e1539774236987.jpg?w=150 150w, https://svenweller.files.wordpress.com/2018/10/maniac_mansion_scientist-e1539774236987.jpg?w=300 300w" sizes="(max-width: 480px) 100vw, 480px" /></p> <pre class="brush: sql; title: ; notranslate"> -- build demo create table swe_test_mutating (id number not null primary key ,name varchar2(1000) not null ,department varchar2(254) ,is_head_of_department varchar2(1) constraint yn_ck check (is_head_of_department in ('Y','N')) ); -- trigger to make sure that there is only one head of department. create or replace trigger swe_test_mutating_bri before insert or update on swe_test_mutating for each row declare v_dummy varchar2(1); begin if :new.is_head_of_department = 'Y' then -- check if there is at least one other person -- for the same department -- which is also marked as HEAD begin select is_head_of_department into v_dummy from swe_test_mutating where id != :new.id -- must be different and department = :new.department -- must be same department and is_head_of_department = 'Y' -- is head and rownum &lt;= 1 -- enough if we find one ; raise_application_error(-20000, &#039;There can only be one head of &#039;||:new.department||&#039;!&#039;); exception when no_data_found then -- ok. Single head of department only null; end; end if; end; / </pre> <p><code>Trigger SWE_TEST_MUTATING_BRI compiled</code></p> <p><em>add some data</em></p> <pre class="brush: sql; light: true; title: ; notranslate"> -- add some personell to the evil lab insert into swe_test_mutating values (1, 'The master', 'LAB05', 'Y'); </pre> <p><code>1 row inserted.</code></p> <pre class="brush: sql; light: true; title: ; notranslate"> insert into swe_test_mutating values (2, 'The apprentice', 'LAB05', 'N'); </pre> <p><code>1 row inserted.</code></p> <pre class="brush: sql; light: true; title: ; notranslate"> insert into swe_test_mutating values (3, 'Doc Holiday', 'LAB05', 'Y'); </pre> <p><code><span style="color:orange;">ORA-20000: There can only be one head of LAB05!</span><br /> ORA-06512: at "EVIL_LAB.SWE_TEST_MUTATING_BRI", line 17<br /> ORA-04088: error during execution of trigger 'EVIL_LAB.SWE_TEST_MUTATING_BRI'<br /> </code><br /> This shows, the trigger worked for single row inserts. The logic inside the trigger prevented us from adding a second head for one department (LAB05).</p> <p>Now a test with multi row inserts.</p> <pre class="brush: sql; light: true; title: ; notranslate"> insert into swe_test_mutating ( select 4, 'Mr. Sissorhands', 'LAB07', 'Y' from dual union all select 5, 'Nagging Nanny', 'LAB07', 'N' from dual union all select 6, 'Evil Clown', 'LAB07', 'Y' from dual ); </pre> <p><code><span style="color:red;">ORA-04091: table EVIL_LAB.SWE_TEST_MUTATING is mutating, trigger/function may not see it</span><br /> ORA-06512: at "EVIL_LAB.SWE_TEST_MUTATING_BRI", line 8<br /> ORA-04088: error during execution of trigger 'EVIL_LAB.SWE_TEST_MUTATING_BRI'<br /> </code><br /> So what happend? We got an error (ORA-04091) saying, we are not allowed to work with the same table that is currently modified.</p> <p>We would have gotten the same mutating error even if the select part has only one row. If there is an insert..select then it is considered a multi row insert and then the mutating table error bites.</p> <h2>Why is the mutating table error a good thing?</h2> <p>There are multiple reasons</p> <p>1) The error prevents developers from making stupid mistakes.</p> <p>I like to compare it to a safety catch. On a pistol it prevents the developer from shooting their own foot. On a climbing rope it prevents the developer from plummeting to death, if something breaks loose. If you remove the safety catch on purpose, then it is <strong>your own risk</strong>. Only remove it if you are absolutly sure what you are doing.</p> <p>Without the error it is easy to create endless loops. Think about what happens, if we do an update on the same table in an after update row trigger. This update would again trigger another update which would trigger yet another update and so on. Eventually we run out of disk space (archive/redo logs) or something else dramatic happens.</p> <p>The mutating table error stops us (developers) from creating such an endless loop or making other mistakes (that mostly have to do with read consistency).</p> <p>2) The Error and I have a little bit of history together. </p> <p><a href="https://imgs.xkcd.com/comics/error_code.png"><img src="https://imgs.xkcd.com/comics/error_code.png" style="max-width:100%;" /></a></p> <p>In one of my first big projects almost all tables had validity columns (valid_from and valid_to). We used triggers to make sure that certain validity rules were also considered over relationships. </p> <p>For example if the validity of a parent record was extended, then the validity of a detail record needed to be extended too &#8211; but only, if it didn&#8217;t clash with any of the other detail records. Very complex rules.</p> <p>Those triggers always ended up with mutating or constraining table errors, so in the end the whole logic needed to be moved to after statement triggers. It was a hell to maintain. </p> <p>Nowadays I would not put all those logic into triggers, instead I would use packaged low level APIs that also make sure have all the integrity rules in place. The code would look so much cleaner with that.</p> <p>I believe having gone through this experience, made me a better developer. </p> <p>3) The error is complex to understand. </p> <p>I do understand it. Which gives me the chance to educate about it. Sharing and passing on knowledge is a fun and highly satisfying thing to do. As is writing such a blog post.</p> <h2>Error Darwinism</h2> <p>Interestingly errors seem to comply to the laws of natural selection. </p> <p>Here is what I noticed how the mutating table error has evolved over time. </p> <ul> <li>It now (since 10g I believe) bites only if more than one row is inserted (or updated or deleted. Which is a very hideous thing to do. Novice developers test using single row inserts. Experienced developers know they should use bulk inserts and test accordingly. </li> <li>The little brother of the mutating table error was the constraining table error.<br /> AskTom: &#8220;A mutating table is a table that is being modified. A constraining table is one involved in declaritive referential integrity with the mutating table.&#8221;</p> <p>Evolution took its toll on it. The constraining table error now is rarly seen in the wild. I asked around a bit, and there were no developers that found it recently. Most didn&#8217;t even know it existed. We might consider it to be extinct. </li> <li>Compound triggers appeared in 11.1. They help to deal with the error in a quick and not so dirty way. So they are a kind of master predator for this error. </li> <li>The recommendation about the errors have changed. Certain tools, like Oracle SQL developer show additional information if an error happend. In the case of the ORA-04091 those additional notes included something about &#8220;pragma autonomous transaction&#8221;. This hint was very misleading. Nowadays the misinformation is gone.<br /> It was like a mosquito (bug) infection in a swamp. The swamp is now dried up, so we see less mosquitos feeding upon that error.</li> </ul> <h2>How to avoid the error?</h2> <p>Anyone who tries to avoid the mutating table error by using the PRAGMA AUTONOMOUS TRANSACTION creates another bug. For a while the error message was misleading and trapped novice developers into thinking that this pragma is the right way to circumvent the issue. It is not. Bug count &gt;= 2 after that pragma. </p> <p>So how to correct it? We move the logic to the after statement trigger. In the past we needed 3 different table triggers to do it correctly. A before statement trigger to initialize a package variable, a row trigger to store the IDs of all records that were touched by the DML and an after statement trigger to do the actual work based upon those stored IDs. By using a compound trigger we can combine those three triggers and make the code look much cleaner.</p> <p>Here is one way how to do it.</p> <pre class="brush: sql; title: ; notranslate"> -- compound trigger to make sure that there is only one head of each evil lab (department). create or replace trigger swe_test_mutating_comptrg for insert or update on swe_test_mutating compound trigger -- define collection type type ID_t is table of swe_test_mutating.id%type index by binary_integer; -- define variable to hold a list of IDs IDs ID_t; before statement is begin -- no initialization needed for compound trigger null; end before statement; after each row is begin -- check if we have a new head of department if :new.is_head_of_department = 'Y' and (:old.is_head_of_department is null -- insert or :new.is_head_of_department != 'Y' ) then -- remember ID IDs(IDs.count + 1) := :new.id; end if; end after each row; -- main logic after statement is v_department swe_test_mutating.department%type; begin if IDs.count &gt; 0 then -- check if there is at least one other person -- for the same department -- which is also marked as HEAD for i in 1..IDs.count loop begin -- since we didn't store the department, we have to reread it from the table select t1.department into v_department from swe_test_mutating t1 join swe_test_mutating t2 on t1.department = t2.department -- must be same department where t1.id = IDs(i) and t1.id != t2.id -- must be different id and t1.is_head_of_department = 'Y' -- remembered ID is head and t2.is_head_of_department = 'Y' -- second personell is also head and rownum &lt;= 1 -- enough if we find one ; raise_application_error(-20000, &#039;There can only be one head of &#039;||v_department||&#039;!&#039;); exception when no_data_found then -- ok. Single head of department only. null; end; end loop; end if; end after statement; end; / -- remove the old trigger drop trigger swe_test_mutating_bri; </pre> <p>If we now do a multi-row insert we will not see the mutating table error. But instead the error message that we want to see (only 1 head allowed).</p> <p>&#8212; repeat the test!<br /> insert into swe_test_mutating<br /> (<br /> select 4, &#039;Mr. Sissorhands&#039;, &#039;LAB07&#039;, &#039;Y&#039; from dual union all<br /> select 5, &#039;Nagging Nanny&#039;, &#039;LAB07&#039;, &#039;N&#039; from dual union all<br /> select 6, &#039;Evil Clown&#039;, &#039;LAB07&#039;, &#039;Y&#039; from dual<br /> );</p> <p><code><span style="color:orange;">ORA-20000: There can only be one head of LAB07!</span><br /> ORA-06512: at "EVIL_LAB.SWE_TEST_MUTATING_COMPTRG", line 50<br /> ORA-04088: error during execution of trigger 'EVIL_LAB.SWE_TEST_MUTATING_COMPTRG'<br /> </code></p> <p>There are multiple optimisations for this code possible. We also could enfore the integrity rule by using a function based unique constraint. The point however was to show how code that demonstrates how to work around the mutating table error.</p> <p>Also note, that the usage of table triggers is not only to create error messages, like I did in the example with the &#8220;there can only be one&#8221; check. Often they are used to store aggregated (=redundant) data in some header tables. And many other scenarios are possible.</p> <h3>Addemdum &#8211; integrity not guaranteed</h3> <p>The trigger as I wrote it first does not guarantee the intended data integrity. It avoids successfully the mutating table error. However it does not ensure, that there will only be one labhead. </p> <p>Here is the scenario to show the problem. If we insert a single labhead from two separate sessions without commiting the first session. Then we end up with two active labheads. Which is not what our business rule says.</p> <pre class="brush: sql; light: true; title: ; notranslate"> -- In session A insert into swe_test_mutating ( select 4, 'Mr. Sissorhands', 'LAB07', 'Y' from dual union all select 5, 'Nagging Nanny', 'LAB07', 'N' from dual ); -- do not commit in session A yet! </pre> <p>Now add another head of lab in a different session.</p> <pre class="brush: sql; light: true; title: ; notranslate"> -- session B insert into evil_lab.swe_test_mutating (select 6, 'Evil Clown', 'LAB07', 'Y' from dual); commit; </pre> <p>After commit in session A we can check the results of the table</p> <pre class="brush: sql; light: true; title: ; notranslate"> -- session A commit; select * from swe_test_mutating; </pre> <pre>ID NAME DEPARTMENT IS_HEAD_OF_DEPARTMENT 6 Evil Clown LAB07 <span style="color:red;">Y</span> 4 Mr. Sissorhands LAB07 <span style="color:red;">Y</span> 5 Nagging Nanny LAB07 N</pre> <p>Thanks to <strong>Alex Nuijten</strong> who pointed out this issue in the comments.</p> <p>On a more abstract level: In a multi user environment, we need to make sure that all data that is needed for a decision is immutable until the transaction is finished. This also means we need to serialize the access to the same lab.</p> <p>The solution is not so simple. </p> <p>We can consider to lock all the personell, at least for the lab in question. But this will not prevent a rule violation via an insert. </p> <p>The proper way is to lock the parent row (the lab) itself. Now in my simplified datamodel we do not have this part. So I first need to extend the datamodel and then do the row locking. </p> <p>Here is the updated scenario</p> <p><em>Improved datamodel with two tables and a FK</em></p> <pre class="brush: sql; title: ; notranslate"> drop table swe_test_mutating; drop table swe_test_mutating_labs; drop table swe_test_mutating_personell; -- build lab enhancement create table swe_test_mutating_labs (name varchar2(254) not null primary key ,description varchar2(4000)); create table swe_test_mutating_personell (id number not null primary key ,name varchar2(1000) not null ,department varchar2(254) references swe_test_mutating_labs(name) ,is_head_of_department varchar2(1) constraint yn_ck check (is_head_of_department in ('Y','N')) ); -- We really should create an index on the FK to lessen the chance for a major deadlock scenario. -- However dealing with the dead is daily business for the evil lab. -- So I don't care at the moment. -- construct some labs insert into swe_test_mutating_labs (name) select 'LAB'||to_char(level,'fm00') from dual connect by level &lt;= 10; commit; </pre> <p>The compound trigger also needed to be changed. The most important thing is that we need to lock the lab in question, before the duplicate check is made.<br /> <em>Improved compound trigger</em></p> <pre class="brush: sql; highlight: [50,51,52,53,54,55]; title: ; notranslate"> -- compound trigger to make sure that there is only one head of each evil lab (department). create or replace trigger swe_test_mutating_personell_comptrg for insert or update on swe_test_mutating_personell compound trigger -- define collection type type ID_t is table of swe_test_mutating_personell.id%type index by binary_integer; -- define variable to hold a list of IDs IDs ID_t; before statement is begin -- no initialization needed for compound trigger null; end before statement; after each row is begin -- check if we have a new head of department if :new.is_head_of_department = 'Y' and (:old.is_head_of_department is null -- insert or :new.is_head_of_department != 'Y' ) then -- remember ID IDs(IDs.count + 1) := :new.id; end if; end after each row; -- main logic after statement is v_department swe_test_mutating_personell.department%type; begin if IDs.count &gt; 0 then -- check if there is at least one other person -- for the same department -- which is also marked as HEAD for i in 1..IDs.count loop begin -- since we didn't store the department, we have to reread it from the table select p1.department into v_department from swe_test_mutating_personell p1 where p1.id = IDs(i) and p1.is_head_of_department = 'Y' -- inserted ID is a labhead ; -- lock the department select d.name into v_department from swe_test_mutating_labs d where d.name = v_department for update of d.name; -- after we ensured exclusive access to this lab, -- we can test if there is another labhead select p2.department into v_department from swe_test_mutating_personell p2 where p2.department = v_department -- must be same department and p2.id != IDs(i) -- must be different person and p2.is_head_of_department = 'Y' -- second personell is also head and rownum &lt;= 1 -- enough if we find one ; -- found one! raise_application_error(-20000, &#039;There can only be one head of &#039;||v_department||&#039;!&#039;); exception when no_data_found then -- ok. Single head of department only. null; end; end loop; end if; end after statement; end; / </pre> <p>We can now repeat the test using the new tables.</p> <p>&#8212; In session A<br /> insert into swe_test_mutating_personell<br /> (<br /> select 4, &#039;Mr. Sissorhands&#039;, &#039;lab07&#039;, &#039;Y&#039; from dual union all<br /> select 5, &#039;Nagging Nanny&#039;, &#039;lab07&#039;, &#039;N&#039; from dual<br /> );</p> <p>Before we commit in session A, we do an insert in session B</p> <p>&#8212; session B<br /> insert into swe_test_mutating_personell<br /> (select 6, &#039;Evil Clown&#039;, &#039;lab07&#039;, &#039;Y&#039; from dual);</p> <p>This insert will now WAIT (it &quot;hangs&quot;) until the first session finishes its transaction. Essentially we serialized the access to each lab. Only one session at a time is allowed to do changes with regards who is the head.</p> <p>The result in session B depends whether session A does a COMMIT or a ROLLBACK.</p> <p><code>session A: commit;<br /> session B: <span style="color:orange;">ORA-20000: There can only be one head of lab07!</span></code></p> <p><code>session A: rollback;<br /> session B: 1 row inserted.</code></p> <p>But this again shows how much trouble we have to avoid and to consider if we decide to a) implement business rules inside database triggers and b) try to avoid the mutating table error.</p> <p><strong>Thank you mutating table error! We have come a good way since I first encountered you.</strong></p> svenweller http://svenweller.wordpress.com/?p=7888 Thu Oct 11 2018 11:05:53 GMT-0400 (EDT) ODC Appreciation Day 2018 - Evangelizando APEX en idioma Español desde el año 2012! - Archivos PDF Personalizados en APEX 18.1 http://feedproxy.google.com/~r/DescubriendoElMundoDeOracle/~3/NcynNyL14ew/odc-appreciation-day-2018-evangelizando.html <br /><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">En este día tan especial de agradecimientos y antes de empezar con este artículo tan interesante sobre el paquete PL/SQL llamado jrxml2pdf, quiero <span style="mso-spacerun: yes;">&nbsp;</span><span style="mso-spacerun: yes;">&nbsp;</span>decir a toda la comunidad fanática de Oracle APEX un muy grande GRACIAS! ¡Porque seguimos creciendo y seguimos evangelizando esta poderosa herramienta en cada rincón del mundo de habla Hispana! <o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Invito a todos los que se iniciaron con APEX tanto con mis cursos como con mis libros en español que compartan lo que han aprendido desde su experiencia así cada vez somos mas los que llevamos la camiseta de Application Express en español con gran orgullo!<o:p></o:p></span></div><br /><b style="mso-bidi-font-weight: normal;"><span lang="ES" style="font-size: 16.0pt; line-height: 107%; mso-ansi-language: ES; mso-bidi-font-size: 11.0pt;">Cómo Imprimir Informes Personalizados en formato PDF desde Código PL/SQL en Oracle Apex 18.1</span></b><br /><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Todos los que hemos trabajado en desarrollar aplicaciones ya sean para escritorio como web, se nos presenta un requerimiento determinante que es el de poder imprimir los reportes que se crean en la aplicación.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Es por ello que al trabajar con Oracle APEX siendo una herramienta sin costo embebida en la base de datos Oracle, siempre he investigado diferentes formas de poder imprimir los reportes y que sean sin costo.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Es por ello que en esta oportunidad les traigo una actualizacion que ya había publicado anteriormente sobre este paquete construido en puro PL/SQL llamado <b>jrxml2pdf</b> que nos permite mostrar reportes PDF listos para imprimir desde nuestra aplicación en <b>APEX 18.1</b>. <o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Como veremos a continuación para construir el reporte que queremos imprimir en formato PDF vamos a trabajar con una herramienta gráfica gratuita y Open Source llamada JasperSoft Studio.<o:p></o:p></span></div><div class="MsoNormal"><br /></div><div style="border-bottom: solid windowtext 1.0pt; border: none; mso-border-bottom-alt: solid windowtext .5pt; mso-element: para-border-div; padding: 0in 0in 1.0pt 0in;"><div class="MsoNormal" style="border: none; margin-bottom: .0001pt; margin-bottom: 0in; mso-border-bottom-alt: solid windowtext .5pt; mso-padding-alt: 0in 0in 1.0pt 0in; padding: 0in;"><b style="mso-bidi-font-weight: normal;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Paquete PL/SQL jrxml2pdf<o:p></o:p></span></b><br /><b style="mso-bidi-font-weight: normal;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></b></div></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-margin-top-alt: auto; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">El paquete PL/SQL jrxml2pdf es una solución escrita en código PL/SQL puro y que genera archivos PDF tomando la información desde la tabla jrxml-report-definition el cual nos permite ingresar el código XML del reporte creado y lo mejor de todo es que no se necesita ningún middleware </span><span lang="ES" style="font-family: &quot;wingdings&quot;; font-size: 12.0pt;"><span style="mso-char-type: symbol; mso-symbol-font-family: Wingdings;">J</span></span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-margin-top-alt: auto; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Podemos diseñar nuestros reportes gráficamente y muy sencillamente usando JasperSoft Studio, como lo veremos en un momento, y con unos simples pasos mostrar dichos reportes en nuestras aplicaciones en APEX.<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-margin-top-alt: auto; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Este paquete fue escrito por Andreas Weiden basándose en el paquete AS_PDF3 escrito por Anton Scheffer y el tipo de licencia que maneja es la GLP y MIT las cuales se encuentran descriptas en el paquete.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div style="margin-bottom: .0001pt; margin: 0in;"><u><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; mso-ansi-language: ES;">Descargar Paquete<o:p></o:p></span></u></div><div style="margin-bottom: .0001pt; margin: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Descargamos el Paquete <strong><span style="font-family: &quot;verdana&quot; , sans-serif; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-bidi-theme-font: minor-bidi;">jrxml2pdf </span></strong><strong><span style="font-family: &quot;verdana&quot; , sans-serif; font-weight: normal;">en nuestra PC desde el</span></strong><strong><span style="font-family: &quot;verdana&quot; , sans-serif; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-bidi-theme-font: minor-bidi;"> </span></strong><strong><span style="font-family: &quot;verdana&quot; , sans-serif; font-weight: normal;">siguiente</span></strong><strong><span style="font-family: &quot;verdana&quot; , sans-serif; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-bidi-theme-font: minor-bidi;"> </span></strong><strong><span style="font-family: &quot;verdana&quot; , sans-serif; font-weight: normal;">link:</span></strong><strong><span style="font-family: &quot;verdana&quot; , sans-serif; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-bidi-theme-font: minor-bidi;"> </span></strong><span class="MsoHyperlink">https://sourceforge.net/projects/pljrxml2pdf/</span><strong><span style="font-family: &quot;verdana&quot; , sans-serif; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-bidi-theme-font: minor-bidi;"><span style="mso-spacerun: yes;">&nbsp; </span></span></strong><strong><span style="font-family: &quot;verdana&quot; , sans-serif; font-weight: normal;">(en mi caso lo descargaré en el escritorio) y lo descomprimimos.<o:p></o:p></span></strong></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><u><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Instalar el paquete <strong><span style="font-family: &quot;verdana&quot; , sans-serif; font-weight: normal;">jrxml2pdf</span></strong><strong><span style="font-family: &quot;verdana&quot; , sans-serif; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-bidi-theme-font: minor-bidi;"> </span></strong><strong><span style="font-family: &quot;verdana&quot; , sans-serif; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-bidi-font-weight: normal; mso-bidi-theme-font: minor-bidi;"><o:p></o:p></span></strong></span></u></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Siguiendo el procedimiento de instalación del paquete necesitamos realizar los siguientes pasos:<o:p></o:p></span></div><ol start="1" style="margin-top: 0in;" type="1"><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Conceder permisos a UTL_FILE al usuario donde se instalará el paquete:<br /> </span><span class="crayon-e"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;">GRANT EXECUTE ON UTL_FILE </span></span><span class="crayon-st"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;">TO</span></span><span class="crayon-h"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;"> </span></span><span class="crayon-o"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;">&lt;</span></span><span class="crayon-e"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;">esquema donde vamos a instalar el paquete jrxml2pdf</span></span><span class="crayon-o"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;">&gt;</span></span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Abrimos una ventana de comandos CMD (si estamos en Windows) y nos ubicamos en el directorio de instalación del paquete: en mi caso </span><span lang="ES" style="font-family: &quot;wingdings&quot;; font-size: 12.0pt; line-height: 107%;"><span style="mso-char-type: symbol; mso-symbol-font-family: Wingdings;">à</span></span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"> </span><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;">C:\Users\Clarisa\Desktop\jrxml2pdf-release\install</span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"> y</span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"> abrimos el SQLPlus.<o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Ejecutamos el Script de Instalación: </span><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;">@install.sql<o:p></o:p></span></li></ol><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-gz11TPfdutc/W78kI7nQ-KI/AAAAAAAAMNU/uGXrEASbeaA7In43sgVzQzvJyLajSYasACLcBGAs/s1600/img01.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="648" data-original-width="1117" height="231" src="https://3.bp.blogspot.com/-gz11TPfdutc/W78kI7nQ-KI/AAAAAAAAMNU/uGXrEASbeaA7In43sgVzQzvJyLajSYasACLcBGAs/s400/img01.JPG" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Después de instalar el paquete podemos ver los objetos instalados desde el Explorador de Objetos del Taller de SQL de APEX o desde el Toad for Orqacle o el SQL Developer si usamos estas herramientas para trabajar con los objetos de la base de datos, si expandimos los Paquetes, vemos que se agregaron los que corresponden al paquete </span><span class="crayon-e"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">jrxml2pdf</span></span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">:<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"></span></div><a name='more'></a><br /><br /><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-kiG6Wdo-ixw/W78kRfMhxnI/AAAAAAAAMNY/5jlVXzbEINUxUkXTqOiKXS6rV7h_5dRqACLcBGAs/s1600/img02.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="516" data-original-width="280" height="400" src="https://2.bp.blogspot.com/-kiG6Wdo-ixw/W78kRfMhxnI/AAAAAAAAMNY/5jlVXzbEINUxUkXTqOiKXS6rV7h_5dRqACLcBGAs/s400/img02.JPG" width="216" /></a></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><br /><div style="border-bottom: solid windowtext 1.0pt; border: none; mso-border-bottom-alt: solid windowtext .5pt; mso-element: para-border-div; padding: 0in 0in 1.0pt 0in;"><div class="MsoNormal" style="border: none; margin-bottom: .0001pt; margin-bottom: 0in; mso-border-bottom-alt: solid windowtext .5pt; mso-padding-alt: 0in 0in 1.0pt 0in; padding: 0in;"><b style="mso-bidi-font-weight: normal;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Descargar e Instalar JasperSoft Studio<o:p></o:p></span></b></div></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">JasperSoft Studio es una poderosa herramienta de diseño visual para JasperReports, con esta herramienta gráfica podemos crear informes que cumplan con los más complejos requerimientos de información, además que es intuitivo, poderoso y muy fácil de usar.<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><u><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Descargar JasperSoft Studio<o:p></o:p></span></u></div><div align="left" class="Capitulos" style="text-align: left; text-indent: 0in;"><br /></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;">El link de descarga es:<o:p></o:p></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span class="MsoHyperlink"><span lang="ES" style="font-size: 12.0pt;"><a href="https://community.jaspersoft.com/project/jaspersoft-studio/releases">https://community.jaspersoft.com/project/jaspersoft-studio/releases</a></span></span><span lang="ES" style="font-size: 12.0pt;"><o:p></o:p></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><br /></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;">Seleccionamos el enlace que corresponde a nuestro sistema operativo, en mi caso es:<o:p></o:p></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><br /></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;">TIB_js-studiocomm_6.6.0_windows_x86_64.zip<o:p></o:p></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-9296DjOi1Po/W78kazsUlCI/AAAAAAAAMNc/MFIXSdnyAPwpLKiApi7wYlefPITgtpO6ACLcBGAs/s1600/img03.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="500" data-original-width="1048" height="190" src="https://4.bp.blogspot.com/-9296DjOi1Po/W78kazsUlCI/AAAAAAAAMNc/MFIXSdnyAPwpLKiApi7wYlefPITgtpO6ACLcBGAs/s400/img03.JPG" width="400" /></a></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span style="font-size: 12pt; text-indent: 0in;">Guardamos la carpeta comprimida en nuestra PC y luego la descomprimimos y creamos un acceso directo al escritorio del ejecutable del programa que se encuentra dentro de la carpeta Jaspersoftstudio/JaspersoftStudio.exe.</span></div><br /><div align="left" class="Capitulos" style="text-indent: 0in;"><span style="font-size: 12pt; text-indent: 0in;">Ahora podemos ejecutar el programa y nos mostrará la página de inicio.</span></div><br /><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-CCBDoAq3U7M/W78kgylPspI/AAAAAAAAMNg/WG53InxFmX0QUR14kSBlq7K--5xsK8ZOgCLcBGAs/s1600/img04.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="838" data-original-width="1600" height="208" src="https://2.bp.blogspot.com/-CCBDoAq3U7M/W78kgylPspI/AAAAAAAAMNg/WG53InxFmX0QUR14kSBlq7K--5xsK8ZOgCLcBGAs/s400/img04.JPG" width="400" /></a></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><br /></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Cerramos la ventana Welcome y visualizamos el Jaspersoft Studio.<o:p></o:p></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-47NlJR7vDHA/W78knwlq0AI/AAAAAAAAMNo/8xLYNutL36QDrqGz3tEO2XWA_wKUvyfAQCLcBGAs/s1600/img05.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="871" data-original-width="1600" height="217" src="https://4.bp.blogspot.com/-47NlJR7vDHA/W78knwlq0AI/AAAAAAAAMNo/8xLYNutL36QDrqGz3tEO2XWA_wKUvyfAQCLcBGAs/s400/img05.JPG" width="400" /></a></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><u><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Crear Conexión a la Base de Datos desde Jaspersoft Studio</span></u></div><br /><div align="left" class="Capitulos" style="text-indent: 0in;"><span style="font-family: calibri, sans-serif; font-size: 12pt; text-align: justify; text-indent: 0in;">Desde la Página de Inicio del Jaspersoft Studio, seleccionamos Data Adapter y con el botón derecho del mouse seleccionamos Create Data Adapter y se abre una ventana emergente. Seleccionamos la opción Database JDBC Connection.</span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><span style="font-family: &quot;calibri&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-cr-PPmDV9Lg/W78kuLawBZI/AAAAAAAAMNw/OW4zHoaAlu8imxh-td3MrlNUXmnNZ7wcwCLcBGAs/s1600/img06.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="510" data-original-width="568" height="358" src="https://4.bp.blogspot.com/-cr-PPmDV9Lg/W78kuLawBZI/AAAAAAAAMNw/OW4zHoaAlu8imxh-td3MrlNUXmnNZ7wcwCLcBGAs/s400/img06.JPG" width="400" /></a></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><span style="font-family: &quot;calibri&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></span></div><span style="font-size: 12pt; text-indent: 0in;">Hacemos clic en el botón Next &gt;</span><br /><br /><div align="left" class="Capitulos" style="text-indent: 0in;"><span style="font-size: 12.0pt; mso-ansi-language: EN-US;">Data Adapter: Database JDBC connection:<o:p></o:p></span></div><div align="left" class="Capitulos" style="margin-left: 0.5in; text-indent: -0.25in;"><!--[if !supportLists]--><span lang="ES" style="font-family: &quot;symbol&quot;; font-size: 12.0pt;">·<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span lang="ES" style="font-size: 12.0pt;">Name: devcmo<o:p></o:p></span></div><div align="left" class="Capitulos" style="margin-left: 0.5in; text-indent: -0.25in;"><!--[if !supportLists]--><span style="font-family: &quot;symbol&quot;; font-size: 12.0pt;">·<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span style="font-size: 12.0pt; mso-ansi-language: EN-US;">JDBC Driver: oracle.jdbc.driver.OracleDriver<o:p></o:p></span></div><div align="left" class="Capitulos" style="margin-left: 0.5in; text-indent: -0.25in;"><!--[if !supportLists]--><span style="font-family: &quot;symbol&quot;; font-size: 12.0pt;">·<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span style="font-size: 12.0pt; mso-ansi-language: EN-US;">JDBC URL: jdbc:oracle:thin:@localhost:1521:XE<o:p></o:p></span></div><div align="left" class="Capitulos" style="margin-left: 0.5in; text-indent: -0.25in;"><!--[if !supportLists]--><span lang="ES" style="font-family: &quot;symbol&quot;; font-size: 12.0pt;">·<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span lang="ES" style="font-size: 12.0pt;">Username: mi_username<o:p></o:p></span></div><div align="left" class="Capitulos" style="margin-left: 0.5in; text-indent: -0.25in;"><!--[if !supportLists]--><span lang="ES" style="font-family: &quot;symbol&quot;; font-size: 12.0pt;">·<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span lang="ES" style="font-size: 12.0pt;">Password: mi_password<o:p></o:p></span></div><div align="left" class="Capitulos"><br /></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"> </span></div><div align="left" class="Capitulos" style="text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;">Hacemos clic en el tab inferior “Driver Classpath”.<o:p></o:p></span></div><div align="left" class="Capitulos" style="text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-4Miz-OVHHsQ/W78k174FzNI/AAAAAAAAMN4/PONb2yVY2Jsr1lVglIG6txg2acCByVzQACLcBGAs/s1600/img07.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="567" height="400" src="https://4.bp.blogspot.com/-4Miz-OVHHsQ/W78k174FzNI/AAAAAAAAMN4/PONb2yVY2Jsr1lVglIG6txg2acCByVzQACLcBGAs/s400/img07.JPG" width="377" /></a></div><div align="left" class="Capitulos" style="text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><span style="font-size: 12pt; text-indent: 0in;">Hacemos clic en el botón Add.</span><br /><br /><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;">Y buscamos el driver jrxml2pdf.jar dentro de la carpeta donde hayamos descargado el paquete en mi caso lo descargué en el escritorio: </span><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt;">C:\Users\Clarisa\Desktop\jrxml2pdf-release\java_for_ireport\jrxml2pdf.jar </span><span lang="ES" style="font-size: 12.0pt;">y hacemos clic en el botón Open.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Además, necesitamos agregar el jar </span><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;">ojdbc6.jar</span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"> dentro del Classpath.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-bWCZ9hPbSiI/W78k8M3Q4VI/AAAAAAAAMOA/8MdRT5KkQQ8MxjpZjB7vTKAwJXoHsiyGQCLcBGAs/s1600/img08.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="602" data-original-width="578" height="400" src="https://4.bp.blogspot.com/-bWCZ9hPbSiI/W78k8M3Q4VI/AAAAAAAAMOA/8MdRT5KkQQ8MxjpZjB7vTKAwJXoHsiyGQCLcBGAs/s400/img08.JPG" width="383" /></a></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><span style="font-size: 12pt; text-indent: 0in;">Hacemos clic en el botón Finish.</span><br /><br /><div align="left" class="Capitulos" style="text-indent: 0in;"><span style="font-size: 12pt; text-indent: 0in;">Volvemos a abrir la conexión que la llamamos devcmo y probamos la conexión.</span></div><div align="left" class="Capitulos" style="text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-nNi2laMH4mQ/W78lEvq7IQI/AAAAAAAAMOI/HeiO9CROqm8Vln4IPBHiOSmuRZsoOq23gCLcBGAs/s1600/img09.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="599" data-original-width="582" height="400" src="https://2.bp.blogspot.com/-nNi2laMH4mQ/W78lEvq7IQI/AAAAAAAAMOI/HeiO9CROqm8Vln4IPBHiOSmuRZsoOq23gCLcBGAs/s400/img09.JPG" width="387" /></a></div><div align="left" class="Capitulos" style="text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="MsoNormal" style="border: none; margin-bottom: .0001pt; margin-bottom: 0in; mso-border-bottom-alt: solid windowtext .5pt; mso-padding-alt: 0in 0in 1.0pt 0in; padding: 0in;"><b style="mso-bidi-font-weight: normal;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Crear el Reporte en JasperSoft Studio<o:p></o:p></span></b></div><div style="border-bottom: solid windowtext 1.0pt; border: none; mso-border-bottom-alt: solid windowtext .5pt; mso-element: para-border-div; padding: 0in 0in 1.0pt 0in;"></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">En esta sección vamos a aprender a crear un reporte básico usando JasperSoft Studio, para que pueda ser invocado más adelante en nuestra aplicación en APEX.<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Nos conectamos a la base de datos con la conexión creada anteriormente, que la habíamos denominado <i>devcmo</i>.<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Hacemos clic en el menú File </span><span lang="ES" style="font-family: &quot;wingdings&quot;; font-size: 12.0pt;">à</span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"> New </span><span lang="ES" style="font-family: &quot;wingdings&quot;; font-size: 12.0pt;">à</span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"> Jasper Report y de esa forma se inicia el asistente. <o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .25in; margin-right: 0in; margin-top: 0in; mso-list: l1 level6 lfo1; text-align: justify; text-indent: -.25in;"><!--[if !supportLists]--><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">1.<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp; </span></span><!--[endif]--><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Report Templates<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Se abre el asistente y seleccionamos el template Coffee Landscape, y hacemos clic en el botón Next.<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .25in; margin-right: 0in; margin-top: 0in; mso-list: l1 level1 lfo1; text-align: justify; text-indent: -.25in;"><!--[if !supportLists]--><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">2.<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp; </span></span><!--[endif]--><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Report File<o:p></o:p></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"> </span></div><ul style="margin-top: 0in;" type="disc"><li class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo2;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Ingresar el directorio padre: MyReports<o:p></o:p></span></li><li class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo2;"><span lang="ES-AR" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">File name: listado-empleados.jrxml<o:p></o:p></span></li></ul><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-9R94j6j8d58/W78lN_DrNvI/AAAAAAAAMOU/SlWOckj6eZ8ZImoWw-HvkCMvu3jBHiDlQCLcBGAs/s1600/img10.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="582" data-original-width="744" height="312" src="https://3.bp.blogspot.com/-9R94j6j8d58/W78lN_DrNvI/AAAAAAAAMOU/SlWOckj6eZ8ZImoWw-HvkCMvu3jBHiDlQCLcBGAs/s400/img10.JPG" width="400" /></a></div><div><span style="font-family: &quot;verdana&quot; , sans-serif;"><br /></span></div><li class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo2;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Hacemos clic en el botón Next &gt;<o:p></o:p></span></li><br /><ul style="margin-top: 0in;" type="disc"> </ul><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt; text-indent: -0.25in;">3.<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp; </span></span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt; text-indent: -0.25in;">Data Source</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><ul style="margin-top: 0in;" type="disc"><li class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo2;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Data Adapter: devcmo<o:p></o:p></span></li></ul><ul style="margin-top: 0in;" type="disc"><li class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo2;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Hacemos doble clic sobre la tabla EMP del esquema DEVCMO para crear la consulta SQL. (Destildamos los campos HIREDATE y DEPTNO)<o:p></o:p></span></li></ul><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-oCx73eavkcE/W78lX7HtfoI/AAAAAAAAMOY/sYHCjTyGLHceRC7pWSw2L0lQk0bHwrM7QCLcBGAs/s1600/img11.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="585" data-original-width="747" height="312" src="https://4.bp.blogspot.com/-oCx73eavkcE/W78lX7HtfoI/AAAAAAAAMOY/sYHCjTyGLHceRC7pWSw2L0lQk0bHwrM7QCLcBGAs/s400/img11.JPG" width="400" /></a></div><div><span style="font-family: &quot;verdana&quot; , sans-serif;"><br /></span></div><span style="font-family: verdana, sans-serif; font-size: 12pt; text-align: justify;">Hacemos clic en el botón Next &gt;</span><br /><br /><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .25in; margin-right: 0in; margin-top: 0in; mso-list: l0 level1 lfo1; text-align: justify; text-indent: -.25in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">4.<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp; </span></span><!--[endif]--><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Fields: Mostrar todos los campos de la Tabla<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .25in; margin-right: 0in; margin-top: 0in; mso-list: l0 level1 lfo1; text-align: justify; text-indent: -.25in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-N6bCINmTjMc/W78liblGT2I/AAAAAAAAMOg/wm9nhtEZwi8dzeT5ve_rBHp2NhDt_OTJACLcBGAs/s1600/img12.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="648" data-original-width="746" height="346" src="https://4.bp.blogspot.com/-N6bCINmTjMc/W78liblGT2I/AAAAAAAAMOg/wm9nhtEZwi8dzeT5ve_rBHp2NhDt_OTJACLcBGAs/s400/img12.JPG" width="400" /></a></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .25in; margin-right: 0in; margin-top: 0in; mso-list: l0 level1 lfo1; text-align: justify; text-indent: -.25in;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Hacemos clic en el botón Next &gt;<o:p></o:p></span></div><br /><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt; text-indent: -0.25in;">5.<span style="font-family: &quot;times new roman&quot;; font-size: 7pt; font-stretch: normal; line-height: normal;">&nbsp;&nbsp; </span></span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt; text-indent: -0.25in;">Agrupar por (Group By…)</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">No seleccionamos nada.<o:p></o:p></span></div><br /><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-oLvfu4LvxdQ/W78lpVqjEwI/AAAAAAAAMOo/81Xzg1FbyUASiV9KJPv6JjHe8AQf2Pm8gCLcBGAs/s1600/img13.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="643" data-original-width="795" height="322" src="https://2.bp.blogspot.com/-oLvfu4LvxdQ/W78lpVqjEwI/AAAAAAAAMOo/81Xzg1FbyUASiV9KJPv6JjHe8AQf2Pm8gCLcBGAs/s400/img13.JPG" width="400" /></a></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Hacemos clic en el botón Next &gt;<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-kbi5DpasOWk/W78lweCJc4I/AAAAAAAAMOs/bPc6E28FXagxOU4-PthXPSuvYpJEjAjRgCLcBGAs/s1600/img14.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="647" data-original-width="793" height="326" src="https://3.bp.blogspot.com/-kbi5DpasOWk/W78lweCJc4I/AAAAAAAAMOs/bPc6E28FXagxOU4-PthXPSuvYpJEjAjRgCLcBGAs/s400/img14.JPG" width="400" /></a></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Finalmente hacemos clic en el botón Finish.<o:p></o:p></span></div><br /><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in;"><span style="font-family: verdana, sans-serif; font-size: 12pt; text-align: justify;">Se abre el IDE del Jaspersoft Studio donde visualizamos el reporte y podemos editar cada sección (band) del mismo y colocar las imágenes que deseamos en nuestro reporte.</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt;">No es objetivo de este artículo aprender a editar un reporte en Jaspersoft Studio.</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Para información sobre esta herramienta por favor visitar la comunidad de JasperSoft Studio.<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Simplemente para este demo hemos ingresado nuevas imágenes desde el workspace de Jaspersoft Studio en:<o:p></o:p></span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt;">C:\Users\Clarisa\JaspersoftWorkspace\MyReports</span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"> y cambiamos los títulos.<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-HYxwSTIeO8g/W78l3SrRK5I/AAAAAAAAMO8/4xDf1vqzJ20f3j84MBmf5lzm3jVkyMIcQCEwYBhgL/s1600/img15.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="341" data-original-width="897" height="151" src="https://3.bp.blogspot.com/-HYxwSTIeO8g/W78l3SrRK5I/AAAAAAAAMO8/4xDf1vqzJ20f3j84MBmf5lzm3jVkyMIcQCEwYBhgL/s400/img15.JPG" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Para pre-visualizar el reporte hacemos clic en el tab <i>Preview</i> que se encuentra en la parte inferior del panel central del diseñador. Ejecutamos el reporte haciendo clic en la flechita verde de play.<o:p></o:p></span></div><br /><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span style="font-family: verdana, sans-serif; font-size: 12pt;">De esta forma podemos visualizar el reporte recién creado en Jaspersoft Studio:</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"></div><div style="text-align: center;">&nbsp;<a href="https://3.bp.blogspot.com/-ZZNMbLX5Flc/W78mMU3f92I/AAAAAAAAMPE/mbCNbKhbZkIC7Nw26LG8Kg1tBitNaVOvQCEwYBhgL/s1600/img16.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="699" data-original-width="1144" height="243" src="https://3.bp.blogspot.com/-ZZNMbLX5Flc/W78mMU3f92I/AAAAAAAAMPE/mbCNbKhbZkIC7Nw26LG8Kg1tBitNaVOvQCEwYBhgL/s400/img16.JPG" width="400" /></a></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div class="MsoNormal" style="border: none; margin-bottom: .0001pt; margin-bottom: 0in; mso-border-bottom-alt: solid windowtext .5pt; mso-padding-alt: 0in 0in 1.0pt 0in; padding: 0in;"><b style="mso-bidi-font-weight: normal;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Expresiones no soportadas en el paquete PL/SQL<o:p></o:p></span></b></div><div style="border-bottom: solid windowtext 1.0pt; border: none; mso-border-bottom-alt: solid windowtext .5pt; mso-element: para-border-div; padding: 0in 0in 1.0pt 0in;"></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">No todas las expresiones usadas en el reporte que hemos diseñado en JasperSoft Studio están soportadas por el paquete jrxml2pdf,<b> </b>es por eso que es muy importante revisar la documentación del paquete para evitar errores en la visualización del reporte cuando lo mostremos desde la aplicación en APEX.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">En el panel de la izquierda del IDE de JasperSoft referente al “Outline” expandimos <i>Styles</i> y luego expandimos <i>Row</i>, esta expresión es la que coloca el color de fondo en las filas de la tabla en forma alternada y que es parte del template que seleccionamos como base para crear nuestro reporte.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;">$V{REPORT_COUNT}%2 == 0<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-YxaUpMDzZr8/W78mz62MLuI/AAAAAAAAMPM/3LQqbADy9d8zX4skpZ1IHbeR6SqnZFKlwCLcBGAs/s1600/parche.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="580" data-original-width="1227" height="188" src="https://4.bp.blogspot.com/-YxaUpMDzZr8/W78mz62MLuI/AAAAAAAAMPM/3LQqbADy9d8zX4skpZ1IHbeR6SqnZFKlwCLcBGAs/s400/parche.JPG" width="400" /></a></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt; line-height: 107%;"><br /></span></div><span style="font-family: verdana, sans-serif; font-size: 12pt; text-align: justify;">Este tipo de expresión no está soportada en el paquete jrxml2pdf, para ello vamos a eliminar la expresión y utilizar la herramienta de apariencia de la fila para darle color a todas las filas.</span><br /><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Para ver expresiones equivalentes que sí estan soportadas por el paquete, es importante revisar la documentación del paquete en el mismo sitio de su descarga.</span></div><br /><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Una vez modificado el reporte, necesitamos compilar el mismo para que se genere el archivo de compilación, para ello hacemos clic en el icono&nbsp;<b>Build All</b>.</span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-5VwXYbNgzpg/W78ngMZwFqI/AAAAAAAAMPg/b0G-bhqgx78NoYggpsNIYp76vDhJhjsQQCLcBGAs/s1600/img17.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="261" data-original-width="485" height="215" src="https://1.bp.blogspot.com/-5VwXYbNgzpg/W78ngMZwFqI/AAAAAAAAMPg/b0G-bhqgx78NoYggpsNIYp76vDhJhjsQQCLcBGAs/s400/img17.JPG" width="400" /></a></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span style="font-family: verdana, sans-serif; font-size: 12pt;">Podemos observar que todas las filas tienen un color de fondo, según los estilos aplicados.</span></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-5k2HRhQ_31I/W78nMImHrrI/AAAAAAAAMPY/b1InWNDytiUTHRs-u8dwcIXMbEKsXMYyQCLcBGAs/s1600/parche2.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="677" data-original-width="1105" height="245" src="https://2.bp.blogspot.com/-5k2HRhQ_31I/W78nMImHrrI/AAAAAAAAMPY/b1InWNDytiUTHRs-u8dwcIXMbEKsXMYyQCLcBGAs/s400/parche2.JPG" width="400" /></a></div><div class="Capitulos" style="text-align: justify; text-indent: 0in;"><span lang="ES" style="font-size: 12.0pt;"><br /></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Podemos visualizar los dos archivos dentro del directorio MyReports: <o:p></o:p></span></div><br /><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 12.0pt;">C:\Users\Clarisa\JaspersoftWorkspace\MyReports<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><i><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">listado-empleados.jrxml y listado-empleados.jasper<o:p></o:p></span></i></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;">Nosotros vamos a usar el XML generado en el archivo “<i>listado-empleados.jrxml” </i>para que sea importado en la aplicación en APEX.<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div style="border-bottom: solid windowtext 1.0pt; border: none; mso-border-bottom-alt: solid windowtext .5pt; mso-element: para-border-div; padding: 0in 0in 1.0pt 0in;"><div class="MsoNormal" style="border: none; margin-bottom: .0001pt; margin-bottom: 0in; mso-border-bottom-alt: solid windowtext .5pt; mso-padding-alt: 0in 0in 1.0pt 0in; padding: 0in; text-align: justify;"><b><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Importar Imágenes en la tabla JRXML_REPORT_IMAGES<o:p></o:p></span></b></div></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Todas las imágenes que usemos en los reportes que creamos con JasperSoft Studio necesitamos ingresarlas en la tabla correspondiente de almacenamiento de imágenes que viene con el paquete jrxml2pdf.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Ingresamos al SQL Developer&nbsp; e insertamos un nuevo registro por cada imagen usada.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-UaxIwo0-enM/W78nq7cXf0I/AAAAAAAAMPk/Wx-ysXHbJYcDK_oEw4dBhZgSCvhYMyQdQCLcBGAs/s1600/img18.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="867" height="276" src="https://3.bp.blogspot.com/-UaxIwo0-enM/W78nq7cXf0I/AAAAAAAAMPk/Wx-ysXHbJYcDK_oEw4dBhZgSCvhYMyQdQCLcBGAs/s400/img18.JPG" width="400" /></a></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span style="font-family: verdana, sans-serif; font-size: 12pt;">Tener en cuenta que necesitamos cargar las imágenes como BLOB y con el mismo nombre que tienen en las imágenes que usamos en JasperSoft Studio.</span></div><div class="MsoNormal"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">No olvidemos de hacer el commit de los registros cargados.<o:p></o:p></span></div><div style="border-bottom: solid windowtext 1.0pt; border: none; mso-border-bottom-alt: solid windowtext .5pt; mso-element: para-border-div; padding: 0in 0in 1.0pt 0in;"><div class="MsoNormal" style="border: none; margin-bottom: .0001pt; margin-bottom: 0in; mso-border-bottom-alt: solid windowtext .5pt; mso-padding-alt: 0in 0in 1.0pt 0in; padding: 0in;"><b><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Importar el Reporte a nuestra base de datos<o:p></o:p></span></b></div></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Vamos a cargar el reporte creado en JaspersSoft a nuestra base de datos:</span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt;"><br /></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt;">1. Desde el Reporte creado (listado-empleados.jrxml) verificamos que al presionar el tab Preview se vea bien el PDF, el cual muestra todo el listado de Empleados.</span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt; text-align: justify;"><span lang="ES" style="font-size: 12pt; line-height: 107%;"><br /></span></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt; text-align: justify;"><span lang="ES" style="font-size: 12pt; line-height: 107%;">2. Hacemos&nbsp;</span></span><span style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt; text-align: justify;">clic en el tab Source (que está al costado izquierdo del tab Preview) y copiamos todo el código XML en memoria con </span><i style="font-family: Verdana, sans-serif; font-size: 12pt; text-align: justify;">Ctrl + a</i></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-tdQzrzD3j8w/W78n5g9rHVI/AAAAAAAAMPs/EYk3a8QvqvcLkx6H0vg7YmvslVIQDnrqACLcBGAs/s1600/img19.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="704" data-original-width="1140" height="246" src="https://2.bp.blogspot.com/-tdQzrzD3j8w/W78n5g9rHVI/AAAAAAAAMPs/EYk3a8QvqvcLkx6H0vg7YmvslVIQDnrqACLcBGAs/s400/img19.JPG" width="400" /></a></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span style="font-family: verdana, sans-serif; font-size: 12pt;">Abrimos el SQL Developer, posteriormente seleccionamos la tabla JRXML_REPORT_DEFINITIONS, y luego hacemos clic en la ficha Data para ingresar un nuevo registro:</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"> </span></div><ol start="1" style="margin-top: 0in;" type="1"><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Hacemos clic en el icono Insertar Fila </span><span style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter"/> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0"/> <v:f eqn="sum @0 1 0"/> <v:f eqn="sum 0 0 @1"/> <v:f eqn="prod @2 1 2"/> <v:f eqn="prod @3 21600 pixelWidth"/> <v:f eqn="prod @3 21600 pixelHeight"/> <v:f eqn="sum @0 0 1"/> <v:f eqn="prod @6 1 2"/> <v:f eqn="prod @7 21600 pixelWidth"/> <v:f eqn="sum @8 21600 0"/> <v:f eqn="prod @7 21600 pixelHeight"/> <v:f eqn="sum @10 21600 0"/> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/> <o:lock v:ext="edit" aspectratio="t"/> </v:shapetype><v:shape id="Picture_x0020_11" o:spid="_x0000_i1026" type="#_x0000_t75" alt="http://pretius.com/wp-content/uploads/2015/07/image2015-7-22-14-0-381.png" style='width:15pt;height:15.75pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:/Users/cmorf/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png" o:title="image2015-7-22-14-0-381"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--></span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><o:p></o:p></span></li><ol start="1" style="margin-top: 0in;" type="a"><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level2 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">JRD_ID: añadimos un nuevo número según la secuencia que exista.<o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level2 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">JRD_NAME: Colocamos aquí el nombre del reporte (es muy importante esta columna y además debemos tener en cuenta de no colocar caracteres especiales ni espacios) en mi caso lo llamaré <b>Empleados</b>.<o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level2 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">JRD_DESCRIPTION: podemos dejar este campo en blanco o colocar una descripción del reporte.<o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level2 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">JRD_XML: aquí es donde debemos colocar todo el código XML que habíamos copiado del reporte en JasperSoft Studio.<o:p></o:p></span></li></ol><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Hacemos clic en el icono Commit </span><span style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><!--[if gte vml 1]><v:shape id="Picture_x0020_12" o:spid="_x0000_i1025" type="#_x0000_t75" alt="http://pretius.com/wp-content/uploads/2015/07/image2015-7-22-14-0-551.png" style='width:13.5pt;height:15pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:/Users/cmorf/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png" o:title="image2015-7-22-14-0-551"/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--></span><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">&nbsp;para que el registro sea creado.<o:p></o:p></span></li></ol><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-kAihIq8kDnE/W78oCIdx9dI/AAAAAAAAMP0/kXF9FEWAvHgja4iIFh_WbCk08SH1aZ2JACLcBGAs/s1600/img20.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="857" data-original-width="1496" height="228" src="https://1.bp.blogspot.com/-kAihIq8kDnE/W78oCIdx9dI/AAAAAAAAMP0/kXF9FEWAvHgja4iIFh_WbCk08SH1aZ2JACLcBGAs/s400/img20.JPG" width="400" /></a></div><div><span style="font-family: &quot;verdana&quot; , sans-serif;"><br /></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><b><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Abrir Oracle APEX 18.1</span></b></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Ya tenemos en una tabla todo el código XML del reporte que creamos en JasperSoft Studio.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Ahora vamos a crear una aplicación en APEX y una página con el reporte de Empleados y un botón que diga Imprimir Reporte.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">La consulta de origen del Informe Interactivo es:<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">select EMPNO as “ID”,<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp;&nbsp;&nbsp; ENAME as “NOMBRE”,<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp;&nbsp;&nbsp; JOB as “JOB”,<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp;&nbsp;&nbsp; MGR as “MANAGER”,<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp;&nbsp;&nbsp; SAL as “SALARY”,<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp;&nbsp;&nbsp; COMM as “COMMISSION” <o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp;</span><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">from EMP EMP</span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-WqQN23HTous/W78oKmkyehI/AAAAAAAAMP8/kr2SRwEnOlkzD32kV2MYW_sJvOKkiiLCwCLcBGAs/s1600/img21.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="635" data-original-width="1600" height="158" src="https://3.bp.blogspot.com/-WqQN23HTous/W78oKmkyehI/AAAAAAAAMP8/kr2SRwEnOlkzD32kV2MYW_sJvOKkiiLCwCLcBGAs/s400/img21.JPG" width="400" /></a></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;"><br /></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"><br /></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><u><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Crear Proceso para Impresión del Reporte<o:p></o:p></span></u></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Desde el Diseñador de Página hacemos clic en la ficha Procesamiento del panel de la izquierda y creamos un nuevo proceso:<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><ol start="1" style="margin-top: 0in;" type="1"><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">En la sección Identificación<o:p></o:p></span></li><ol start="1" style="margin-top: 0in;" type="a"><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level2 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Nombre: Imprimir Reporte<o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level2 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Tipo: Código PL/SQL<o:p></o:p></span></li></ol><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">En la sección Origen<br /> Código PL/SQL:<o:p></o:p></span></li></ol><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">DECLARE<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp; vcName&nbsp; VARCHAR2(200);<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp; lParams SCHEMA.PK_JRXML2PDF_REPGEN.TPARAMLIST;<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp; </span><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">bl BLOB;<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">BEGIN<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp; </span><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">vcName := 'nombre-reporte'; <o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp; bl := SCHEMA.PK_JRXML2PDF_REPGEN.FK_RUN(i_vcName=&gt;vcName);<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp; SCHEMA.PK_JRXML2PDF_REPGEN.PR_SHOW_REPORT(bl);<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">&nbsp; APEX_APPLICATION.STOP_APEX_ENGINE;<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;"><span lang="ES" style="font-family: &quot;courier new&quot;; font-size: 10.0pt; line-height: 107%;">END;<o:p></o:p></span></div><ol start="3" style="margin-top: 0in;" type="1"><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">En la sección Condición<o:p></o:p></span></li><ol start="1" style="margin-top: 0in;" type="a"><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level2 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Si Se Hace Clic en el Botón: IMPRIMIR<o:p></o:p></span></li></ol><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Guardamos todos los cambios hacienda clic en el botón Guardar<o:p></o:p></span></li></ol><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Reemplazamos ‘nombre_reporte’ por el nombre que pusimos a nuestro reporte, en este caso Empleados.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Reemplazamos SCHEMA por el nombre de nuestro esquema.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12pt; text-align: justify;">Ejecutamos la Página y podemos ver que el reporte se visualiza correctamente en nuestra aplicación en APEX.</span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"> </span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><u><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Nota:</span></u><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"> puede haber problemas con algunos tipos de formato imagen como el jpg.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-7oc8qJ8RArY/W78oVIQ7lnI/AAAAAAAAMQE/o7XPJSYUuAEc0UM2KMHTKh8Bnl1WZ5fngCLcBGAs/s1600/img22.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="872" data-original-width="1600" height="217" src="https://1.bp.blogspot.com/-7oc8qJ8RArY/W78oVIQ7lnI/AAAAAAAAMQE/o7XPJSYUuAEc0UM2KMHTKh8Bnl1WZ5fngCLcBGAs/s400/img22.JPG" width="400" /></a></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><br /></div><div style="border-bottom: solid windowtext 1.0pt; border: none; mso-border-bottom-alt: solid windowtext .5pt; mso-element: para-border-div; padding: 0in 0in 1.0pt 0in;"><div class="MsoNormal" style="border: none; margin-bottom: .0001pt; margin-bottom: 0in; mso-border-bottom-alt: solid windowtext .5pt; mso-padding-alt: 0in 0in 1.0pt 0in; padding: 0in;"><b><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Resumen<o:p></o:p></span></b></div></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Como hemos visto a lo largo de todo este artículo, podemos crear reportes PDF listos para imprimir y sin costo asociado.<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Hemos aprendido a:<o:p></o:p></span></div><div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;"><br /></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; text-align: justify;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt;"> </span></div><ul style="margin-top: 0in;" type="disc"><a href="https://www.blogger.com/blogger.g?blogID=1315583943401206186" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="https://www.blogger.com/blogger.g?blogID=1315583943401206186" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Descargar e instalar el JasperSoft Studio<o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Crear un reporte básico en JasperSoft Studio<o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Descargar e Instalar el paquete PL/SQL jrxml2pdf<o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Implementar el paquete en nuestra aplicación en APEX 18.1<o:p></o:p></span></li><li class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-list: l0 level1 lfo1;"><span lang="ES" style="font-family: &quot;verdana&quot; , sans-serif; font-size: 12.0pt; line-height: 107%;">Conocer algunas limitaciones del paquete</span></li></ul><img src="http://feeds.feedburner.com/~r/DescubriendoElMundoDeOracle/~4/NcynNyL14ew" height="1" width="1" alt=""/> Clarisa J. Maman Orfali tag:blogger.com,1999:blog-1315583943401206186.post-3673939044054358544 Thu Oct 11 2018 06:40:00 GMT-0400 (EDT) Custom Syntax Highlighting in SQL Developer https://jeffkemponoracle.com/2018/10/custom-syntax-highlighting-in-sql-developer/ <p>A few years ago I raised an <a href="https://apex.oracle.com/pls/apex/f?p=43135:7:::NO:RP,7:P7_ID:44501">enhancement request for SQL Developer</a> to add custom highlighting, specifically to &#8220;grey out&#8221; all the calls to logger throughout my code. <a href="https://jeffkemponoracle.com/2016/10/24/enhancement-request-for-sql-developer-for-users-of-logger/">I blogged about this here.</a></p> <p><a href="https://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html">Oracle SQL Developer 18.3</a> adds this feature with <strong>PL/SQL Custom Syntax Rules</strong> &#8211; and the best thing is, these rules are enabled by default so you don&#8217;t have to do anything. Any calls to <strong>logger</strong>, <strong>dbms_output</strong> and <strong>apex_debug</strong> will be greyed out.</p> <p><img class="size-full wp-image-5150 alignnone" src="https://jeffkemponoracle.com/wp-content/uploads/2018/10/syntax-highlighting.png" alt="" width="552" height="475" srcset="https://jeffkemponoracle.com/wp-content/uploads/2018/10/syntax-highlighting.png 552w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/syntax-highlighting-300x258.png 300w" sizes="(max-width: 552px) 100vw, 552px" /></p> <p>You can customise the colour for this rule in Tools -&gt; Preferences -&gt; Code Editor -&gt; PL/SQL Syntax Colors &#8211; the one for logger etc. is called &#8220;PlSqlCustom2&#8221;:</p> <p><img class="alignnone size-full wp-image-5151" src="https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_syntax_colors.png" alt="" width="934" height="642" srcset="https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_syntax_colors.png 934w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_syntax_colors-300x206.png 300w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_syntax_colors-768x528.png 768w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_syntax_colors-750x516.png 750w" sizes="(max-width: 934px) 100vw, 934px" /></p> <p>You can view (and edit, if you want) the rule in PL/SQL Custom Syntax Rules:</p> <p><img class="alignnone size-large wp-image-5153" src="https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_custom_syntax_rules-1-1024x587.png" alt="" width="1024" height="587" srcset="https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_custom_syntax_rules-1-1024x587.png 1024w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_custom_syntax_rules-1-300x172.png 300w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_custom_syntax_rules-1-768x441.png 768w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_custom_syntax_rules-1-750x430.png 750w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/plsql_custom_syntax_rules-1.png 1304w" sizes="(max-width: 1024px) 100vw, 1024px" /></p> <p>I&#8217;m not very familiar with the syntax but you can add additional libraries by adding more lines like this to the rule:</p> <pre class="brush: plain; gutter: false; title: ; notranslate"> | ?grandChild = 'MYCUSTOMLOGGER' </pre> <p>The only thing missing is that it doesn&#8217;t pick up the standard logger variable declarations (scope and params). I haven&#8217;t worked out how to include these in the rule yet.</p> Jeffrey Kemp https://jeffkemponoracle.com/?p=5149 Wed Oct 10 2018 21:27:27 GMT-0400 (EDT) Commit your docker container! http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/GHIi5mnujNk/commit-your-docker-container.html <h2>Safe your work </h2>I would somehow like to persist the actual result of this approach and the easiest way to do this is to create a new image based on my actual container. I will use the <b>docker commit </b>comand to do this.<br /><br />I connect to the docker with putty, identify the <b>Container Id&nbsp; </b>by using the command <b>docker ps</b> and create a new image by issuing the command <b>docker commit d8ff275aeb95 martinm/oracle/database:18.3.0-ee</b><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-Q6nQw8i0y2c/W74qz9mH5II/AAAAAAAAJVc/h_PImwFFPBEReByIopeJvvKcReXLlOFTACLcBGAs/s1600/commit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="279" data-original-width="1289" height="86" src="https://3.bp.blogspot.com/-Q6nQw8i0y2c/W74qz9mH5II/AAAAAAAAJVc/h_PImwFFPBEReByIopeJvvKcReXLlOFTACLcBGAs/s400/commit.png" width="400" /></a></div><b><br /></b>This will stop the docker container for a while, take some time<br /><br /><div class="separator" style="clear: both; text-align: center;">&nbsp;<a href="https://3.bp.blogspot.com/-iSaYJBOTyzs/W74oSkfXPgI/AAAAAAAAJVU/N4DoWpN_vBcmn1pxxpco6LMHzR6DCblxgCEwYBhgL/s1600/stopped.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="83" data-original-width="810" height="40" src="https://3.bp.blogspot.com/-iSaYJBOTyzs/W74oSkfXPgI/AAAAAAAAJVU/N4DoWpN_vBcmn1pxxpco6LMHzR6DCblxgCEwYBhgL/s400/stopped.png" width="400" /></a></div><br />and create the image<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-3yJJ4SllcjE/W747m6SrLlI/AAAAAAAAJVo/3bBuPZTDnF46GSsH0ki4HfM8Nl3L_MYkwCLcBGAs/s1600/Image.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="93" data-original-width="803" height="46" src="https://3.bp.blogspot.com/-3yJJ4SllcjE/W747m6SrLlI/AAAAAAAAJVo/3bBuPZTDnF46GSsH0ki4HfM8Nl3L_MYkwCLcBGAs/s400/Image.png" width="400" /></a></div><br /><h3>Hyperbackup</h3>Did I already mention, that I also backup my <b>oradata</b> folder?<br /><b></b> <b></b><img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/GHIi5mnujNk" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-1694708547687533197 Wed Oct 10 2018 13:51:00 GMT-0400 (EDT) ODC Appreciation Day : APEX Workspace Activity Logs http://www.grassroots-oracle.com/2018/10/odc-appreciation-day-apex-workspace-activity-log.html Everything gets a special day these days, and thanks to Tim Hall's encouragement, you can enjoy a vibrant display of appreciation for what the Oracle Developer Community embraces about the technology they use daily.<br /><br />The first year I talked about <a href="http://www.grassroots-oracle.com/2016/10/otn-appreciation-day-apex-dynamic-actions-jquery-selector.html" target="_blank">Dynamic Actions</a>.<br />Last year I missed the boat - too busy preparing for some holidays.<br />This year I'd like to lay down my love for a supply of data every APEX developer has access to:&nbsp;<b>apex_workspace_activity_log</b>.<br /><br />Yup, I'm talking about a log table.<br /><br />It's enabled in your Oracle APEX applications by default, and inserts a record in a log table every time APEX renders a page, or a dynamic action interacting with the database thanks to a PL/SQL or Refresh action.<br /><br />Every time a user opens a page, you know when, who, what, why, and <i>how long it took to generate</i>.<br /><pre class="brush:sql">select apex_user as who<br /> ,application_id||':'||page_id as what<br /> ,view_date as when<br /> ,elapsed_time as how_long<br /> ,page_view_type as why<br /> ,request_value as more_why<br />from apex_workspace_activity_log<br />where application_id &gt;= 4000<br />and apex_user != 'nobody'</pre><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-vUTV44vAEmM/W7vqRJBdtGI/AAAAAAAAT_g/16zfGSPB_BwiqU10D7L6n1mHy5gQEbbVgCLcBGAs/s1600/log.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="343" data-original-width="587" src="https://4.bp.blogspot.com/-vUTV44vAEmM/W7vqRJBdtGI/AAAAAAAAT_g/16zfGSPB_BwiqU10D7L6n1mHy5gQEbbVgCLcBGAs/s1600/log.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">How APEX Builder dashboard knows who's been the busiest developer</td></tr></tbody></table><div class="separator" style="clear: both; text-align: center;"></div><br />We can combine this information to produce a wealth of information. Oracle provides some out of the box under Administration -&gt; Monitor Activity.<br /><br />I think the first report worth noting is <i>By Weighted Page Performance</i>.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-Hy-SDZ8MQjY/W7tslDyI3iI/AAAAAAAAT-o/xMweH023vFMPSHbI3QZQbrfwO6cA2nUNQCLcBGAs/s1600/weighted.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="234" data-original-width="434" src="https://1.bp.blogspot.com/-Hy-SDZ8MQjY/W7tslDyI3iI/AAAAAAAAT-o/xMweH023vFMPSHbI3QZQbrfwO6cA2nUNQCLcBGAs/s1600/weighted.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Packaged Reports</td></tr></tbody></table><br />This report multiplies how many times certain pages were loaded by how long it took to load, so ordering gives weight to those pages consuming overall time. Here I've also highlighted the Median column, since that too can be an indicator. A higher average that maintains a low median can indicate outliers, while a raised median really should be looked at.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-e4KqswsCfqM/W7tujmVXIpI/AAAAAAAAT-0/TP2jPywlRKMq9KYRJNZ2FDy6ddmZhCcgQCLcBGAs/s1600/weighted_report.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="166" data-original-width="813" height="129" src="https://4.bp.blogspot.com/-e4KqswsCfqM/W7tujmVXIpI/AAAAAAAAT-0/TP2jPywlRKMq9KYRJNZ2FDy6ddmZhCcgQCLcBGAs/s640/weighted_report.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Weighted Page Performance</td></tr></tbody></table><br />Fundamentally, we're asking - should I choose to tune a 3 second page that runs once a day, or tune a 1 second page that runs thousands of times a day?<br /><br />I've taken this information to produce a range of drillable reports, starting with a beautiful OracleJET chart. This starts by day - guess where the weekend is?<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-3wJ9RdVD450/W7twMF1Bp8I/AAAAAAAAT_A/WK1cWcuap4IpmZLKefErekawYiq8iwHmACLcBGAs/s1600/apex_pulse.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="231" data-original-width="1186" height="124" src="https://2.bp.blogspot.com/-3wJ9RdVD450/W7twMF1Bp8I/AAAAAAAAT_A/WK1cWcuap4IpmZLKefErekawYiq8iwHmACLcBGAs/s640/apex_pulse.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">OracleJET Plots Pretty Popular Page Performance</td></tr></tbody></table><br />Another favourite of mine plots performance over time, allowing me to target specific pages.<br /><br />It all reminds me of the first time I remember implementing such a practice in Oracle Forms. We had a pre-form trigger that would log <i>who </i>opened <i>which </i>Form <i>when</i>.<br /><br />Using this information, we could communicate with the business about how often how many people really are using those 'super important' Forms.<br /><br />Now APEX gives me this information out-of-the-box, and also tells me how long it spent working on each result. Awesome!<br /><br />It's <i>proof</i>.<br />Proof that a user has (<i>or hasn't</i>) opened a particular page.<br />Proof that the application 'isn't running slow', well, the database is certainly ok.<br />Proof that people are in fact using your application.<br /><br />From 5.x it also logs the Request value, allowing more granularity than ever before. With this I can do things like measure how often a page 3 is opened from page 1 vs page 2. <i>Where are users clicking to navigate?</i><br /><br />So thank you, Oracle APEX team, for continuing to baking such a resourceful feature into the product.<br /><br />I use it <b>every day</b>.<br /><br /><a href="https://twitter.com/search?q=%23ThanksODC" target="_blank">#ThanksODC</a><br /><br /><i>Further reading:</i><br />- Start reading related documentation <a href="https://docs.oracle.com/database/apex-18.2/AEADM/managing-logs-and-files.htm#AEADM29198" target="_blank">here</a>.<br />-&nbsp;<a href="https://www.talkapex.com/2009/05/apex-logs-storing-log-data/" target="_blank">Martin</a> shows us how to get started with archiving this data. It is possible to <a href="https://community.oracle.com/thread/3968352" target="_blank">change the interval</a> between the background table switching.<br />-&nbsp;<a href="https://jeffkemponoracle.com/2008/05/add-a-whos-online-now-box-to-your-apex-app/" target="_blank">Jeff</a> offers an example showing recent users of APEX.<br />- I removed outliers in this <a href="http://www.grassroots-oracle.com/2018/05/filtering-outliers-from-oracle-apex-workspace-activity-logs.html" target="_blank">post</a>.<br />- I pasted a few other SQL examples in this <a href="https://community.oracle.com/message/14720361" target="_blank">forum question</a>. Scott Wesley tag:blogger.com,1999:blog-4818542164384221282.post-5439961783684465194 Wed Oct 10 2018 12:06:00 GMT-0400 (EDT) ODC Appreciation Day: why I’m “on Oracle” #ThanksODC https://jeffkemponoracle.com/2018/10/odc-appreciation-day-thanksodc/ <div id="attachment_5139" style="width: 474px" class="wp-caption alignright"><a href="https://parks.dpaw.wa.gov.au/site/hamersley-gorge" target="_blank" rel="noopener"><img class="wp-image-5139 size-large" src="https://jeffkemponoracle.com/wp-content/uploads/2018/10/PANO_20180708_160444sm-464x1024.jpg" alt="Hamersley Gorge, Karajini National Park, Western Australia. ©2018 Jeffrey Kemp" width="464" height="1024" srcset="https://jeffkemponoracle.com/wp-content/uploads/2018/10/PANO_20180708_160444sm-464x1024.jpg 464w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/PANO_20180708_160444sm-136x300.jpg 136w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/PANO_20180708_160444sm-768x1696.jpg 768w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/PANO_20180708_160444sm-750x1656.jpg 750w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/PANO_20180708_160444sm-300x662.jpg 300w, https://jeffkemponoracle.com/wp-content/uploads/2018/10/PANO_20180708_160444sm.jpg 900w" sizes="(max-width: 464px) 100vw, 464px" /></a><p class="wp-caption-text">Pictured: Hamersley Gorge, Karajini National Park, Western Australia</p></div> <p><strong>Why is this blog called &#8220;Jeff Kemp on Oracle&#8221;?</strong></p> <p>Pretty much my entire career has been underpinned by the Oracle database. My first few I.T. jobs involved maintaining and building Oracle Forms and Reports. SQL and PL/SQL have been my indispensable two-pronged tool since day one and remain so today. Through fortuitous circumstance I had the opportunity to swap Forms for APEX quite a few years ago and I&#8217;ve been busy working on APEX applications since then.</p> <p>The Oracle database is pretty old, and it&#8217;s huge and horrendously complex. It&#8217;s not the most popular &#8211; it certainly is among the &#8220;most dreaded&#8221; technologies in recent surveys; and (apart from XE) it is not cheap. But it unarguably has been, and still is, a major force to be reckoned with. When handled well it is still top of the line when it comes to performance and reliability.</p> <p>Oracle APEX started out as a kid brother to Oracle Forms back in the mid-2000s, and has since quietly risen to be a nimble and capable development platform. It allows developers from different backgrounds to be productive very quickly.</p> <ul> <li>If you&#8217;re a web developer skilled with HTML, CSS and Javascript, you can let APEX handle the database plumbing for you and build beautiful, functional and responsive web sites.</li> <li>If you&#8217;re a PL/SQL nut like me, you can let APEX handle all the user interface and web browser complexities and build beautiful, functional and responsive web sites.</li> </ul> <p>Either way, APEX gives you a starting point to learn the &#8220;other side&#8221;, whichever angle you came from.<small></small></p> Jeffrey Kemp https://jeffkemponoracle.com/?p=5136 Wed Oct 10 2018 12:00:56 GMT-0400 (EDT) Anuncio: mis publicaciones realizadas en el sitio web "Toad World" sobre APEX de los años 2015 y 2016 no han sido migradas al nuevo sitio web http://feedproxy.google.com/~r/DescubriendoElMundoDeOracle/~3/bgWso-XomEs/anuncio-mis-publicaciones-realizadas-en.html Hola a todos!<br /><br />Quería avisar en este post que todas mis publicaciones realizadas de Oracle APEX en el año 2015 y 2016 en el sitio web de&nbsp;<a href="https://www.toadworld.com/" target="_blank">Toad World</a> no han sido migradas despues del rediseño de su sitio web.<br /><br />Si hay algún post en este blog que tenga el link de <b>"Seguir Leyendo...."</b> <span style="color: red;">roto</span> y quieran ver ese artículo o blog por favor me mandan un mensaje por medio del formulario de contacto que esta en la lateral derecha del blog pidiendo si puedo publicar el post, para ello necesito el título y el link del post para que pueda buscar en mis registros y volverlo a publicar.<br /><br />Para ver donde esta mi perfil en el nuevo sitio web de Toad World por favor hacer lci en el link:<br /><br /><a href="https://blog.toadworld.com/author/clarisa-maman-orfali" target="_blank">Perfil Clarisa Maman Orfali</a><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-wit4zLInCS0/W74gmwiFJGI/AAAAAAAAMNI/oA0KppXpMnYZEOCgLhqJkUpNPUXWpBC3ACLcBGAs/s1600/img1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="823" data-original-width="1600" height="205" src="https://4.bp.blogspot.com/-wit4zLInCS0/W74gmwiFJGI/AAAAAAAAMNI/oA0KppXpMnYZEOCgLhqJkUpNPUXWpBC3ACLcBGAs/s400/img1.JPG" width="400" /></a></div><br />Hasta Pronto!<img src="http://feeds.feedburner.com/~r/DescubriendoElMundoDeOracle/~4/bgWso-XomEs" height="1" width="1" alt=""/> Clarisa J. Maman Orfali tag:blogger.com,1999:blog-1315583943401206186.post-4533997915171846694 Wed Oct 10 2018 11:56:00 GMT-0400 (EDT) Few Exadata MOS Docs to review http://jaffardba.blogspot.com/2018/10/few-exadata-mos-docs-to-review.html <div dir="ltr" style="text-align: left;" trbidi="on">If you have MOS login credentials and managing Exadata database machines, below is the list of few MOS Doc which is worth reading:<br /><br /><div class="mentions-texteditor__content" style="background-position: 0px 0px; border: 0px; box-sizing: inherit; line-height: 1.5; outline: 0px; padding: 0px; text-align: left; vertical-align: baseline;"></div><ul style="text-align: left;"><li><span style="font-family: Arial, Helvetica, sans-serif;">888828.1, "Exadata Database Machine and Exadata Storage Server Supported Versions"</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">1070954.1, "Oracle Exadata Database Machine Exachk or HealthCheck"</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">1353073.2, "Exadata Diagnostic Collection Guide"</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">1500257.1, " Exadata Write-Back Flash Cache - FAQ"</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">1553103.1, "dbnodeupdate.sh and dbserver.patch.zip: Updating Exadata Database Server Software using the DBNodeUpdate Utility and patchmgr"</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">1589868.1, "Procedure to check for corrupted root file system on Exadata Storage Servers and Linux database servers"</span></li></ul><div style="color: rgba(0, 0, 0, 0.901961);"><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div></div> The Human Fly tag:blogger.com,1999:blog-19771507.post-9065841450238070011 Wed Oct 10 2018 05:20:00 GMT-0400 (EDT) DATABASE not so READY TO USE! http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/vomcHLufbTM/database-not-so-ready-to-use_8.html <h2>Lesson learned</h2><strike>In fact it turned out, that the database was not READY TO USE. Even if it was stated in the log. The listener simply refused the connection. So I waited until today and finally I was able to connect to the db. There was no further action required. Simply relax and wait. </strike><br /><br />In fact this statement is bulls...<br /><br />OK the database wasn't ready to use and after a restart of the server I was not even able to connect to the database anymore.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-56e6UwcUrJ8/W7u3VwfePMI/AAAAAAAAJT8/9z04FYVRm2sR-etKakh_AyaM9C65_KKcgCLcBGAs/s1600/listener.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="209" data-original-width="390" height="171" src="https://4.bp.blogspot.com/-56e6UwcUrJ8/W7u3VwfePMI/AAAAAAAAJT8/9z04FYVRm2sR-etKakh_AyaM9C65_KKcgCLcBGAs/s320/listener.png" width="320" /></a></div><br /><br /><h3>Und da waren sie wieder, meine x Probleme...&nbsp;</h3>So 1st of all the listener does not know of any services anymore. Even after&nbsp; waiting some time.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-4wyZtDMeZWw/W7uQlU8IrZI/AAAAAAAAJTk/C8xy06g0EPgg3xuYTZcizMpdvyv1IbYjACLcBGAs/s1600/listener.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="299" data-original-width="880" height="135" src="https://3.bp.blogspot.com/-4wyZtDMeZWw/W7uQlU8IrZI/AAAAAAAAJTk/C8xy06g0EPgg3xuYTZcizMpdvyv1IbYjACLcBGAs/s400/listener.png" width="400" /></a></div><br />After consulting google I found the advise to execute the sql cmd<br /><br /><b>alter system register;</b><br /><br />But how to connect to the database without a listener? In my last post I was able to execute sqlplus on the docker container, so maybe it is possible from there.<br /><br />But unfortunately...<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-Q9_JHcx_vVc/W7u35Kll2YI/AAAAAAAAJUE/vkTf-bVsaHoK9KQ0gbnzeIYg6t_kkYu3ACLcBGAs/s1600/ora.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="266" data-original-width="770" height="137" src="https://3.bp.blogspot.com/-Q9_JHcx_vVc/W7u35Kll2YI/AAAAAAAAJUE/vkTf-bVsaHoK9KQ0gbnzeIYg6t_kkYu3ACLcBGAs/s400/ora.png" width="400" /></a></div><br /><b></b>After consulting google again...<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-Wn-ApCXRjAk/W7uSwq8sNYI/AAAAAAAAJTw/BBWC2HVq638l_7XCeOs9GkxwtXdxcykhQCLcBGAs/s1600/oracle_sid.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="164" data-original-width="617" height="106" src="https://3.bp.blogspot.com/-Wn-ApCXRjAk/W7uSwq8sNYI/AAAAAAAAJTw/BBWC2HVq638l_7XCeOs9GkxwtXdxcykhQCLcBGAs/s400/oracle_sid.png" width="400" /></a></div>So I stop the container, add an the environment variable <b>ORACLE_SID</b> and restart the container.<br /><div class="separator" style="clear: both; text-align: center;"></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-SHOgh1IjIGQ/W7u4ScFBIwI/AAAAAAAAJUQ/haQl6cv2K8Y1Mbd0-tQ-01BUpNXWl_wNACLcBGAs/s1600/oracls_sid.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="544" data-original-width="636" height="341" src="https://1.bp.blogspot.com/-SHOgh1IjIGQ/W7u4ScFBIwI/AAAAAAAAJUQ/haQl6cv2K8Y1Mbd0-tQ-01BUpNXWl_wNACLcBGAs/s400/oracls_sid.png" width="400" /></a></div><br /><br /> OK, now I'm able to connect to the database and run the cmd.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-boFgHoPDxIE/W7u4wrTmOSI/AAAAAAAAJUc/QgSSHInkm2QmlJd2swjWa_bGHJZoB1T-ACLcBGAs/s1600/sqlplus.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="357" data-original-width="844" height="167" src="https://2.bp.blogspot.com/-boFgHoPDxIE/W7u4wrTmOSI/AAAAAAAAJUc/QgSSHInkm2QmlJd2swjWa_bGHJZoB1T-ACLcBGAs/s400/sqlplus.png" width="400" /></a></div><br /><br />But still no effect.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-negcxDuwp2o/W7u5DvnDbNI/AAAAAAAAJUk/3SnnayLn2xs-_tzqbckxsHYlH_O9f7bZwCLcBGAs/s1600/lsnrctl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="460" data-original-width="955" height="192" src="https://2.bp.blogspot.com/-negcxDuwp2o/W7u5DvnDbNI/AAAAAAAAJUk/3SnnayLn2xs-_tzqbckxsHYlH_O9f7bZwCLcBGAs/s400/lsnrctl.png" width="400" /></a></div><br /><br />After consulting google again... it looks like there is an issue with 0.0.0.0. So we need a host name. Does the container have a host name? Well not yet. But we can create a container with a host name.<br /><br />So we delete the existing container. Change the permissions of the <b>tnanames.ora </b>and <b>listener.ora</b> in the /docker/oradata/dbconfig/ORCLCDB folder and update the files with the host name that will be used for the container <b>my.oracle18db.net</b>.<br /><h3>&nbsp;<listener .="" aria-haspopup="true" class="goog-spellcheck-word" id=":dg.19" role="menuitem" span="" style="background: yellow none repeat scroll 0% 0%;" tabindex="-1">ora</listener></h3>&gt;&nbsp;LISTENER = <br />(DESCRIPTION_LIST = <br />&nbsp; (DESCRIPTION = <br />&nbsp;&nbsp;&nbsp; (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1)) <br />&nbsp;&nbsp;&nbsp; (ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle18db.net)(PORT = 1521)) <br />&nbsp; ) <br />) <br /><br />DEDICATED_THROUGH_BROKER_LISTENER=ON<br />DIAG_ADR_ENABLED = off<br /><br /><h3>&lt;tnsnames.ora&gt;</h3>LISTENER_ORCLCDB=<br />&nbsp;(ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle18db.net)(PORT = 1521))<br /><br />ORCLCDB= <br />(DESCRIPTION = <br />&nbsp; (ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle18db.net)(PORT = 1521))<br />&nbsp; (CONNECT_DATA =<br />&nbsp;&nbsp;&nbsp; (SERVER = DEDICATED)<br />&nbsp;&nbsp;&nbsp; (SERVICE_NAME = ORCLCDB)<br />&nbsp; )<br />)<br /><br />Now I create a new container with the command:<br /><br /><b>docker run --name oracle-18c-database --hostname my.oracle18db.net -v /volume4/docker/apex:/opt/oracle/apex:rw -v /volume4/docker/oradata:/opt/oracle/oradata:rw -p 31521:1521/tcp -p 35500:5500/tcp -p 38080:8080/tcp oracle/database:18.3.0-ee</b><br /><br />adding<b> </b>a host name. Of course I have establish the ORACLE_SID environment variable again.<br /><br />And after restarting the container.<br /><h3>Tadaaa its magic</h3><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-DDGk9aV6lB4/W7u_fqJppTI/AAAAAAAAJUw/A72kaqhC75cDoEHZZ2Sp6NPAE4Ms339qQCLcBGAs/s1600/listener.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="622" data-original-width="995" height="250" src="https://1.bp.blogspot.com/-DDGk9aV6lB4/W7u_fqJppTI/AAAAAAAAJUw/A72kaqhC75cDoEHZZ2Sp6NPAE4Ms339qQCLcBGAs/s400/listener.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Also the SQL Developer works again</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-YwKJj9MM69U/W7u_y2aSM9I/AAAAAAAAJU4/rHcgI4Lnvis9qereunwWYHuDHZvgqVkkQCEwYBhgL/s1600/connected.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="128" data-original-width="289" height="177" src="https://3.bp.blogspot.com/-YwKJj9MM69U/W7u_y2aSM9I/AAAAAAAAJU4/rHcgI4Lnvis9qereunwWYHuDHZvgqVkkQCEwYBhgL/s400/connected.png" width="400" /></a></div><h3 class="separator" style="clear: both; text-align: left;">A brief summary</h3><ul><li>add the environment variable ORACLE_SID to the container</li><li>add a host name to the container</li><li>&nbsp;update listener.ora and tnsnames.ora</li></ul>And now to something completely different! <img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/vomcHLufbTM" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-6870873394702695252 Mon Oct 08 2018 16:42:00 GMT-0400 (EDT) Running sqlplus on the docker container http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/eiBJ-FLyZcg/running-sqlplus-on-docker-container.html <h2>Running sqlplus on the docker container</h2>I faced some issues while trying to install APEX from windows. Especially loading images was not possible. So I decided to use the sqlplus client in my docker container.<br /><br /><h3>Secure access to the APEX installation files</h3>Do you remember the volume we have mounted during the 1st execution of the container?<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-PN63AfcAB7w/W7ob6hK_nVI/AAAAAAAAJSY/eXiJIojwExEH-GZMqNZUg1acnkuGCmIcQCLcBGAs/s1600/mountpoint.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="67" data-original-width="518" height="51" src="https://3.bp.blogspot.com/-PN63AfcAB7w/W7ob6hK_nVI/AAAAAAAAJSY/eXiJIojwExEH-GZMqNZUg1acnkuGCmIcQCLcBGAs/s400/mountpoint.png" width="400" /></a></div><br />I unzip the Apex installation files into the docker/apex folder on my synology. Access secured.<br /><h3>Connect as root</h3>To be able to run sqlplus on the docker container it is required, that we access the synology using SSH most likely as user root.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-2rqWZ7YUVMw/W7oc_ON0iNI/AAAAAAAAJSk/RerAK0iW21YtsiFPqPbjtG8xvVXsdJPVQCLcBGAs/s1600/root.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="153" data-original-width="413" height="118" src="https://4.bp.blogspot.com/-2rqWZ7YUVMw/W7oc_ON0iNI/AAAAAAAAJSk/RerAK0iW21YtsiFPqPbjtG8xvVXsdJPVQCLcBGAs/s320/root.png" width="320" /></a></div><h3>&nbsp;Bash shell in the docker container</h3>To open a bash shell inside the docker container, we first run the command <b>docker ps</b> to identify the name of our oracle image. There should not be any surprise, but just in case :)<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-T4QJaRVkFJw/W7oenzHmx0I/AAAAAAAAJSw/aCqyQBILzZwHt7DpymBSqPokzbya8YVJACLcBGAs/s1600/dps.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="134" data-original-width="665" height="64" src="https://1.bp.blogspot.com/-T4QJaRVkFJw/W7oenzHmx0I/AAAAAAAAJSw/aCqyQBILzZwHt7DpymBSqPokzbya8YVJACLcBGAs/s320/dps.png" width="320" /></a></div><br />Then we execute a bash shell inside the container by running&nbsp;<b> <br />&nbsp;</b><br /><b>docker exec -it oracle-18c-database /bin/bash</b><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-ebDyvF7ToMk/W7ofpA3urtI/AAAAAAAAJS4/cs3zSKmpI9ApeH5n-e_VWchddlKngSkcQCLcBGAs/s1600/bash.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="54" data-original-width="760" height="22" src="https://4.bp.blogspot.com/-ebDyvF7ToMk/W7ofpA3urtI/AAAAAAAAJS4/cs3zSKmpI9ApeH5n-e_VWchddlKngSkcQCLcBGAs/s320/bash.png" width="320" /></a></div>That's it!<br /><h3>Running sqlplus</h3>To continue with the APEX installation we navigate to the installation directory of the APEX installation files (<b>cd /opt/oracle/apex</b>). And execute sqlplus in nolog mode (<b>sqlplus /nolog)</b><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-xDaEE6NI7x8/W7ogwTFygjI/AAAAAAAAJTM/Ew10t_dG5_04lWOTW11w6zaaTH3bVS4qwCLcBGAs/s1600/sqlplus.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="193" data-original-width="759" height="81" src="https://3.bp.blogspot.com/-xDaEE6NI7x8/W7ogwTFygjI/AAAAAAAAJTM/Ew10t_dG5_04lWOTW11w6zaaTH3bVS4qwCLcBGAs/s320/sqlplus.png" width="320" /></a></div><br /><br /><br /><br /><div class="separator" style="clear: both; text-align: center;"></div><br /><img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/eiBJ-FLyZcg" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-6548784857888757358 Mon Oct 08 2018 13:21:00 GMT-0400 (EDT) apex.world - Behind the Scenes https://jackiemcilroy.blogspot.com/2018/10/apexworld-behind-scenes_8.html <p>In the past month, since I started helping out as an administrator of apex.world, the most common questions I get are ‘What’s it like?’, ‘What do you do?’, and, of course, ‘What is it like to work with Juergen?’. So, I thought I would take the time write it out here, in case anyone else is interested.</p><h2 id="whats-it-like">What’s it like?</h2><p>It’s awesome! I have been a frequent visitor of apex.world since its launch. apex.world was actually the reason I opened a Twitter account in the first place as I saw from the feed on the site how active and accessible the #orclapex community is. Its the first Slack workspace I ever joined. Its the easiest way to search APEX related blog content - well actually <em>any</em> APEX related content. And its a great way to get it touch with our wonderful APEX community. As an administrator of the site, I am immersed daily in the happenings of the APEX world. I see new blog posts as they are published, stay on top of the news and latest announcements, read <em>almost</em> every tweet, I never miss a plug-in or new meetup group, I am first to hear of any APEX job opening, and the I get to see our awesome community grow each and every day.</p><h2 id="what-do-you-do">What do you do?</h2><p>There is actually a lot of work that goes in to keeping apex.world running on a daily basis. If I am honest, a lot more than I initially imagined when Juergen asked me to help out.</p><p>We are all familiar with apex.world, right? (If you answered <em>NO</em> please proceed directly to <a href="https://apex.world/">apex.world</a> and get acquainted 😉) apex.world is a one-stop-shop for all things Oracle APEX - its all about content. We don’t do any work to rebuild the site or make it super fancy - no new themes, no new functionality (unless necessary), no promotion. apex.world is meant to be in the background, as a canvas for content. It is like the actual paper of a newspaper, just the means to an end. This is the spirit of apex.world - service to the community, no room for self promotion. And we should all be celebrating - apex.world is turning 3 on October 19th! In this time we have:</p><ul><li>3800 Registerted Members</li><li>1600 News Posts</li><li>1120 Twitter Followers</li><li>1600 Slack Members</li><li>180000 Slack Messages</li><li>41 Meetups</li><li>3100 Meetup Members</li><li>28 Newsletters</li><li>10 On Air Shows</li><li>22 Podcasts</li><li>36 Conferences</li><li>155 Plug-ins</li><li>120 Jobs</li><li>130 Trainings</li></ul><p>You find all this wonderful content as soon as you log in. The actual home page has three main sections, <strong>Slack</strong>, <strong>News</strong>, and <strong>Tweets</strong>.</p><p><img src="https://lh3.googleusercontent.com/lhBcITTYqfAyiV-Hl7TpBbRgIBBRyhD9BVh8A_SYUvXMa_Kq_ozZl4Yi88JJ15Ku5_5ZWM65jZG6=s700" alt="apex.world home page"></p><h3 id="slack">Slack</h3><p>I am an owner of the orclapex Slack workspace. Really, all that means is I can add new channels if the need arises. I could probably do a lot more, but there is a great group of APEX community members that monitor and help out with our Slack channel. I do get to see how active the Slack workspace is, which is interesting and I keep track of the fluctuating membership number (currently <strong>1,610</strong>) , If you aren’t a member, I highly recommend logging in to apex.world and requesting an invitation. Lots of really smart people are here answering questions and helping out.</p><h3 id="news">News</h3><p>This is the ❤️ of apex.world. Here we showcase APEX related announcements, blog posts, videos, webinars, and events. This is also where most of the effort is involved. As newsworthy content arises, Juergen and I add it to apex.world. No, this does not happen magically - here is what we do:</p><ul><li>Blogs - If you are an apex.world member, every time you publish a blog and we see it via #orclapexworld, @orclapexworld, or #orclapex, we review it for appropriate content (no spam or obnoxious sales pitches) and create an entry in our apex.world admin application.<br><img src="https://lh3.googleusercontent.com/jmUYeyTU5L_C1l55VHfE7w7lDRBSvKME8ERuLDQF9HY4sLghGArKVYB0H_eHT5Kz4GaUzLSoVVE8=s700" alt="apex.world Admin Application"><br>We add tags (we have more than <strong>135</strong>!) to the best of our ability to make it easy for others to find your fantastic blog post (or other news content), we also might shorten the title a bit to get straight to the point - and <em>voilà</em> - its published on the site for all our users to enjoy. We do only publish blog posts for members of apex.world, so if you are an APEX blogger - please be sure to sign up. But don’t just sign up - be sure to fill out your profile and add a profile picture. You will only get published if you have a picture - this allows us to avoid those annoying and ugly broken image links in the news. If for some reason you don’t have a picture and you publish a blog post you can expect an email from Juergen or myself requesting that you add one before we publish your article.</li><li>Videos - Did you know apex.world has its own <a href="https://www.youtube.com/channel/UCY7t5jZ2cyZXIil1L8jfTwg">YouTube channel</a>? When y’all publish new APEX videos, webinars, or tutorials - we add them to the appropriate channel then log in to our trusty apex.world Admin application and create the news entry with the appropriate tags.<br><img src="https://lh3.googleusercontent.com/AA7FAVkrPV1tvpKp-3TIh-eIQsI9uWyndPU6hcs2jkhm46Fa10qYgv00TRyvsjHTl3Te5ApX1UXT=s700" alt="apex.world YouTube"></li><li>Plug-ins - When a new plug-in is added by a developer to the apex.world site, I get a notification email. I can then log in and make sure things look good. I check to make sure the links are correct and that there is a nice description and image/gif for the plug-in. If everything checks out, I create a news entry and tweet about it from the <a href="https://twitter.com/orclapexworld">@orclapexworld</a> twitter account (more on this later).</li><li>Job Offers - I also get an email notification every time a new job offer is added to apex.world. There is a little more work involved here as a job offer can be added by anyone, not just members of apex.world. This is because we don’t expect recruiters to sign up for apex.world when in reality they are not interested in the content. So, we have to verify that the job offer is legitimate and that email address provided is monitored. We send an email to the poster asking them to confirm the request. Its pretty simple, if they respond the job offer is posted to the community and tweeted. If no response, its dropped. We also mark these job offers as expired when needed or remove them completely at the request of the poster. All in an effort to keep the information as up-to-date as possible.</li><li>Meetups, Conferences, and Training - We also keep track of events that are of interest to the APEX community. New meetup groups can be submitted to the site, and after we confirm that they are legit, they are listed so that APEX enthusiasts all around the world can get connected to people in their area. Upcoming conferences are also listed, as well as training opportunities for APEX developers. We have general rule to post English content news only. This is because we simply can not review content in a 150 languages. But, we make an exception to this rule for training - it’s essential to find a training course in your native language.</li><li>Member of the Month - At the end of each month, a <em>Member of the Month</em> is selected. What we do is review all of the content from that month and determine who had the most impact. It can be someone that published a ton of really helpful blog posts, someone who went above and beyond in Slack, or someone that developed something really fantastic for the APEX community. Anything goes, we just try to determine who really stood out that month and give them a bit of recognition 😄. This is published as news and also tweeted.</li><li>Monthly Newsletter - Each month we send out, via email, a recap of all the happenings in the APEX Community for the given month as well as upcoming events. We also publish this as news and tweet it for anyone interested who might not be subscribed.</li></ul><h3 id="tweets">Tweets</h3><p>The tweets are the most fun 🙂. Our handle is <a href="twitter.com/orclapexworld">@orclapexworld</a>. We have a really cool APEX application called the <strong>The Tweet Master 9000</strong>.<br><img src="https://lh3.googleusercontent.com/OD85Lw8IfMDp65Fa4_pOpvEkoZTy1RyP01WKsL9sYQkrChf0YRONLUyA0Z3_BJeVaSUy9E_AZtEy=s700" alt="Tweet Master 9000"></p><p>This application was developed by the very talented <a href="https://twitter.com/cczarski">Carsten Czarski</a> when Juergen could not find a twitter client that gave him the ability to retweet or delete multiple tweets. For the curious, the <em>9000</em> was added the name because all awesome machines in Germany get the product number 9000. It kind of sounds like the ultimate version like the T1000 in The Terminator 😄. The Tweet Master 9000 uses RESTful services, of course, to gather all the tweets that reference #orclapexworld, @orclapexworld, or #orclapex that we haven’t already retweeted or discarded and displays them so that we are able to review the content and retweet in bulk. Here, we look at each and every tweet to determine that the content is appropriate and its not spam. If it passes inspection it gets retweeted to all of our followers. The Tweet Master 9000 is also where we find a lot of the news items (blog posts, videos, webinars, training, general announcements) that get added to apex.world. Most of the daily activity on our twitter feed is retweets of relevant content posted to twitter. The goal here is to have one account you can follow to get all of the APEX content you could ever want 🙂. We do tweet original content when we find it would be useful to our followers - this includes Jobs, Meetups, Conferences, Member of the Month, Newsletters, Plug-ins, Podcasts, Breaking news (like new APEX versions), and training. Some of you may ask, <em>‘Can’t you just write some code that will retweet all of this for you?’</em>. The answer is no (or not yet 😉) - unfortunately people abuse the hashtags for content unrelated to APEX and when hashtags become popular, a lot of bots and spam get attached to them as well. There is a lot of human instinct used to decide what is appropriate to post or to retweet. AI could not properly grasp hidden intentions in the content - but maybe in the future - we will see 😉. Our goal is to make sure that only content related to Oracle APEX be included in our feed.</p><h2 id="what-is-it-like-to-work-with-juergen">What is it like to work with Juergen?</h2><p>Maybe I should rephrase that question - most of the time its asked this way - <em>Don’t you spend all your time arguing with Juergen?</em> I get where people are coming from. You see him out on twitter giving and defending his opinion on various topics (just ask <a href="https://twitter.com/martindsouza">Martin D’Souza</a> 😉). Yes, <a href="https://twitter.com/JuergenSchuster">Juergen</a> has strong opinions and is not afraid to voice them - but, to his credit, he thinks things through very rationally and can be easily swayed if you provide better logic. So, in answer to that question - no we don’t argue all the time. We actually have worked together really well <em>so far</em> and seem to agree on direction and daily decisions for apex.world. Juergen has worked really hard to create a very clear set of rules for apex.world that we adhere to despite our personal opinions or affiliations. When it comes to apex.world he is completely neutral. He has developed a way to keep the APEX community informed in an easy to use, fair and impartial way. He is a pillar of our community. I am honored that he has trusted me to help him with the daily operation of apex.world. Running the site is not easy and takes dedication and time (5+ hours a week, at least) . He has done the brunt of the work in keeping it going every day since it began and frankly, he deserves a vacation! I am happy to be a part of it and help in any way I can.</p><p>-Jackie-</p> Jackie McIlroy tag:blogger.com,1999:blog-7781371764054860649.post-329661431244750973 Mon Oct 08 2018 12:57:00 GMT-0400 (EDT) (EX42) Flash disk failure may lead to ASM metadata corruption when using write-back flash cache http://jaffardba.blogspot.com/2018/10/ex42-flash-disk-failure-may-lead-to-asm.html <div dir="ltr" style="text-align: left;" trbidi="on">While reviewing the latest Exachk report on X5-2 machine, the following critical alrams were observed:<br /><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-Zk3FuymonI0/W7tFzuZfzNI/AAAAAAAAf2I/cUG5E7-w-cwDm-5BPJIHlEXkM8m09ebMwCLcBGAs/s1600/Screen%2BShot%2B2018-10-08%2Bat%2B2.54.16%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="130" data-original-width="1600" height="50" src="https://4.bp.blogspot.com/-Zk3FuymonI0/W7tFzuZfzNI/AAAAAAAAf2I/cUG5E7-w-cwDm-5BPJIHlEXkM8m09ebMwCLcBGAs/s640/Screen%2BShot%2B2018-10-08%2Bat%2B2.54.16%2BPM.png" width="640" /></a></div><br />And details shows below description:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-yA8lcPekWpY/W7tGKTth3cI/AAAAAAAAf2Q/87_b2EHDEaYVvydiz1OzupkbmQ8lZC9swCLcBGAs/s1600/Screen%2BShot%2B2018-10-08%2Bat%2B2.57.06%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="499" data-original-width="1600" height="198" src="https://2.bp.blogspot.com/-yA8lcPekWpY/W7tGKTth3cI/AAAAAAAAf2Q/87_b2EHDEaYVvydiz1OzupkbmQ8lZC9swCLcBGAs/s640/Screen%2BShot%2B2018-10-08%2Bat%2B2.57.06%2BPM.png" width="640" /></a><a href="https://3.bp.blogspot.com/-rmE7a31nf40/W7tGUd-fSBI/AAAAAAAAf2U/L0r5b2cDOoYLVI698Zm5k-YbZfGhLZ3kwCLcBGAs/s1600/Screen%2BShot%2B2018-10-08%2Bat%2B2.57.51%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="610" data-original-width="1072" height="364" src="https://3.bp.blogspot.com/-rmE7a31nf40/W7tGUd-fSBI/AAAAAAAAf2U/L0r5b2cDOoYLVI698Zm5k-YbZfGhLZ3kwCLcBGAs/s640/Screen%2BShot%2B2018-10-08%2Bat%2B2.57.51%2BPM.png" width="640" /></a></div><br />And the MOS Note : 1270094.1 explains the following:<br /><br /><div class="separator" style="clear: both; te: center;"><a href="https://2.bp.blogspot.com/-V9l1BaZrTv0/W7tGwwp9IxI/AAAAAAAAf2g/y-8n_bUQJ7Q_Osle00z6epJcm6ziQjiIwCLcBGAs/s1600/Screen%2BShot%2B2018-10-08%2Bat%2B2.59.40%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="153" data-original-width="1600" height="60" src="https://2.bp.blogspot.com/-V9l1BaZrTv0/W7tGwwp9IxI/AAAAAAAAf2g/y-8n_bUQJ7Q_Osle00z6epJcm6ziQjiIwCLcBGAs/s640/Screen%2BShot%2B2018-10-08%2Bat%2B2.59.40%2BPM.png" width="640" /></a></div><br />According to MOS Doc: 2356460.1, the said behavior is due to a bug (27372426) which applies on Exa version 12.2.1.1.0 to 12.2.1.1.5 or 18.1.0.0.0 to 18.1.3.0.0. <br /><br /><b><u>Impact:</u></b><br /><br />If you are running GI 11.2.0.4 or 12.1 with the above said Exa version, and &nbsp;with FlashCache configured as Writeback mode, the following ORA error may encounter, during: ASM rebalancing operation, disk group mount, &amp; disk group consistency checks, ASM review asm alert.log:<br /><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;">ORA-00600: internal error code, arguments: [kfdAuDealloc2]</span><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;"><br /></span><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;">WARNING: cache read a corrupt block: group=1(DATA) fn=381 indblk=27 disk=110 (DATA_CD_04_DM01CEL01)</span><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;">ORA-15196: invalid ASM block header [kfc.c:26411] [endian_kfbh]</span><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;"><br /></span><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;">ORA-00600: internal error code, arguments: [kfrValAcd30]</span><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;"><br /></span><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;">ORA-00600: internal error code, arguments: [kfdAuPivotVec2], [kfCheckDG]</span><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;"><br /></span><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;">ERROR: file +DATADG1.3341.962251267: F3341 PX38530 =&gt; D55 A765853 =&gt; F1677</span><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;">PX1647463: fnum mismatch</span><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;">ERROR: file +DATADG1.3341.962251267: F3341 PX38531 =&gt; D15 A205431 =&gt; F3341</span><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;">PX56068: xnum mismatch</span><br /><span style="background-color: #e0eaf1; font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: 11.699999809265137px;"><br /></span><br /><br /><b><u>Workaround</u></b>:<br />To fix the bug, Following action plan needs to be applied:<br /><br />1) Update the storage server to &gt;=12.2.1.1.6 or &gt;=18.1.4.0.0<br />2) Apply patch 27510959 and scan ASM metadata<br /><br /><br /><b><u>Note :</u></b><br /><b><u><br /></u></b>The issues doesn't impact on GI 12.2 or whenever you have higher version of Exa software mentioned in this bug;<br />The bug also doesn't affect if the FlashCache mode is WriteThrough;<br /><br /><b><u>References:</u></b><br /><b><u><br /></u></b><span style="background-color: white; font-family: &quot;tahoma&quot; , &quot;verdana&quot; , &quot;helvetica&quot; , sans-serif; font-size: 14.300000190734863px; font-weight: bold; text-align: right;">Exadata Critical Issues (Doc ID 1270094.1)</span><br /><span style="background-color: white; font-family: &quot;tahoma&quot; , &quot;verdana&quot; , &quot;helvetica&quot; , sans-serif; font-size: 14.300000190734863px; font-weight: bold; text-align: right;"><br /></span><br /><table border="0" cellpadding="0" cellspacing="0" id="kmPgTpl:r1:0:tl5" style="caret-color: rgb(51, 51, 51); color: #333333; font-family: Tahoma, Verdana, Helvetica, sans-serif; font-size: 11px; width: 100%px;" summary=""><tbody><tr id="kmPgTpl:r1:0:rl12"><td align="left" id="kmPgTpl:r1:0:cf49"><span class="xq" id="kmPgTpl:r1:0:ol22" style="color: black; font-size: 14.300000190734863px; font-weight: bold; padding: 0px 6px 0px 0px; text-align: right;"><label>(EX42) Flash disk failure may lead to ASM metadata corruption when using write-back flash cache (Doc ID 2356460.1)</label></span></td></tr></tbody></table></div> The Human Fly tag:blogger.com,1999:blog-19771507.post-8037287961971595755 Mon Oct 08 2018 08:19:00 GMT-0400 (EDT) Connectivity! http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/XEmJ4UB2HR0/connectivity.html <h2>Fritz Box</h2>I't is required to configure static port forwarding rules in your router to enable the communication between the internet and your container. In my setup I have mapped the ports 38080, 31521 and 35500 to sligtly different ports lets say x8080, x1521 and x5500. These ports can be reached via the DynDNS address of my NAS<br /><h3>TNS_ADMIN</h3>The lazy developer utilizes the tnsnames.ora file.<br /><h4>Environment variable</h4>If not already available create an environment variable with the name <b>TNS_ADMIN</b> pointing at the path of your tnsnames.ora file.<br /><h4>tnsnames.ora</h4>Add the following entries to your existing tnsnames.ora file or create a new one in the prefered location.<br /><br />ORCLCDB =<br />&nbsp;(DESCRIPTION = <br />&nbsp;&nbsp; (ADDRESS_LIST =<br />&nbsp;&nbsp;&nbsp;&nbsp; (ADDRESS = (PROTOCOL = TCP)(HOST = <b>xxx.xxxxxxx.xxx</b>)(PORT = <b>X</b>1521))<br />&nbsp;&nbsp; )<br />&nbsp;(CONNECT_DATA =<br />&nbsp;&nbsp; (SERVICE_NAME = ORCLCDB)<br />&nbsp;)<br />)<br /><br />ORCLPDB1 =<br />&nbsp;(DESCRIPTION = <br />&nbsp;&nbsp; (ADDRESS_LIST =<br />&nbsp;&nbsp;&nbsp;&nbsp; (ADDRESS = (PROTOCOL = TCP)(HOST = <b>xxx.xxxxxxx.xxx</b>)(PORT = <b>X</b>1521))<br />&nbsp;&nbsp; )<br />&nbsp;(CONNECT_DATA =<br />&nbsp;&nbsp; (SERVICE_NAME = ORCLPDB1)<br />&nbsp;)<br />) <br /><br />Please adapt the host and port to your DynDNS address and external port.<br /><h3>SQL Developer</h3>The actual SQL Developer version at point of writing is 18.2.<br />With an tnsnames.ora in place it is easy to establish connections to the container and plugable database.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-09yQkeCBi8E/W7nZ9RG1MiI/AAAAAAAAJR0/a3GTUcTT8bsu_lRMJMmIMTehWz1hwbMXgCLcBGAs/s1600/connections.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="405" data-original-width="753" height="215" src="https://2.bp.blogspot.com/-09yQkeCBi8E/W7nZ9RG1MiI/AAAAAAAAJR0/a3GTUcTT8bsu_lRMJMmIMTehWz1hwbMXgCLcBGAs/s400/connections.png" width="400" /></a></div><br />Connecting the sys schema as SYSDBA allows me to apply DBA related tasks to the database(s).<br /><br /><h3>Oracle Enterprise Manager</h3>I can call the enterprise manager under the following link:<br /><br /><b>https://<dyndns .name="">:<x>5500/em</x></dyndns></b><br /><br /><div class="separator" style="clear: both; text-align: center;"></div>I want to connect to the container db <b>ORCLCDB </b>as sysdba first. Please not that the Container name to be used has to be <b>CDB$ROOT.</b> While trying to login into the CDB you will most likely face this dialog:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-KO2NPs5TUYg/W7nTpuQi0XI/AAAAAAAAJRs/mPjz_sXx_ecbG50q_QfIwNMNEFGfYVD3QCEwYBhgL/s1600/xdb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="414" data-original-width="679" height="243" src="https://1.bp.blogspot.com/-KO2NPs5TUYg/W7nTpuQi0XI/AAAAAAAAJRs/mPjz_sXx_ecbG50q_QfIwNMNEFGfYVD3QCEwYBhgL/s400/xdb.png" width="400" /></a></div><br />Finally I came across an <a href="https://www.martinberger.com/?p=4131" target="_blank">explanation </a>of the issue and even better the solution. We simply have to enable the related global port by executing the command:<br /><br /><b>exec dbms_xdb_config.setglobalportenabled(TRUE);</b><br /><br />as user SYS as SYSDBA on the database ORCLCDB. I had to reload my FireFox to be able to connect to the EM.<br />It is required to enable the global port separately for every plugable db that needs to be accessed with the EM. In case of the ORCLPDB1, this means run the command as user SYS<b> </b>as SYDBA on the database ORCLPDB1. In case of plugable databases the container name in the EM is equal to the database name. Finally you will see this wonderful dashboard.<br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-QZKyHrHjqAM/W7ndHZ4pBFI/AAAAAAAAJSA/t0ugJmKVLsMsLW3i9EO4jcbb8z18uUMMwCLcBGAs/s1600/em.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="745" data-original-width="1600" height="185" src="https://1.bp.blogspot.com/-QZKyHrHjqAM/W7ndHZ4pBFI/AAAAAAAAJSA/t0ugJmKVLsMsLW3i9EO4jcbb8z18uUMMwCLcBGAs/s400/em.png" width="400" /></a></div><br /><h3>sqlplus</h3>Finally I would like to connect to my database(s) using sqlplus. I downloaded the oracle instant client 18.2 from <a href="https://www.oracle.com/technetwork/topics/winx64soft-089540.html" target="_blank">OTN.</a> It is required to fetch the basic and the sqlplus package. I have unpacked both packages and added the location to my %PATH%.<br />I start sqlplus by using the windows powershell and the command<br /><br /><b>sqlplus /nolog</b><br /><br />and login into the plugable database with the command<br /><br /><b>conn sys@orclpdb1 as sysdba</b><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-5T0pHD8bFu8/W7nimhhFsQI/AAAAAAAAJSM/ObjbWNgAK4IbbvWeBWpwjVGRZqa0HaJ0ACLcBGAs/s1600/sqlplus.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="243" data-original-width="627" height="124" src="https://4.bp.blogspot.com/-5T0pHD8bFu8/W7nimhhFsQI/AAAAAAAAJSM/ObjbWNgAK4IbbvWeBWpwjVGRZqa0HaJ0ACLcBGAs/s320/sqlplus.png" width="320" /></a></div><br /><br />Please ignore the warning =&gt; SP2-0310: unable to open file "LOGIN.SQL"<b> </b><img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/XEmJ4UB2HR0" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-9120224005234584385 Sun Oct 07 2018 06:33:00 GMT-0400 (EDT) DATABASE not so READY TO USE http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/ksjhZeFjY7k/database-not-so-ready-to-use.html <h2>Lesson learned</h2>In fact it turned out, that the database was not READY TO USE. Even if it was stated in the log. The listener simply refused the connection. So I waited until today and finally I was able to connect to the db. There was no further action required. Simply relax and wait.<img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/ksjhZeFjY7k" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-9105769319122478963 Sun Oct 07 2018 05:00:00 GMT-0400 (EDT) DATABASE IS READY TO USE! http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/pr4ZjtHMBQI/database-is-ready-to-use.html <h2>Finally</h2>After 2.5h finally the log stated<br /><br /><pre class="allowDefCtxMenu selectabletext">#########################</pre><pre class="allowDefCtxMenu selectabletext">DATABASE IS READY TO USE!</pre><pre class="allowDefCtxMenu selectabletext">######################### </pre><br />According to the log a conatiner database <b>ORCLCDB</b> and the first plugable database<b> ORCLPDB1</b><br />have been created.<br /><br />As creating an Oracle RDBMS container takes some time it might be usefull to export the container.<br /><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-cOyCPvumgns/W7j1IxotWrI/AAAAAAAAJRI/zD72dA0jPtYUFF3zF6Zl1ivR73JpL5z7gCLcBGAs/s1600/export.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="296" data-original-width="1051" height="112" src="https://2.bp.blogspot.com/-cOyCPvumgns/W7j1IxotWrI/AAAAAAAAJRI/zD72dA0jPtYUFF3zF6Zl1ivR73JpL5z7gCLcBGAs/s400/export.png" width="400" /></a></div><br />And to be on the save side I prefer to export the container and its content to my Diskstation.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-35Il7OgObR8/W7j1mnArr3I/AAAAAAAAJRQ/CjvyFpFdoWI2hZ0IAPRg7qhXdDOycWhYACLcBGAs/s1600/export1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="440" data-original-width="534" height="263" src="https://4.bp.blogspot.com/-35Il7OgObR8/W7j1mnArr3I/AAAAAAAAJRQ/CjvyFpFdoWI2hZ0IAPRg7qhXdDOycWhYACLcBGAs/s320/export1.png" width="320" /></a></div><br />In addition I create a Hyperbackup of my oradata files to have a backup of my database.<img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/pr4ZjtHMBQI" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-8773698281328228020 Sat Oct 06 2018 13:51:00 GMT-0400 (EDT) Launching the container for the 1st time http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/6f-Dg3dDjM8/launch-container-for-1st-time.html <h2>Container preparation</h2>I know, that it is possible to use the command line, but in this case I prefer the wizard to create and launch the container. To start I go to the images section, highlight the <b>oracle/database:18.3.0-ee</b> image and press the launch button.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-5mqElzN5FqY/W7iU0tPJOYI/AAAAAAAAJPk/FTEIpML0APoJTdayQEzlplcIlgI91_0gACLcBGAs/s1600/Image.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="561" data-original-width="1055" height="211" src="https://4.bp.blogspot.com/-5mqElzN5FqY/W7iU0tPJOYI/AAAAAAAAJPk/FTEIpML0APoJTdayQEzlplcIlgI91_0gACLcBGAs/s400/Image.png" width="400" /></a></div><h3>General Settings</h3>Always choose a meaningful container name. I will use <b>oracle-18c-database</b>, as I will not have multiple databases in place at the same point in time. Then I click on the advanced settings button.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-g3hyseTKH3Q/W7iV1ol6R1I/AAAAAAAAJPs/rR65yYCfoosckxeu_mSbYAGHe1KL9xfgQCLcBGAs/s1600/container1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="494" data-original-width="687" height="287" src="https://1.bp.blogspot.com/-g3hyseTKH3Q/W7iV1ol6R1I/AAAAAAAAJPs/rR65yYCfoosckxeu_mSbYAGHe1KL9xfgQCLcBGAs/s400/container1.png" width="400" /></a></div><br />I will not limit the resources of my synology unless it is absolutely required. It is possible to run the container with the default settings, but I would like to make some adjustments.<br /><h3>Advanced settings</h3>Not very advanced, but I would like enable the <b>auto-restart</b>.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-o39OhEbDaBk/W7iX6gAi7_I/AAAAAAAAJP4/BezVhx78Fq8dT-phvl8PbZVHY34_spbLQCLcBGAs/s1600/advancedSettings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="198" data-original-width="630" height="100" src="https://2.bp.blogspot.com/-o39OhEbDaBk/W7iX6gAi7_I/AAAAAAAAJP4/BezVhx78Fq8dT-phvl8PbZVHY34_spbLQCLcBGAs/s320/advancedSettings.png" width="320" /></a></div><br /><h3>Volume</h3>Mounting volumes simply enables us to use directories placed outside the container inside the container. This makes it easier to add additional functionality to the container. I mount two volumes.<br />Both source directories are located in my docker home.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-MW0gIUxrcqc/W7iaIoaZuiI/AAAAAAAAJQE/wV0YAIwxLYEGiP7Uh1CasubenmhSSOXIACLcBGAs/s1600/volumes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="164" data-original-width="671" height="78" src="https://2.bp.blogspot.com/-MW0gIUxrcqc/W7iaIoaZuiI/AAAAAAAAJQE/wV0YAIwxLYEGiP7Uh1CasubenmhSSOXIACLcBGAs/s320/volumes.png" width="320" /></a></div><br />The directory <b>oradata</b> will contain the database files and the directory <b>apex</b> contains the latest Oracle Apex version 18.2 that will be installed in a later step.<br /><h3>Port settings</h3>I like static port mappings so here we go. Using static port mappings will secure that all my port forwarding's are still valid after a restart of the container.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-Su9frFs6nKg/W7ibBLQkATI/AAAAAAAAJQM/zLbDmZKCkBkVWDMudDBCe89s7uAwolpKACLcBGAs/s1600/ports.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="202" data-original-width="700" height="92" src="https://4.bp.blogspot.com/-Su9frFs6nKg/W7ibBLQkATI/AAAAAAAAJQM/zLbDmZKCkBkVWDMudDBCe89s7uAwolpKACLcBGAs/s320/ports.png" width="320" /></a></div><br />Pressing apply returns us to the <b>General Settings </b>screen. Everything is in place so we can hit the Next button.<br /><h3>Summary</h3>The summary page highlights all details of the future container. The flag to run the container immediately after the wizard is finished is set already. I hit apply as everything looks fine.<br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-A4CFYckI1C4/W7ic3TQjP0I/AAAAAAAAJQY/gLFPwTbJiD8DxZSVT4nc0CcxOMXpP_p_QCLcBGAs/s1600/summary.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="493" data-original-width="690" height="228" src="https://3.bp.blogspot.com/-A4CFYckI1C4/W7ic3TQjP0I/AAAAAAAAJQY/gLFPwTbJiD8DxZSVT4nc0CcxOMXpP_p_QCLcBGAs/s320/summary.png" width="320" /></a></div><br />Starting the container will take some time, because at this point in time the databases will be created and you will not see much progress. However you can switch to the containers page to monitor the progress.<br /><h3>Container</h3>This is the place to see all available containers and there status (high level).<br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-rtjn2rlbpzE/W7idwmD77XI/AAAAAAAAJQg/9DrIfQfFHh0V1rQs7kMdIZUB--xeohaxgCLcBGAs/s1600/container.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="294" data-original-width="1048" height="89" src="https://3.bp.blogspot.com/-rtjn2rlbpzE/W7idwmD77XI/AAAAAAAAJQg/9DrIfQfFHh0V1rQs7kMdIZUB--xeohaxgCLcBGAs/s320/container.png" width="320" /></a></div>To get more details I highlight the container and hit the Details button.<br /><h3>Overview </h3><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-Nmc9SRWC5Js/W7ieJxqSFkI/AAAAAAAAJQo/i7ZYRk12HWcVFCJ2c7Qerve3YtPYyF7sgCLcBGAs/s1600/details.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="552" data-original-width="1407" height="156" src="https://2.bp.blogspot.com/-Nmc9SRWC5Js/W7ieJxqSFkI/AAAAAAAAJQo/i7ZYRk12HWcVFCJ2c7Qerve3YtPYyF7sgCLcBGAs/s400/details.png" width="400" /></a></div>Did I mention that creating a database will take a hell of time? If you start to get worried you can check two tabs of the container details page.<br /><h3>Log</h3><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-vbYZTjdvb6Y/W7ie-k3wXvI/AAAAAAAAJQ0/mxWUZjOS0-Afk0p5Dt5WAgORNpITGtfdACLcBGAs/s1600/log.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="555" data-original-width="1406" height="157" src="https://1.bp.blogspot.com/-vbYZTjdvb6Y/W7ie-k3wXvI/AAAAAAAAJQ0/mxWUZjOS0-Afk0p5Dt5WAgORNpITGtfdACLcBGAs/s400/log.png" width="400" /></a></div><br />The log tab will show you the actual log of your container and therefor the progress of the installation. However, sometimes it takes some time as well until the progress in shown in the log (NO PANIC!). It also shows you the initial password set for your DBA schema's. The log will remain at least for some days. In fact I have not seen any log entries disappearing.<br /><h3>Process</h3><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-epMf9ts2fSY/W7igAtkGesI/AAAAAAAAJQ8/_81F4dH_L18evDHTosmCu36W09K-ZjGKACLcBGAs/s1600/process.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="555" data-original-width="1407" height="157" src="https://2.bp.blogspot.com/-epMf9ts2fSY/W7igAtkGesI/AAAAAAAAJQ8/_81F4dH_L18evDHTosmCu36W09K-ZjGKACLcBGAs/s400/process.png" width="400" /></a></div><br />The process tab shows the actual processes running in your container. So everything is fine as long as figures are changing here, even if there is no progress in the log (NO PANIC!).<br /><h3>Terminal</h3>Okay, there is a terminal tab. But I don't use it. You can give it a try and you will find out, why I prefer to use putty instead.<br /><br /><h3>The run command</h3>In case you still want to use the cmd or in case you don't use this on a synology.<br /><br />docker run --name oracle-18c-database -v /volume4/docker/apex:/opt/oracle/apex:rw -v /volume4/docker/oradata:/opt/oracle/oradata:rw -p 31521:1521/tcp -p 35500:5500/tcp -p 38080:8080/tcp oracle/database:18.3.0-ee <img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/6f-Dg3dDjM8" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-3032981814445186522 Sat Oct 06 2018 07:48:00 GMT-0400 (EDT) SQL Connection via an Encrypted SSH Tunnel https://insum.ca/sql-connection-via-encrypted-ssh-tunnel/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/10/sqlnet-over-ssh-Insum-100x100.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="sqlnet over ssh Insum" srcset="https://insum.ca/wp-content/uploads/2018/10/sqlnet-over-ssh-Insum-100x100.jpg 100w, https://insum.ca/wp-content/uploads/2018/10/sqlnet-over-ssh-Insum-150x150.jpg 150w, https://insum.ca/wp-content/uploads/2018/10/sqlnet-over-ssh-Insum-600x600.jpg 600w, https://insum.ca/wp-content/uploads/2018/10/sqlnet-over-ssh-Insum-300x300.jpg 300w, https://insum.ca/wp-content/uploads/2018/10/sqlnet-over-ssh-Insum-50x50.jpg 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><h2>Background</h2> <p>I recently did multiple upgrades on my Mac: the O/S to High Sierra, SQL Developer to 18.1, and then the JDK to bring it up to a level that SQL Dev requires. Naturally, I updated to the latest JDK, which is higher than SQL Dev 18.1 supports, but hey, why not?</p> <p>Any time you change more than one thing, troubleshooting becomes complicated. This was no exception. The challenge started when I realized that by &#8220;upgrading&#8221; SQL Developer on my Mac, I actually overwrote the previous install, thereby deleting all of my connections and preferences. Sadly, this isn&#8217;t the first time I&#8217;ve done this. I don&#8217;t do a SQL Dev upgrade that often, so I forgot that it would overwrite everything. Sigh.</p> <h2>SSH Tunnel Connections</h2> <p>After increasing the SQL Dev font size (my eyes aren&#8217;t what they used to be) I endeavored to recreate my connections. All went well until I tried to set up the connections that require an SSH tunnel. This is a great feature. It allows you to encrypt SQL*Net (or any other kind of traffic) between your laptop and database (or other) server. I&#8217;ll spare you most of the trials I attempted working through the different upgrades and provide the spoiler: it was operator error. I didn&#8217;t set up my SSH tunnel in SQL Developer correctly.</p> <p>I worked out how to do it years ago (using SSH without the assistance of SQL Developer). Worked it out again 18 months ago using SQL Developer. And worked it out again yesterday. Each time I went through the same issues and errors. Like I said, when you don&#8217;t do something frequently, you forget the details. This time, though, I&#8217;m blogging about it, including the error message, so that next year when I Google the error message, I&#8217;ll find my own blog post. It&#8217;s embarrassing how often that happens. Alas, it&#8217;s not just my eyes that are getting old.</p> <h2>Two Flavors</h2> <p>Let&#8217;s say you have a database and you want to encrypt the SQL*Net (or jdbc) traffic from the db server to the client (e.g. SQL Developer, SQLcl). This could be for a variety of reasons and there are a variety of solutions. My colleague and overall Oracle and Linux guru, Rich Soule, is about to publish a white paper with all the details of the full setup. I&#8217;ll link to that whitepaper when it becomes available. In the meantime, I&#8217;m going to present the &#8220;SSH Tunnel&#8221; solution, in two flavors:</p> <p>1. Use SSH command line to establish the SSH Tunnel<br /> 2. Use SQL Developer to establish the SSH Tunnel</p> <p>I&#8217;m also going to include the error message you may receive if you do it incorrectly.</p> <p>In SQL Developer you may see the following:</p> <pre>An error was encountered performing the requested operation: IO Error: Connection reset by peer, connect lapse 73 ms., Authentication lapse 0 ms. Vendor code 17002</pre> <p>In SQLcl, you may see this:</p> <pre>Status : Failure -Test failed: IO Error: Connection reset by peer, connect lapse 3 ms., Authentication lapse 0 ms.</pre> <p>In both cases, you have probably fallen victim to thinking you have followed the SQL Developer help or the many blog posts about how to do this. Unfortunately, most of those, including the help, look at a simple case with only one or two machines involved. In my case, I always have at least 3 and sometimes 4 or 5 machines involved.</p> <h2>Machines involved</h2> <p>The 4 most likely machines involved are</p> <p>1. Laptop with SQLDev or SQLcl (myLaptop or &#8220;localhost&#8221;), potentially outside the firewall.<br /> 2. Firewall (insum.ca) which is port forwarding (potentially from some random port, e.g. 44549 *) to an SSH server<br /> 3. The SSH server (myssh.insum.ca)<br /> 4. The db server (db.insum.ca)</p> <p>You might have an additional firewall between 3 &amp; 4. Aside from more things to configure and troubleshoot, though, it doesn&#8217;t change the steps required for this blog post.</p> <p>Throughout this blog post, I will use the machine names above in the examples.</p> <p>* If you have your firewall forward the standard SSH port (22) you will get a LOT of random hacking attempts. If you assign some non-standard port, those attacks will be greatly reduced. In most cases, the attacker will only have a chance of finding your random port by doing a port scan on your firewall and your firewall will shut it down before it makes it to the port you chose.</p> <p>1 &amp; 4 are required.<br /> If there is a firewall, 3 &amp; 4 are not visible to the outside world.<br /> If any components are collapsed (or don&#8217;t exist), you just use the appropriate machine name. So, if you are using an SSH account on your database server (which isn&#8217;t that great of an idea, unless it&#8217;s all that you have) then you&#8217;ll just configure the SSH things on your equivalent of db.insum.ca instead of on myssh.insum.ca.</p> <h2>Configuring the Firewall</h2> <p>If you&#8217;re going to do this, you should do it right. That means configuring the firewall correctly, locking down the SSH server so that only the appropriate user or users have access, using key files, etc. That said, you&#8217;ll likely have a Linux admin and firewall admin doing at least some of the work. We&#8217;ll cover the Linux steps in another post. Let&#8217;s assume that you have been given the following:</p> <p>1. The firewall server name (or the SSH server name if there is not a firewall involved): insum.ca<br /> 2. The port on insum.ca that is accepting SSH traffic: 44549<br /> 3. The db server name. This is the name that the SSH server can use to see the db: db.insum.ca, not that your laptop doesn&#8217;t need to be able to resolve this host.<br /> 4. The db service name: dev01.insum.ca<br /> 5. The db listener port: 1521<br /> 6. An OS user on the SSH server: sshuser<br /> 7. Either a key file for the OS user or the password for the OS user**. Key file name: my_key_file, Password for sshuser: myPassword</p> <p>Throughout this blog post, I will use the values above in the examples.</p> <p>** Of course, I recommend a passphrase protected key file for this. Describing how to create the key file, set up a no-login SSH account, configure the firewall, etc. is covered in Rich&#8217;s white paper. As all of this opens a significant hole in your firewall, I recommend reading that white paper and working with your firewall and Linux admins to do it correctly.</p> <p>In this blog post, I&#8217;m not covering the server-side setups, but I will show how to set up SQL Dev (and SSH command line) to connect with either a key file or password.</p> <h2>Creating an SSH Tunnel Command Line</h2> <p>Creating an SSH tunnel simply establishes a secure channel between two machines and says where to route the traffic passing through the tunnel. In practice, this is accomplished by defining a port on the local machine to accept traffic and routing it via SSH to an SSH server on another machine. The SSH server then routes the traffic to a machine and port accessible to the SSH server. In our scenario, we also have a firewall that in the mix. The network traffic will ultimately look like this:</p> <p>SQLcl connects to localHost on port 55444 &gt; myLaptop forwards the traffic to the firewall (insum.ca) on port 44549 &gt; the firewall forwards the traffic without inspection to the SSH server (myssh.insum.ca) on port 44549 &gt; myssh.insum.ca forwards the traffic to db.insum.ca on port 1521</p> <p>The firewall is pre-configured to port forward, so as a user, you don&#8217;t need to know the name of myssh.insum.ca. As mentioned above, though, you do need an ssh user on myssh.insum.ca. You can use the following command line to establish this tunnel:</p> <pre>ssh -L 55444:db.insum.ca:1521 -f -C -q -N -i my_key_file sshuser@insum.ca -p 44549</pre> <h2>The Break down</h2> <pre>-L localPort:destination_machine:destination_port localPort This can be any available port on localhost (your laptop). I simply chose 55444 and checked to see it was available. destination_machine The database server destination_port The database listener port -f -C -q -N combine to allow you to do a nologin connection, return to the command line without having to ctl-c, and to continue running after closing the command window. In order to stop your SSH tunnel, you will need to find the process and kill it using ps -ef | grep ssh Locate the process id and kill -9 [pid] -i key file name (if you are using a key file) -p the port your ssh server is using (or that your firewall is port forwarding)</pre> <p>If you don&#8217;t plan to use a key file, you can skip the -i portion:</p> <pre>ssh -L 55444:db.insum.ca:1521 -f -C -q -N sshuser@insum.ca -p 44549</pre> <p>You will be prompted for either the key file pass phrase or the SSH user&#8217;s password.</p> <h2>Voilà, Encryption</h2> <p>That&#8217;s it, now you have an SSH tunnel with encrypted traffic running between myLaptop, port 55444, and myssh.insum.ca and forwarding it unencrypted on port 1521 to db.insum.ca.</p> <p>Keep in mind that anything can use this tunnel: SQLcl, SQL Developer, or literally any other process on your machine that might be aware of this tunnel.</p> <p>To run SQLcl through the SSH tunnel, just &#8220;pretend&#8221; the database is running on localhost port 55444:</p> <pre>./sql anton@localhost:55444/dev01.insum.ca</pre> <p>Of course, once you have this SSH tunnel running, you can do the same thing in SQL Developer. Just create a connection using<br /> host: localhost<br /> port: 55444<br /> service name: dev01.insum.ca</p> <p>Keep in mind, exiting from SQLcl or SQL Developer does not close the SSH tunnel. To do this, you&#8217;ll need to kill the process as described above.</p> <h2>Creating an SSH Tunnel in SQL Developer</h2> <p>If you skipped &#8220;Creating an SSH Tunnel Command Line above&#8221; you may wish to read it just to get an understanding of what is happening. SQL Developer does essentially the same thing as the command line above, but it gives you a user interface to put in all the bits of information. The key is to put the info in the right spots. Rich&#8217;s white paper has lots of pictures of each of these steps. I&#8217;ll capture the minimum here.</p> <p>1. Run SQL Developer<br /> 2. Click View &gt; SSH<br /> 3. At the lower left, right click on SSH Hosts, then choose New SSH Host</p> <p>This will create an SSH Tunnel definition equivalent to the command line in the previous section.</p> <p><img class="alignnone size-medium wp-image-13223" src="https://insum.ca/wp-content/uploads/2018/10/ssh1-262x300.png" alt="" width="262" height="300" srcset="https://insum.ca/wp-content/uploads/2018/10/ssh1-262x300.png 262w, https://insum.ca/wp-content/uploads/2018/10/ssh1-524x600.png 524w, https://insum.ca/wp-content/uploads/2018/10/ssh1-450x515.png 450w, https://insum.ca/wp-content/uploads/2018/10/ssh1.png 692w" sizes="(max-width: 262px) 100vw, 262px" /></p> <p>You can then create a database connection with connection type SSH.</p> <p><img class="alignnone size-medium wp-image-13224" src="https://insum.ca/wp-content/uploads/2018/10/ssh2-300x250.png" alt="" width="300" height="250" srcset="https://insum.ca/wp-content/uploads/2018/10/ssh2-300x250.png 300w, https://insum.ca/wp-content/uploads/2018/10/ssh2-768x640.png 768w, https://insum.ca/wp-content/uploads/2018/10/ssh2-600x500.png 600w, https://insum.ca/wp-content/uploads/2018/10/ssh2-880x733.png 880w, https://insum.ca/wp-content/uploads/2018/10/ssh2-450x375.png 450w, https://insum.ca/wp-content/uploads/2018/10/ssh2.png 1018w" sizes="(max-width: 300px) 100vw, 300px" /></p> <p>When you connect to the database you will be prompted for either the key file pass phrase or the SSH user&#8217;s password. This will open the SSH tunnel. Alternatively, you can open the SSH tunnel by right clicking on the local port forward under SSH Hosts.</p> <p>Once the tunnel is up and running, it is accessible to anything running on your laptop. Hence, you are able to use SQLcl through the SSH tunnel established within SQL Developer, much as you could use SQL Developer through the SSH command line tunnel.</p> <p>Keep in mind, disconnecting from the database in SQL Developer does not close the SSH tunnel. To do this, you&#8217;ll need to right click on the local port forward connection (under SSH Hosts) and disconnect, or exit SQL Developer.</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <h6><em>Photo credit: Yiran Ding, Unsplash</em></h6> <p>The post <a rel="nofollow" href="https://insum.ca/sql-connection-via-encrypted-ssh-tunnel/">SQL Connection via an Encrypted SSH Tunnel</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Anton Nielsen https://insum.ca/?p=13194 Thu Oct 04 2018 07:50:20 GMT-0400 (EDT) APEX Plugins for Beginners http://www.explorer.uk.com/apex-plugins-for-beginners/ <p>One of the great features of APEX is the possibility to import JavaScript plugins and css libraries into the application, just by referencing an external link or uploading a .js file.</p> <p>There are several JavaScript plugins available online that can be used to easily add new functionality to you application. When you add a JavaScript library to a page or application, you usually do the following steps:</p> <p>As an example, I will use a simple but very useful JavaScript plugin to create real-time masks (https://github.com/igorescobar/jQuery-Mask-Plugin)</p> <p>1. Upload the files to the Static Application or Workspace files</p> <p><a href="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-1.png" rel="lightbox[7582]"><img class="aligncenter size-full wp-image-7591" src="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-1.png" alt="" width="794" height="72" srcset="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-1.png 794w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-1-300x27.png 300w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-1-768x70.png 768w" sizes="(max-width: 794px) 100vw, 794px" /></a></p> <p>2. Load these files on application or page level (I will do it page level)</p> <p><a href="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-2.png" rel="lightbox[7582]"><img class="aligncenter size-full wp-image-7584" src="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-2.png" alt="" width="590" height="145" srcset="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-2.png 590w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-2-300x74.png 300w" sizes="(max-width: 590px) 100vw, 590px" /></a></p> <p>3. Call the JavaScript function.</p> <p><a href="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-3.png" rel="lightbox[7582]"><img class="aligncenter size-full wp-image-7585" src="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-3.png" alt="" width="588" height="96" srcset="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-3.png 588w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-3-300x49.png 300w" sizes="(max-width: 588px) 100vw, 588px" /></a></p> <p>Next, I will show how to implement this same functionality as an APEX plugin. The advantages of having APEX plugins comes since no JavaScript knowledge is required to used it, and they can be easily exported and imported across different applications.</p> <ol> <li>Go to Shared Components/Plug-ins and click on create, and then create from scratch.</li> <li>Choose a name and internal name. The internal name is used internally by APEX for identifying the plug-in, it is not displayed.</li> <li>Choose the item type, it is where this plugin will be used.</li> </ol> <p>Now, you must define a PL/SQL anonymous block that contains a function for rendering, validating, execution and Ajax callbacks for the plug-in. This can also be stored in the database.</p> <pre class="brush: php; title: ; notranslate"> /* When you create an item plugin, you must create the following interface. */ PROCEDURE render_mask_field ( p_item in apex_plugin.t_item, p_plugin in apex_plugin.t_plugin, p_param in apex_plugin.t_item_render_param, p_result in out nocopy apex_plugin.t_item_render_result ) IS /* Here we define a plugin attribute used by the developer to set the item mask */ lv_format_mask varchar2(100) := p_item.attribute_01; /* We need to call the following function to allow APEX to map the submitted value to the actual page item in session state. This function returns the mapping name for your page item. If the HTML input element has multiple values then set p_is_multi_value to TRUE.*/ lv_item_name varchar2(1000) := apex_plugin.get_input_name_for_page_item(false); Begin /* This outputs the necessary HTML code to render a text field*/ sys.htp.p('&lt;input id=&quot;'||p_item.name||'&quot; class=&quot;text_field apex-item-text '||p_item.element_css_classes||'&quot; name=&quot;'||lv_item_name||'&quot; size=&quot;'||p_item.element_width||'&quot; type=&quot;text&quot; value=&quot;'||sys.htf.escape_sc(p_param.value)||'&quot; placeholder=&quot;'||p_item.placeholder||'&quot; /&gt;'); /* Here we call the javascript to set the mask to the item $('#P1_TOTAL').mask('000.000.000.000.000,00'); */ apex_javascript.add_onload_code('$(&quot;#'||p_item.name||'&quot;).mask(&quot;'||lv_format_mask||'&quot;)'); End render_mask_field; </pre> <p>4. Now we set the name of render function</p> <p><a href="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-4.png" rel="lightbox[7582]"><img class="aligncenter size-full wp-image-7586" src="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-4.png" alt="" width="808" height="53" srcset="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-4.png 808w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-4-300x20.png 300w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-4-768x50.png 768w" sizes="(max-width: 808px) 100vw, 808px" /></a></p> <p>5. Supported for: We must define where the plugin is supported, where it is available in the Builder, Page Items and/or Interactive Grid Columns. Also if the plug-in is displayed in the Builder as a supported component for desktop and/or mobile.</p> <p><a href="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-5.png" rel="lightbox[7582]"><img class="aligncenter size-full wp-image-7587" src="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-5.png" alt="" width="648" height="169" srcset="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-5.png 648w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-5-300x78.png 300w" sizes="(max-width: 648px) 100vw, 648px" /></a></p> <p>6. Standard Attributes: For Item type plug-ins, identify the attributes that apply to this plug-in:</p> <p><a href="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-6.png" rel="lightbox[7582]"><img class="aligncenter size-large wp-image-7588" src="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-6-1024x134.png" alt="" width="800" height="105" srcset="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-6-1024x134.png 1024w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-6-300x39.png 300w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-6-768x100.png 768w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-6.png 1483w" sizes="(max-width: 800px) 100vw, 800px" /></a></p> <p>7. Now we must save, so APEX will identify the plugin type and add some plugin options, we must create the format mask custom attribute.</p> <p><a href="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-7.png" rel="lightbox[7582]"><img class="aligncenter size-large wp-image-7589" src="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-7-1024x65.png" alt="" width="800" height="51" srcset="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-7-1024x65.png 1024w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-7-300x19.png 300w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-7-768x49.png 768w" sizes="(max-width: 800px) 100vw, 800px" /></a></p> <p>8. JavaScript Files: basically, what are we going to do next is similar of what we do to use javaScript on a page level, upload and load the JavaScript File.</p> <p><a href="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-8.png" rel="lightbox[7582]"><img class="aligncenter size-large wp-image-7590" src="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-8-1024x311.png" alt="" width="800" height="243" srcset="http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-8-1024x311.png 1024w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-8-300x91.png 300w, http://www.explorer.uk.com/wp-content/uploads/2018/09/Image-8-768x233.png 768w" sizes="(max-width: 800px) 100vw, 800px" /></a></p> <p>Finally, we can save and use the plugin. Just create a page item and change the item type to the plugin that we just created.</p> <p>The post <a rel="nofollow" href="http://www.explorer.uk.com/apex-plugins-for-beginners/">APEX Plugins for Beginners</a> appeared first on <a rel="nofollow" href="http://www.explorer.uk.com">Explorer | Award Winning UK Oracle Partner</a>.</p> Devon Page http://www.explorer.uk.com/?p=7582 Wed Oct 03 2018 12:09:55 GMT-0400 (EDT) Oracle 18c Docker Image (on Synology 918+) http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/9VjVL4X2UFo/oracle-18c-docker-image-on-synology-918_3.html <h2>Connect to your synology using ssh</h2>To build the image we have to connect to the synology via ssh. Root privileges would help. Latest at this point you need to enable the SSH service on your synology.<br /><br />I use putty to connect to my synolgy via SSH. Credentials are simply the user name and password of my admin account. To obtain root privileges I use the command:<br /><br /><b>sudo -i</b><br /><br />and key in the admins password again. Done.<br /><b> </b><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-04eGeUB69FE/W7D28h6kUGI/AAAAAAAAJNM/TjQW8x_3nhwoJoTHym_goJVfLwdbQOdIQCLcBGAs/s1600/root.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="305" data-original-width="739" height="165" src="https://4.bp.blogspot.com/-04eGeUB69FE/W7D28h6kUGI/AAAAAAAAJNM/TjQW8x_3nhwoJoTHym_goJVfLwdbQOdIQCLcBGAs/s400/root.png" width="400" /></a></div><h2>Build the image</h2>The script <b>buildDockerImage.sh </b>to create a single instance database image is located in the<br />folder (docker root on volume 4 on my synology):<br /><br /><b>/volume4/docker/docker-images-master/OracleDatabase/SingleInstance/dockerfiles</b><br /><br />Moving to this folder makes life a lot easier.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-jxNCI2R8nww/W7D4td3Uh-I/AAAAAAAAJNY/rulPKDqJuTIfnbXygQ0JVluha9urpx9NQCLcBGAs/s1600/jump.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="91" data-original-width="1184" height="48" src="https://1.bp.blogspot.com/-jxNCI2R8nww/W7D4td3Uh-I/AAAAAAAAJNY/rulPKDqJuTIfnbXygQ0JVluha9urpx9NQCLcBGAs/s640/jump.png" width="640" /></a></div><b> </b><br /><br />Usage of the buildDockerImage.sh is explained in the <a href="https://github.com/oracle/docker-images/blob/master/OracleDatabase/SingleInstance/README.md" target="_blank">readme</a>. For now I would like to create an Oracle 18.3 enterprise edition image, so here we go:<br /><br /><b>&nbsp;./buildDockerImage.sh -v 18.3.0 -e</b><br /><br />TROUBLE:&nbsp;<b> </b>I don't like this kind of messages:<br /><br /><b>Docker version is below the minimum required version 17.09<br />Please upgrade your Docker installation to proceed.</b><br /><br />So upgrading docker does not seem to be an option. For now I grep an <a href="https://github.com/oracle/docker-images/tree/b20993f1521c2d9d06acac0e8f67a50cfc3a8dad" target="_blank">earlier </a>version of the build scripts. Maybe this is not the best possible solution, but it works.<br /><br />SOME SMALLER OBSTACLES: Ok very small<br /><br /><b>-ash: ./buildDockerImage.sh: Permission denied</b><br /><br />Nothing that couldn't be changed with a <b>chmod +x buildDockerImage.sh</b><br /><br />After some time (NOTE: The build process will download all other required images, so there might be some activity in your docker lately) the build will be ready to use.<br /><br /><b> </b><br /><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-ad_Na6_8FT0/W7EUqIfXDkI/AAAAAAAAJNk/XSf1hw9ztiEoiB-MFdnLLWq0hX3jClwVACLcBGAs/s1600/build.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="206" data-original-width="931" height="141" src="https://3.bp.blogspot.com/-ad_Na6_8FT0/W7EUqIfXDkI/AAAAAAAAJNk/XSf1hw9ztiEoiB-MFdnLLWq0hX3jClwVACLcBGAs/s640/build.png" width="640" /></a></div><b> </b><br /><br />It takes some more time if additional downloads are required!<br /><br /><img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/9VjVL4X2UFo" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-3411327094467509490 Wed Oct 03 2018 05:49:00 GMT-0400 (EDT) Getting prepared to create an Oracle 18c Docker Image on my Synology 918+ http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/1UmNydBnovU/getting-prepared-to-create-oracle-18c.html <h2>I'll try to keep it short...</h2>Before you can start you have to install the docker package on your synology (It works on my 918+, but I would strongly recommend some RAM).<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-uM9OgWIr2Ac/W7CpLxJoG3I/AAAAAAAAJMk/zN6BqG9xEFoXvzYe4_LVB3bKbbeshIpMgCLcBGAs/s1600/Docker.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="110" data-original-width="271" src="https://1.bp.blogspot.com/-uM9OgWIr2Ac/W7CpLxJoG3I/AAAAAAAAJMk/zN6BqG9xEFoXvzYe4_LVB3bKbbeshIpMgCLcBGAs/s1600/Docker.png" /></a></div><h2>Starting from scratch...</h2>I want to use the newest oracle 18c database for my development/learning environment and i couldn't find any non commercial docker image. I don't want to use the commercial images, because in my understanding I will have to pay a license fee at some point in time.<br /><br />So lets create a docker image from scratch. Well not 100% from scratch, because there is a <a href="https://github.com/oracle/docker-images/" target="_blank">git repo</a> out there to support us. First of all we need to grep the build files(<b>docker-images-master.zip</b>) from the repo (Simply press the green button and download the Zip). Additionally we need the oracle installation binaries from <a href="https://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html" target="_blank">OTN</a>. Downloading of course requires a free OTN account.<br /><br />So lets pick the Linux X86-64<b>(LINUX.X64_180000_db_home.zip</b>) version.<br /><br /><h2><b>Preparing the synology...</b></h2>Please activate the ssh service on your synology to enable external access(Control Panel / Terminal &amp; SNMP) if not already done.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-JN0VTzmyqRM/W7Dtn40LghI/AAAAAAAAJM0/Ei1sik9s4I4Jr9uVlhFH1IWXtGTaDcQ6QCLcBGAs/s1600/ssh_service.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="174" data-original-width="404" height="137" src="https://2.bp.blogspot.com/-JN0VTzmyqRM/W7Dtn40LghI/AAAAAAAAJM0/Ei1sik9s4I4Jr9uVlhFH1IWXtGTaDcQ6QCLcBGAs/s320/ssh_service.png" width="320" /></a></div><b> </b><br /><br /><b></b>To utilize the predefined script <b>buildDockerImage.sh</b> we need a compatible folder structure accessible on the synology and to store the oracle installation binary inside the correct sub folder.<br /><br />Lets keep it easy, I extract the docker-images-master.zip into the docker root(/volume4/docker) on my synology and copy the file LINUX.X64_180000_db_home.zip into the sub folder<br /><br /><b>/volume4/docker/docker-images-master/OracleDatabase/SingleInstance/dockerfiles/18.3.0</b><br /><br />I use WinSCP as admin to transfer the files from windows<b> </b>to the synology. In my case the docker root is located on volume 4.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-jLhyAvlkr1Q/W7DxEhbrXuI/AAAAAAAAJNA/hn0jHL4QMaEzg3MxStg1ewKQFwW4Q3GTgCLcBGAs/s1600/files.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="475" data-original-width="711" height="213" src="https://4.bp.blogspot.com/-jLhyAvlkr1Q/W7DxEhbrXuI/AAAAAAAAJNA/hn0jHL4QMaEzg3MxStg1ewKQFwW4Q3GTgCLcBGAs/s320/files.png" width="320" /></a></div><br /><img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/1UmNydBnovU" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-3388173724468469475 Wed Oct 03 2018 05:48:00 GMT-0400 (EDT) Acting when the user pastes an image https://apextips.blogspot.com/2018/10/acting-when-user-pastes-image.html I recently saw a question about how to act when someone paste's an image (from clipboard data). There is a plugin that can handle that - to store the image into a table, but I was interested from a purely academic perspective how this would work without using the plugin.<br /><br />So, taking a look on MDN, I can see that there is a 'paste' event that you can listen to. See the documentation here: <a href="https://developer.mozilla.org/en-US/docs/Web/Events/paste">https://developer.mozilla.org/en-US/docs/Web/Events/paste</a>.<br /><br />Ok, so lets give this a whirl! I'm not going to cover loading this into a table/BLOB column, as it's been covered before. What we'll do, is create a region with an image element this will show our image as we paste - this can easily be extended to load it into a canvas, load into a table, whatever your hearts content!<br /><br />Firstly, the region to show what the user pastes:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-atC0sdZMaSI/W7QLPlaOggI/AAAAAAAAI5k/a-ViM7jS4BMqECmNCXgCijrheOH1DBxTQCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-10-02%2B20-19-54.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="408" data-original-width="672" height="242" src="https://3.bp.blogspot.com/-atC0sdZMaSI/W7QLPlaOggI/AAAAAAAAI5k/a-ViM7jS4BMqECmNCXgCijrheOH1DBxTQCLcBGAs/s400/Screenshot%2Bfrom%2B2018-10-02%2B20-19-54.png" width="400" /></a></div><br />Next, we need a dynamic action. This will be a custom event ("paste") with the selector being the body.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-_LGMNNOzPac/W7QLt4VgGoI/AAAAAAAAI5s/q6KtJhSedugX1B_WNTWTDLNbVJ08RK0aACLcBGAs/s1600/Screenshot%2Bfrom%2B2018-10-02%2B20-22-00.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="485" data-original-width="381" height="400" src="https://4.bp.blogspot.com/-_LGMNNOzPac/W7QLt4VgGoI/AAAAAAAAI5s/q6KtJhSedugX1B_WNTWTDLNbVJ08RK0aACLcBGAs/s400/Screenshot%2Bfrom%2B2018-10-02%2B20-22-00.png" width="313" /></a></div><br />Our True Action will be "Execute JavaScript Code" with code resembling:<br /><br /><pre>function setImage(evt){<br /> var dataUrl = evt.target.result;<br /> $('#imageMagick').attr('src', dataUrl);<br />}<br /><br />var pasteEvt = this.browserEvent;<br />var pasteItems =<br /> (pasteEvt.clipboardData || pasteEvt.originalEvent.clipboardData).items;<br /><br />for (index in pasteItems){<br /> <br /> var item = pasteItems[index];<br /> if (item.kind === "file"){<br /> var pasteBlob = item.getAsFile();<br /> if (pasteBlob.type === "image/png"){<br /> var reader = new FileReader();<br /> reader.onload = setImage;<br /> reader.readAsDataURL(pasteBlob);<br /> }<br /> }<br />}<br /></pre><br /><br />Now, when you paste, the image will get loaded into the region, with the img placeholder we set up. Neat! You may wish to cancel event propagation, but I'll leave that up to you to experiment with depending on your needs.<br /><br />If you want to try out this specific example, I have an example:&nbsp; <a href="https://apex.oracle.com/pls/apex/f?p=14882:32">https://apex.oracle.com/pls/apex/f?p=14882:32</a><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-ZlCivnJoRUw/W7QNmMPoKPI/AAAAAAAAI54/tWORze7Mzpg4PRTld36Ce7geGLX2fsvCwCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-10-02%2B20-29-47.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="411" data-original-width="658" height="248" src="https://2.bp.blogspot.com/-ZlCivnJoRUw/W7QNmMPoKPI/AAAAAAAAI54/tWORze7Mzpg4PRTld36Ce7geGLX2fsvCwCLcBGAs/s400/Screenshot%2Bfrom%2B2018-10-02%2B20-29-47.png" width="400" /></a></div><br />Sources used in the making of this example:<br /><br />- <a href="https://developer.mozilla.org/en-US/docs/Web/Events/paste">https://developer.mozilla.org/en-US/docs/Web/Events/paste</a><br />- <a href="https://stackoverflow.com/questions/6333814/how-does-the-paste-image-from-clipboard-functionality-work-in-gmail-and-google-c">https://stackoverflow.com/questions/6333814/how-does-the-paste-image-from-clipboard-functionality-work-in-gmail-and-google-c</a> trent tag:blogger.com,1999:blog-8785176694082881912.post-654333897147206755 Tue Oct 02 2018 20:33:00 GMT-0400 (EDT) Oracle Forms and Reports Modernization – Forms Challenges https://insum.ca/oracle-forms-and-reports-modernization-forms-challenges/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/09/Oracle-Forms-and-Reports-Modernization-–-Issues-with-Forms-100x100.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Oracle Forms and Reports Modernization – Issues with Forms" srcset="https://insum.ca/wp-content/uploads/2018/09/Oracle-Forms-and-Reports-Modernization-–-Issues-with-Forms-100x100.jpg 100w, https://insum.ca/wp-content/uploads/2018/09/Oracle-Forms-and-Reports-Modernization-–-Issues-with-Forms-150x150.jpg 150w, https://insum.ca/wp-content/uploads/2018/09/Oracle-Forms-and-Reports-Modernization-–-Issues-with-Forms-600x600.jpg 600w, https://insum.ca/wp-content/uploads/2018/09/Oracle-Forms-and-Reports-Modernization-–-Issues-with-Forms-300x300.jpg 300w, https://insum.ca/wp-content/uploads/2018/09/Oracle-Forms-and-Reports-Modernization-–-Issues-with-Forms-50x50.jpg 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p>This post kicks off a four-part series of blogs dedicated to Oracle Forms and Reports Modernization. If your company still uses <a href="https://www.oracle.com/technetwork/developer-tools/forms/overview/index.html">Forms applications</a>, is looking to modernize them, but have not yet found a realistic and reliable solution, then this blog series will be well worth your time. <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <h2>Forms and Reports Modernization is doable</h2> <p>Forms modernization doesn’t have to be a huge all-at-once undertaking. There are ways to start off small, with a modest budget and timetable and expand from there. Best of all, there is an Oracle technology available now that can make Forms modernization achievable within a reasonable timetable, no matter how many Forms applications you are running.  <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p><span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span>In this series, we’ll identify the issues with Forms that are holding many companies back in their modernization plans. We’ll then introduce you to Oracle Application Express, a Rapid Application Development platform, we’ll have a detailed look at how Oracle Forms and Oracle APEX work and explain why APEX characteristics make it ideally suited to Oracle Forms and Reports Modernization. Finally, we’ll look at simple and advanced Forms/APEX integrations. <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p><span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p>Enjoy! <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p><span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <h2>A unique predicament</h2> <p>If your company currently uses Oracle Forms Applications, it is probably facing a unique predicament. On one hand, your Forms apps are likely well-maintained by experienced developers. Forms users are efficient with its features. Data-entry and maintenance is a snap even if the look and feel of its applications are from a bygone era.<span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p>On the other hand, the rest of the company likely uses browser-based applications. Much more intuitive, they provide the flow and features that everyone expects from a browser-based experience.<span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p>Your company may be able to put up with this incompatibility, but for how long? The growing under-the-hood difference between Forms and current development software is leading many companies to look for an alternative. To understand the cost of keeping forms applications as-is in your system, let&#8217;s look at some of the challenges it presents to developers.<span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <h2>Challenges from a Development Standpoint</h2> <p>Forms challenges developers in several ways. When running it within a web-browser, developers must strictly control the browser version and parameters. Not an easy task as browsers are often updated. But, even when updated to its latest compatible version and aligned with a proper browser version, Forms&#8217; performance often falls well below an average user’s expectations. Forms predates web-based technology and simply doesn&#8217;t have the page-to-page flow and logic of web applications.  When it comes to Web services or Mobile applications, Forms is that much more complicated to develop.<span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p><span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span>Forms often paired with its brother, a reporting tool called Reports. Compared to later Oracle reporting tools and other data analysis products, it is also getting old. In Reports, adding a view on your data basically means building a new report. This lack of dynamic reporting capability is now almost unheard of.  <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <h2><span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span>Client-Server Technology</h2> <p>Why so complex? Oracle Forms was originally based on client-server technology. Although Oracle continues Forms support, its client-server characteristics continue to be an obstacle to efficiency and cost savings. For example, Jinitiator is the Java virtual machine that allows Forms client applications to run inside web browsers.  Developers must install Jinitiator on each client computer. Likewise, each developer needs development software installed directly on his computer or alternatively, on a Virtual Machine (VM) somewhere in the cloud, before starting their development work. Then, for deployment, the developer must generate executable files and move them into a centralized production environment. Unlike most software today, it isn’t a matter of developing an application and then making it accessible or downloadable from the web. Developer instances are treated individually during upgrades or patches.</p> <p>All this represents a big chunk of a developer&#8217;s time and increasing costs as the company grows.<span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}">  And, w</span>e are not even talking about the complex software and infrastructure required on the web servers to run Oracle Forms on a company&#8217;s environments.</p> <h2>Holding back Oracle Forms and Reports Modernization</h2> <p>These significant technical limitations are part of the reason many companies using Forms applications are not connecting them to the web or to web services or even updating them (Yikes!). Without a doubt, they are missing out on what web technologies have to offer.<span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p>Another important reason why companies hesitate to move away from Forms is the perception that the undertaking would be massive, drawn-out and expensive. As mentioned earlier, some companies have hundreds of Forms, each with their own particularities. To open and rewrite every one of them would surely be too difficult. <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <h2>PL/SQL vs Java</h2> <p>This perception may have a lot to do with Oracle’s move from PL/SQL-based programming (which is at the heart of Forms) and Java-based programming. Oracle brought in Java object-based programming to move towards connection to and use of the world wide web for Oracle products in the early 2000s. The move was judicious but Java-based development technology is recognized as complex, particularly for PL/SQL Forms developers. In fact, it is another paradigm altogether.<span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <h2>ADF</h2> <p>Over the years, Oracle has proposed a couple of Java-based replacement solutions for Forms users, including a development platform called ADF.  It didn’t catch on too well with Forms developers. For a more detailed explanation, see our blog called “<a href="https://insum.ca/simplified-cost-effective-development-in-ebs-think-oracle-apex/">Simplified, Cost Effective Development In EBS – Think Oracle APEX</a>” <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <h2>Designer 2000</h2> <p>But Java wasn’t the only complication in the Forms story. Forms and Reports were also included in Oracle’s “CASE tool” based information system generator called Oracle Designer 2000. Designer is a top to bottom business system generation tool. It includes business process modeling, systems analysis modeling, systems design and application development. Forms development in this system contains automation. The resulting Forms applications have several times more code than a manually generated Forms application. What’s more, changing a Form produced with this system brings you back to the very beginning of the modeling process. Not many developers still use it.     <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p>Web-based development eventually superseded these systems. Designer 2000 is now de-supported by Oracle. Unfortunately, it leaves companies that developed Forms this way with the additional burden of dealing with that all that extra code if they wish to modernize or migrate away from their Forms applications. <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <h2> <b>APEX for Oracle Forms and Reports Modernization</b><span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></h2> <p>Businesses need to know there’s a solution that addresses all these issues. Oracle Application Express (APEX), a Rapid Application Development platform, is firmly rooted in web technology and yet shares many similarities with Forms, not the least of which is that it is PL/SQL based. <span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p><span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span>Today, thanks to a well-thought-out development plan that includes extensive web-service support and ease of use, as well as continuing (I would even say growing) Oracle support, APEX is now the very best alternative for Oracle Forms and Reports Modernization.<span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p><span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span>In my next installment, I’ll get into the details about the surprising parallels between Forms and Oracle APEX.<span data-ccp-props="{&quot;134233117&quot;:true,&quot;134233118&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:240}"> </span></p> <p>&nbsp;</p> <p>See also</p> <p><a href="https://insum.ca/oracle-forms-conversion-to-oracle-apex-where-to-start/">Oracle Forms Conversion to Oracle APEX &#8211; Where to Start</a></p> <p><a href="https://insum.ca/oracle-forms-modernization-journey/">The Oracle Forms Modernization Journey</a></p> <p><a href="https://insum.ca/time-modernize-oracle-forms-reports-application/">How You Know It&#8217;s Time To Modernize Your Oracle Forms &amp; Reports App</a></p> <p><a href="https://insum.ca/oracle-forms-keep-or-migrate/">Debating Whether to Keep Oracle Forms or to Migrate From It?</a></p> <p>&nbsp;</p> <p>The post <a rel="nofollow" href="https://insum.ca/oracle-forms-and-reports-modernization-forms-challenges/">Oracle Forms and Reports Modernization – Forms Challenges</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Francis Mignault https://insum.ca/?p=13131 Tue Oct 02 2018 08:30:23 GMT-0400 (EDT) ORA-28014: cannot drop administrative users https://oracleinsights.blogspot.com/2018/10/ora-28014-cannot-drop-administrative.html <div dir="ltr" style="text-align: left;" trbidi="on"> Just so I don't forget :)<br /> <br /> <pre style="border: 1px solid rgba(0, 0, 0, 0.0980392); box-sizing: border-box; color: #2b2b2b; font-family: monospace, serif; font-size: 15px; hyphens: none; line-height: 1.6; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 12px; vertical-align: baseline; word-wrap: normal;"><code style="border: 0px; font-family: monospace, serif; font-style: inherit; font-weight: inherit; hyphens: none; line-height: 1.6; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">SQL&gt; drop user apex_180100 cascade; Error starting at line : 1 in command - drop user apex_180100 cascade Error report - ORA-28014: cannot drop administrative users SQL&gt; </code><code style="border: 0px; font-family: monospace, serif; font-style: inherit; line-height: 1.6; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><b style="background-color: #fff2cc;">alter session set "_oracle_script"=true;</b></code><code style="border: 0px; font-family: monospace, serif; font-style: inherit; font-weight: inherit; hyphens: none; line-height: 1.6; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> Session altered. SQL&gt; drop user apex_180100 cascade; User APEX_180100 dropped. </code></pre> <br /> <div> <br /></div> </div> Mark Lancaster tag:blogger.com,1999:blog-869579236085438805.post-8814060726881721653 Mon Oct 01 2018 07:34:00 GMT-0400 (EDT) Criando colunas de auditoria em tabelas Oracle http://desenvolvedorapex.blogspot.com/2018/09/criando-colunas-de-auditoria-em-tabelas.html Olá pessoal,<br /><br />é comum a inclusão de colunas de auditoria quando se cria um sistema.<br /><br />As colunas de auditoria são as que armazenam informações sobre a criação e alteração do registro que se encontra na tabela. Os nomes de coluna mais comuns em Português são: CRIADO_POR, CRIADO_EM, ALTERADO_POR e ALTERADO_EM.<br /><br />Primeiramente temos que criar essas 4 colunas em todas as tabelas (Caso já não existam).<br /><br />Calma! Você não precisará entrar em todas as suas dezenas (ou centenas) de tabelas e alterar.<br /><br />Segue um script para fazer esta atividade de forma automática.<br /><br />Copie e cole o script abaixo no Comandos SQL e pressione "Executar" (ou "Run")<br /><br /><i>--------------------INICIO SCRIPT---------------------</i><br /><i>----------------Inclui colunas de auditoria-------------</i><br /><i>BEGIN</i><br /><i><br /></i><i>FOR cur IN (select * from user_tables) LOOP</i><br /><i><br /></i><i>&nbsp; &nbsp;EXECUTE IMMEDIATE 'alter table ' || cur.table_name || ' add (CRIADO_POR VARCHAR2(255))';</i><br /><i>&nbsp; &nbsp;EXECUTE IMMEDIATE 'alter table ' || cur.table_name || ' add (CRIADO_EM DATE)';</i><br /><i>&nbsp; &nbsp;EXECUTE IMMEDIATE 'alter table ' || cur.table_name || ' add (ALTERADO_POR VARCHAR2(255))';</i><br /><i>&nbsp; &nbsp;EXECUTE IMMEDIATE 'alter table ' || cur.table_name || ' add (ALTERADO_EM DATE)';</i><br /><i><br /></i><i>END LOOP;</i><br /><i><br /></i><i>END;</i><br /><i>------------------------FIM SCRIPT-------------------------</i><br /><div class="MsoNormal"><br />Ao final da execução, aparecerá uma mensagem de sucesso, conforme imagem abaixo.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-R-UgeF-M84M/W7FhaxLm80I/AAAAAAAAB1o/J8l62LnJRygEadZyGF0rIwzeibRgUujAACLcBGAs/s1600/Script%2BAdiciona%2BColunas%2Bde%2Bauditoria.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="920" data-original-width="1320" height="446" src="https://4.bp.blogspot.com/-R-UgeF-M84M/W7FhaxLm80I/AAAAAAAAB1o/J8l62LnJRygEadZyGF0rIwzeibRgUujAACLcBGAs/s640/Script%2BAdiciona%2BColunas%2Bde%2Bauditoria.JPG" width="640" /></a></div><br /><br />Para ter certeza de que deu certo, vá ao Browser de Objetos e confira se as colunas foram criadas.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-tDhcxpmlmR8/W7FiX0PdaNI/AAAAAAAAB1w/gb4XzQq9BKssiQ4OrMKhm9zb7hEonmEwwCLcBGAs/s1600/Browser%2Bde%2Bobjetos.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="943" data-original-width="1460" height="411" src="https://2.bp.blogspot.com/-tDhcxpmlmR8/W7FiX0PdaNI/AAAAAAAAB1w/gb4XzQq9BKssiQ4OrMKhm9zb7hEonmEwwCLcBGAs/s640/Browser%2Bde%2Bobjetos.JPG" width="640" /></a></div><br /><br />A melhor maneira de garantir que suas colunas de auditoria serão preenchidas corretamente, é por meio de trigger no banco de dados.<br /><br />Para facilitar o trabalho, segue um script que cria as triggers para as tabelas com tamanho menor que 26 (<b>As tabelas com tamanho maior que 26 deverão ser criadas manualmente</b>).<br /><br />O script deve ser executado no Comandos SQL também.<br /><br /><span style="color: red;">Observação: O trecho que utiliza APEX$SESSION funciona apenas a partir do Apex 5, portanto deve ser alterado para versões anteriores do Apex.</span><br /><br /></div><div class="MsoNormal"><i>--------------------INICIO SCRIPT---------------------</i><br /><i>DECLARE</i><br /><i>&nbsp; &nbsp;v_comando VARCHAR2(4000);</i><br /><i><br /></i><i>BEGIN</i><br /><i><br /></i><i>FOR cur IN (select * from user_tables where length(table_name) &lt;=26) LOOP&nbsp;</i><br /><i>&nbsp; &nbsp;v_comando := 'create or replace trigger BIU_'||cur.table_name||' before insert or update on "'||cur.table_name||'"&nbsp;</i><br /><i>for each row&nbsp;</i><br /><i>begin</i><br /><i>&nbsp; &nbsp; if inserting then</i><br /><i>&nbsp; &nbsp; &nbsp; &nbsp; :new.criado_em := sysdate;</i><br /><i>&nbsp; &nbsp; &nbsp; &nbsp; :new.criado_por := nvl(sys_context(''APEX$SESSION'',''APP_USER''),user);</i><br /><i>&nbsp; &nbsp; end if;</i><br /><i>&nbsp; &nbsp; :new.alterado_em := sysdate;</i><br /><i>&nbsp; &nbsp; :new.alterado_por := nvl(sys_context(''APEX$SESSION'',''APP_USER''),user);</i><br /><i>end;';</i><br /><i>htp.p(v_comando);</i><br /><i>EXECUTE IMMEDIATE v_comando;</i><br /><i><br /></i><i>END LOOP;</i><br /><i><br /></i><i>END;</i><br /><i>------------------------FIM SCRIPT-------------------------</i></div><div class="MsoNormal"><i><br /></i>Verifique se o comando foi executado corretamente. Você pode ir também ao Browser de Objetos e conferir se as triggers foram criadas sem problemas.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-uJEZar15EEQ/W7FlOd_EPBI/AAAAAAAAB2I/FJmByUPEZ9AaG1UkU-wBXOWA1ZTXsM8jACLcBGAs/s1600/Script%2Btriggers.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="948" data-original-width="1462" height="414" src="https://1.bp.blogspot.com/-uJEZar15EEQ/W7FlOd_EPBI/AAAAAAAAB2I/FJmByUPEZ9AaG1UkU-wBXOWA1ZTXsM8jACLcBGAs/s640/Script%2Btriggers.JPG" width="640" /></a></div><i><br /></i>Para verificar quais tabelas devem ter as triggers criadas&nbsp; manualmente, execute o SELECT abaixo no Comandos SQL.</div><div class="MsoNormal"><span lang="EN-US" style="color: #1f497d; mso-fareast-language: EN-US;"><br /></span><span lang="EN-US" style="color: #1f497d; mso-fareast-language: EN-US;">select * from user_tables where length(table_name) &gt;26<o:p></o:p></span></div><div class="MsoNormal"><br /><br />Utilize o CREATE TRIGGER abaixo no Comandos SQL substituindo as tags &lt;&lt;nome_tabela_abreviada&gt;&gt; e &lt;&lt;nome_tabela&gt;&gt; pelo nome desejado.<br /><br /><i>create or replace trigger BIU_&lt;&lt;nome_tabela_abreviado&gt;&gt; before insert or update on &lt;&lt;nome_tabela&gt;&gt;&nbsp;</i><br /><i>for each row&nbsp;</i><br /><i>begin</i><br /><i>&nbsp; &nbsp; if inserting then</i><br /><i>&nbsp; &nbsp; &nbsp; &nbsp; :new.criado_em := sysdate;</i><br /><i>&nbsp; &nbsp; &nbsp; &nbsp; :new.criado_por := nvl(sys_context(''APEX$SESSION'',''APP_USER''),user);</i><br /><i>&nbsp; &nbsp; end if;</i><br /><i>&nbsp; &nbsp; :new.alterado_em := sysdate;</i><br /><i>&nbsp; &nbsp; :new.alterado_por := nvl(sys_context(''APEX$SESSION'',''APP_USER''),user);</i><br /><i>end;&nbsp;</i><br /><br />Pronto! Agora basta inserir algum registro por algum formulário ou fazer algum comando DML diretamente no banco que as colunas serão preenchidas.<br /><br />Espero que tenha gostado!<br /><br />Até a próxima.</div> Anderson Ferreira tag:blogger.com,1999:blog-5150514048465222719.post-6197220533737864680 Sun Sep 30 2018 20:12:00 GMT-0400 (EDT) SQL*Plus, Node and Docker https://apextips.blogspot.com/2018/09/sqlplus-node-and-docker.html This post is a continuation of my post from earlier in the week, in which <a href="https://apextips.blogspot.com/2018/09/setting-up-sqlplus-with-help-of-oracle.html">I showed how to set up SQL*Plus, through a docker container that Oracle provides in their container registry.</a><br /><br />In that post, I set up the sqlplus command through an alias. Almost all examples I've seen in the past use an alias when setting up a command line program that is in effect a docker container.<br /><br />However, I have an extension in VSCode that I use that compiles my code which in effect is calling sqlplus and running my script. Even though I was able to connect in gnome-terminal and use SQL*Plus effectively, in my extension, no output was coming through.<br /><br />My code looked like this:<br /><br /><pre>var ChildProcess = require('child_process');</pre><pre>&nbsp;</pre><pre>var sqlplusArgs = ["vmtest/vmtest@//192.168.0.104", "@test.sql"];</pre><pre>var sqlplusProcess = ChildProcess.spawn("sqlplus", sqlplusArgs);<br /><br />sqlplusProcess.stdout.on('data', (data) =&gt; {<br /> console.log( data.toString() );<br />});<br /></pre><br /><br />The first issue here is this is only set up to display the standard output channel - we need to also give the user feedback when any errors occurred. So we can tweak this slightly to become:<br /><br /><pre>var ChildProcess = require('child_process'); </pre><pre>&nbsp;</pre><pre>var sqlplusArgs = ["vmtest/vmtest@//192.168.0.104", "@test.sql"]; </pre><pre>var sqlplusProcess = ChildProcess.spawn("sqlplus", sqlplusArgs);<br /><br />function printOutput(data){<br /> console.log(data.toString());<br />}<br /><br />sqlplusProcess.stdout.on('data', printOutput);<br />sqlplusProcess.stderr.on('data', printOutput);<br /></pre><br /><br />So just a reminder, the alias command looked like this in my previous post:<br /><br />alias sqlplus='docker run -ti --rm container-registry.oracle.com/database/instantclient sqlplus'<br /><br />So now when we try and run this little node demo program, we get an exception:<br /><br /><br /><pre>events.js:167<br /> throw er; // Unhandled 'error' event<br /> ^<br /><br />Error: spawn sqlplus ENOENT<br /></pre><br /><br />So, it looks like node isn't finding the alias we set up, and per this logged issue: <a href="https://github.com/nodejs/node/issues/3916">https://github.com/nodejs/node/issues/3916</a>, bash doesn't expand aliases in non interactive shells.<br /><br />Ok, so instead of using an alias we should consider wrapping our docker command in a shell script. So we end up with a script per:<br /><br /><pre>#!/bin/bash<br />docker run \<br /> -it \<br /> --rm \<br /> container-registry.oracle.com/database/instantclient sqlplus \<br /> "$@"<br /></pre><br /><br />I've already set this up on my path and removed my alias, so I can go ahead and try my little node program again. This time, we get the following error:<br /><br />the input device is not a TTY<br /><br />This is an easy fix. In our original docker run command we passed in the arguments -it. The -i is for interactive and the -t is for TTY. So we can safely go ahead and remove that from our shell script. So, line 3 in the shell script above would just read: -i \.<br /><br />At this point, we are not entirely ready, because with SQL*Plus, we want to be able to compile scripts, and suppose I'm within the folder: /home/trent/Projects/blog/ and have a script test.sql. If I launch sqlplus, it won't have access to those files, which you will see if you try to run:<br /><br /><pre>sqlplus vmtest/vmtest@//192.168.0.104/xe @test.sql<br /><br />Copyright (c) 1982, 2016, Oracle. All rights reserved.<br /><br />Connected to:<br />Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production<br /><br />SP2-0310: unable to open file "test.sql"<br />SQL&gt;<br /></pre><br /><br />So this solution to this in 2 parts. Firstly, exposing your files into the container. Personally, I think it makes enough sense that you should just expose your entire home folder where, at least for me, is most likely where all my source folders will be stored. So, I append the following flag to my docker run command:<br /><br /><pre>-v $HOME:$HOME.</pre><br />This alone will be perfect if I want to compile with absolute paths. e.g.<br /><br /><pre>sqlplus vmtest/vmtest@//192.168.0.104/xe @/home/trent/Projects/blog/test.sql</pre><br />But usually you will probably just be specifying a relative path. So, we need to set the working directory. The docker run command has a flag for this too, so we can add in:<br /><br /><pre>-w $(pwd)</pre><br />So finally, the docker run command in our shell script would look like:<br /><br /><pre>#!/bin/bash<br />docker run \<br /> -i \<br /> --rm \<br /> -v $HOME:$HOME \<br /> -w $(pwd) \<br /> container-registry.oracle.com/database/instantclient sqlplus \<br /> "$@"<br /></pre><br /><br />So that brings us to the next point. Performance.<br /><br />You are surely aware by now that Oracle now has a new command line tool for connecting to the database named SQLcl, which is effectively a drop in replacement for SQL*Plus.<br /><br />So after my last post, there was a reply from Jeff Smith:<br /><br /><blockquote class="twitter-tweet" data-conversation="none" data-lang="en"><div dir="ltr" lang="en">You could just grab the 20mb <a href="https://twitter.com/oraclesqlcl?ref_src=twsrc%5Etfw">@oraclesqlcl</a> ...even easier/faster</div>— Jeff Smith 🥃 ☜ (@thatjeffsmith) <a href="https://twitter.com/thatjeffsmith/status/1045424802775937024?ref_src=twsrc%5Etfw">September 27, 2018</a></blockquote><script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script> <br /><br />One of the reasons I advocate having SQL*Plus installed is because of the plugin I already mentioned that I have in VSCode (there are similar ones for Atom and Sublime) makes use of SQL*Plus (or SQLcl) to connect to the database and compile the active script/file. Unlike say SQL Developer, the connection isn't kept alive. It's purely launching SQL*Plus (or SQLcl) to compile the script, and then exits. And the startup time is so much faster with SQL*Plus. From my experience, SQL*Plus is well under 1 second to startup and run the script, where SQLcl takes at least 3 seconds or more.<br /><br />Since this post, and the last, were about running SQL*Plus through a docker container, a co-worker replied:<br /><br /><blockquote class="twitter-tweet" data-conversation="none" data-lang="en"><div dir="ltr" lang="en">I’ve experienced this. It does make a big difference. <br />Trent, even through docker sqlplus is faster? That surprises me</div>— Jorge Rimblas (@rimblas) <a href="https://twitter.com/rimblas/status/1045434761576153089?ref_src=twsrc%5Etfw">September 27, 2018</a></blockquote><script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script> <br />In my initial testing, it was still very fast to startup. But don't take my word for it, let's get some hard facts. We can make use of the time command to startup each environment, immediately issue an exit statement to see how long the round trip takes in each.<br /><br />1. SQL*Plus installed natively<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-XUwugBFNqNw/W7Dp0SPuUwI/AAAAAAAAI5M/U6dBetAwA5AKKCVVZjHf3RZJV3vrtp3kQCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-09-30%2B11-19-54.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="404" data-original-width="1333" height="192" src="https://2.bp.blogspot.com/-XUwugBFNqNw/W7Dp0SPuUwI/AAAAAAAAI5M/U6dBetAwA5AKKCVVZjHf3RZJV3vrtp3kQCLcBGAs/s640/Screenshot%2Bfrom%2B2018-09-30%2B11-19-54.png" width="640" /></a></div><br />3 tests produced: 0.010s, 0.003s, 0.009s (in that order) for user time<br /><br /><br />2. SQL*Plus running through a Docker container<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-BxjoRoRRm9c/W6_cxk0s-ZI/AAAAAAAAI5A/YBdYhLhu4dI5YebcmVpbREo_rRVi4tXEwCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-09-29%2B16-12-35.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="395" data-original-width="1406" height="178" src="https://4.bp.blogspot.com/-BxjoRoRRm9c/W6_cxk0s-ZI/AAAAAAAAI5A/YBdYhLhu4dI5YebcmVpbREo_rRVi4tXEwCLcBGAs/s640/Screenshot%2Bfrom%2B2018-09-29%2B16-12-35.png" width="640" /></a></div><br />3 tests produced: 0.073s, 0.065s, 0.065s (in that order) for user time (a little longer than a native installation though probably not enough of a difference to be noticeable by the user) <br /><br />3. SQLcl <br /><br /><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-ufxW3fg0G0M/W6_cD_N4AJI/AAAAAAAAI44/C91fA99D7ZYrMFYFPnWgC16mrJl1zTD3gCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-09-29%2B16-09-20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="430" data-original-width="1389" height="198" src="https://1.bp.blogspot.com/-ufxW3fg0G0M/W6_cD_N4AJI/AAAAAAAAI44/C91fA99D7ZYrMFYFPnWgC16mrJl1zTD3gCLcBGAs/s640/Screenshot%2Bfrom%2B2018-09-29%2B16-09-20.png" width="640" /></a></div><br />3 tests produced: 3.513s, 3.399s, 3.560s (in that order) for user time<br /><br />So as you can see, not a lot of difference with SQL*Plus installed natively or by running through a container. trent tag:blogger.com,1999:blog-8785176694082881912.post-7681299341563207933 Sun Sep 30 2018 11:52:00 GMT-0400 (EDT) A brandnew infrastructure http://feedproxy.google.com/~r/LearningApexTheHardWay/~3/GJDiDF32dfU/a-brandnew-infrastructure.html <div dir="ltr" style="text-align: left;" trbidi="on"><h2 style="text-align: left;">The underlying Idea</h2><div style="text-align: left;">It has been a while since I last posted and I have changed my development Infrastructure a lot since. I started a new approach and after some failures I thought it might be a good idea to write a new blog in regards to my dev/learning environment. <br />Instead of running a development environment including APEX&nbsp; and an oracle database on my various laptops, I decided to create some kind of a server that can be accessed from nearly everywhere. In addition I would like to utilize oracles 18th editions.</div><h2 style="text-align: left;">Target environment</h2><ul style="text-align: left;"><li>my new NAS Synology 918+&nbsp; (OK, I pimped the RAM to <a href="https://idomix.de/synology-diskstation-ds918-ram-upgrade-8-12-16-gb" target="_blank">16GB</a> (thanks Dominik))</li><li>Docker (I have to learn a lot)</li><li>Oracle 18c on Oracle Linux</li><li>APEX 18.2 (Brand new on the 28 September 2018. In fact I failed with)</li><li>Accessible through my Fritz Box 7490</li></ul><b>Not</b> being a server manager, docker expert and a DBA, this will be a learning experience for me as well. Supporting hints are welcome at any time.</div><img src="http://feeds.feedburner.com/~r/LearningApexTheHardWay/~4/GJDiDF32dfU" height="1" width="1" alt=""/> Martin M. tag:blogger.com,1999:blog-7559944140284887244.post-2728007797075777851 Sun Sep 30 2018 06:39:00 GMT-0400 (EDT) Announcing Oracle APEX 18.2 https://blogs.oracle.com/apex/announcing-oracle-apex-182 <p>&nbsp;</p> <p>Oracle Application Express (APEX) 18.2 is now generally available! APEX enables you to develop, design and deploy beautiful, responsive, data-driven desktop and mobile applications using only a browser. APEX 18.1 was a dramatic step forward in the ease of integration with remote data sources, and the easy inclusion of robust, high-quality application features.&nbsp; Building upon this success, APEX 18.2 introduces a number of features as well as improves the overall quality of APEX.</p> <p>Some of the improvements to Oracle APEX 18.2 include:</p> Create Page Wizards <p>In Oracle APEX 18.2, the Create Page wizard has been extended to enable the creation of application pages for Side-by-Side Master Detail and a Dashboard.&nbsp; The Side-by-Side master detail form creates a single page master detail utilizing a side by side layout and report regions with modal edit windows.&nbsp; The dashboard&nbsp;enables the creation of a first-cut dashboard based on sample data which you can later customize using Page Designer.&nbsp;</p> Font APEX <p><a href="https://apex.oracle.com/fontapex" target="_blank">Font APEX</a> is a collection of over 1,000 high-quality icons, many specifically created for use in business applications.&nbsp; Font APEX in APEX 18.1 included a new set of high-resolution 32 x 32 icons which included much greater detail and the correctly-sized font would be automatically selected for you, based upon where it is used in your APEX application.&nbsp; Oracle APEX 18.2 also includes the ability to update Font APEX stylesheets and font files, independent of Oracle APEX releases.&nbsp; Font APEX is now available on <a href="https://oracle.github.io/font-apex/" target="_blank">GitHub</a>.</p> <span><span>Reduced Downtime</span></span> <p>In an era of always-available cloud services and enterprise applications, particular focus has been given in APEX 18.2 to significantly reduce the outage time of an APEX upgrade. A multi-phase reduced-downtime upgrade approach was first introduced in APEX 18.1, which resulted in a significant decrease in the overall outage incurred during the upgrade process.&nbsp; In APEX 18.2, this <a href="https://docs.oracle.com/database/apex-18.2/HTMIG/maximizing-uptime-during-an-application-express-upgrade.htm#HTMIG-GUID-DE1EEE34-E79A-4937-8B5E-B405BE23F1B5" target="_blank">multi-phase upgrade process</a> has been further refined, resulting in an even greater reduction in the already brief outage period for an APEX upgrade.&nbsp;&nbsp;</p> <span><span>Simplified Service Request &amp; Creation</span></span> <p>The workflow to request an APEX workspace has been dramatically simplified, improving the experience for users trying Oracle APEX for the first time.&nbsp; Additional settings have been added to the APEX configuration so that, out-of-the-box, reasonable defaults are used during the workspace request process, and very little information is required to get up and running with APEX!</p> Sample Data Set Enhancements <p>To assist in the learning process, Oracle APEX includes a number of data sets which can be easily installed and used for application creation.&nbsp; In APEX 18.2, the Create Application wizard will be automatically populated with components built on top of the datasets.&nbsp; Additionally, some of the datasets have been expanded to include data in other languages, including&nbsp;<span><span>Chinese, Czech, French, German, Japanese, Korean, Polish, Russian, and Spanish.</span></span></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>As in every APEX release, a number of enhancements and and bugs fixes have been made to the productivity and sample applications.&nbsp; Additionally, more than 150 bugs have been fixed in APEX 18.2, resulting in even higher quality and stability for APEX environments.</p> <p>&nbsp;</p> Additional Information <p>Application Express (APEX) is the low code rapid app dev platform which can run in any Oracle Database and is included with every Oracle Database Cloud Service.&nbsp; APEX, combined with the Oracle Database, provides a fully integrated environment to build, deploy, maintain and monitor data-driven business applications that look great on mobile and desktop devices.&nbsp; To learn more about Oracle Application Express, visit&nbsp;<a href="https://apex.oracle.com" target="_blank">apex.oracle.com</a>. &nbsp;To learn more about Oracle Database Cloud, visit&nbsp;<a href="https://cloud.oracle.com/database" target="_blank">cloud.oracle.com/database</a>.&nbsp;</p> Joel Kallman https://blogs.oracle.com/apex/announcing-oracle-apex-182 Fri Sep 28 2018 16:44:00 GMT-0400 (EDT) Announcing Oracle APEX 18.2 https://blogs.oracle.com/apex/announcing-oracle-apex-182 <p>&nbsp;</p> <p>Oracle Application Express (APEX) 18.2 is now generally available! APEX enables you to develop, design and deploy beautiful, responsive, data-driven desktop and mobile applications using only a browser. APEX 18.1 was a dramatic step forward in the ease of integration with remote data sources, and the easy inclusion of robust, high-quality application features.&nbsp; Building upon this success, APEX 18.2 introduces a number of features as well as improves the overall quality of APEX.</p> <p>Some of the improvements to Oracle APEX 18.2 include:</p> Create Page Wizards <p>In Oracle APEX 18.2, the Create Page wizard has been extended to enable the creation of application pages for Side-by-Side Master Detail and a Dashboard.&nbsp; The Side-by-Side master detail form creates a single page master detail utilizing a side by side layout and report regions with modal edit windows.&nbsp; The dashboard&nbsp;enables the creation of a first-cut dashboard based on sample data which you can later customize using Page Designer.&nbsp;</p> Font APEX <p><a href="https://apex.oracle.com/fontapex" target="_blank">Font APEX</a> is a collection of over 1,000 high-quality icons, many specifically created for use in business applications.&nbsp; Font APEX in APEX 18.1 included a new set of high-resolution 32 x 32 icons which included much greater detail and the correctly-sized font would be automatically selected for you, based upon where it is used in your APEX application.&nbsp; Oracle APEX 18.2 also includes the ability to update Font APEX stylesheets and font files, independent of Oracle APEX releases.&nbsp; Font APEX is now available on <a href="https://oracle.github.io/font-apex/" target="_blank">GitHub</a>.</p> <span><span>Reduced Downtime</span></span> <p>In an era of always-available cloud services and enterprise applications, particular focus has been given in APEX 18.2 to significantly reduce the outage time of an APEX upgrade. A multi-phase reduced-downtime upgrade approach was first introduced in APEX 18.1, which resulted in a significant decrease in the overall outage incurred during the upgrade process.&nbsp; In APEX 18.2, this <a href="https://docs.oracle.com/database/apex-18.2/HTMIG/maximizing-uptime-during-an-application-express-upgrade.htm#HTMIG-GUID-DE1EEE34-E79A-4937-8B5E-B405BE23F1B5" target="_blank">multi-phase upgrade process</a> has been further refined, resulting in an even greater reduction in the already brief outage period for an APEX upgrade.&nbsp;&nbsp;</p> <span><span>Simplified Service Request &amp; Creation</span></span> <p>The workflow to request an APEX workspace has been dramatically simplified, improving the experience for users trying Oracle APEX for the first time.&nbsp; Additional settings have been added to the APEX configuration so that, out-of-the-box, reasonable defaults are used during the workspace request process, and very little information is required to get up and running with APEX!</p> Sample Data Set Enhancements <p>To assist in the learning process, Oracle APEX includes a number of data sets which can be easily installed and used for application creation.&nbsp; In APEX 18.2, the Create Application wizard will be automatically populated with components built on top of the datasets.&nbsp; Additionally, some of the datasets have been expanded to include data in other languages, including&nbsp;<span><span>Chinese, Czech, French, German, Japanese, Korean, Polish, Russian, and Spanish.</span></span></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>As in every APEX release, a number of enhancements and and bugs fixes have been made to the productivity and sample applications.&nbsp; Additionally, more than 150 bugs have been fixed in APEX 18.2, resulting in even higher quality and stability for APEX environments.</p> <p>&nbsp;</p> Additional Information <p>Application Express (APEX) is the low code rapid app dev platform which can run in any Oracle Database and is included with every Oracle Database Cloud Service.&nbsp; APEX, combined with the Oracle Database, provides a fully integrated environment to build, deploy, maintain and monitor data-driven business applications that look great on mobile and desktop devices.&nbsp; To learn more about Oracle Application Express, visit&nbsp;<a href="https://apex.oracle.com" target="_blank">apex.oracle.com</a>. &nbsp;To learn more about Oracle Database Cloud, visit&nbsp;<a href="https://cloud.oracle.com/database" target="_blank">cloud.oracle.com/database</a>.&nbsp;</p> Joel Kallman https://blogs.oracle.com/apex/announcing-oracle-apex-182 Fri Sep 28 2018 16:44:00 GMT-0400 (EDT) Oracle Forms to APEX IDE Transition http://www.grassroots-oracle.com/2018/09/oracle-forms-to-apex-ide-transition.html If you would like a good high level run-down on why Oracle APEX is a great choice to modernise Oracle Forms, have a read of <a href="https://apex.oracle.com/en/solutions/oracle-forms/" target="_blank">this</a>.<br /><br />After listening in on the AskTom <a href="https://asktom.oracle.com/pls/apex/f?p=100:551:::NO:551:P551_CLASS_ID,P551_STUDENT_ID:4825&amp;cs=1B45460A1FACDBB9462CD282156412A51" target="_blank">Office Hours</a> on this topic (make sure you also read the chat transcript), I had a few ideas for posts to help Forms developers transition to APEX, before my Forms knowledge gets <i>too </i>stale!<br /><br />If you put the Forms &amp; APEX IDEs together, it's not hard to see they're sown from the same cloth, so to speak.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-0zxnUih8lik/W6rYIZc7kRI/AAAAAAAAT74/xHgWzR9s1pggNXA2NZkfHiwuStmeWENZwCLcBGAs/s1600/forms_classic.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="920" data-original-width="1091" height="538" src="https://2.bp.blogspot.com/-0zxnUih8lik/W6rYIZc7kRI/AAAAAAAAT74/xHgWzR9s1pggNXA2NZkfHiwuStmeWENZwCLcBGAs/s640/forms_classic.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Oracle Forms</td></tr></tbody></table><br />Navigator on the left, properties on the right, layout editor in them middle. All with similar behaviours (link to my videos from a while back)<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-tH03PsVI02Y/W6rYIL0fPBI/AAAAAAAAT70/pBZKZ9nolAc5I6cfB7dH-kTvCy8eRpFjACLcBGAs/s1600/apex_builder.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="752" data-original-width="1544" height="310" src="https://2.bp.blogspot.com/-tH03PsVI02Y/W6rYIL0fPBI/AAAAAAAAT70/pBZKZ9nolAc5I6cfB7dH-kTvCy8eRpFjACLcBGAs/s640/apex_builder.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Oracle APEX 5.1, with custom skin</td></tr></tbody></table>I thought I'd run down some components within the Forms IDE, and add some commentary.<br /><br /><h3>Before you begin...</h3><br />The key thing to remember when transitioning from Forms to APEX is ... <a href="http://www.clearintentions.net/emptying-your-cup/" target="_blank"><i>empty the cup</i></a>.<br /><br />Web behaviour changes some UX fundamentals, but it's an environment in which you should already be rather fluent. So forget about how you build applications in Forms, and think about how you want your website to behave.<br /><br /><h3>Render vs Process</h3><br />Forms renders the Form to the pixel from compiled source files, and you can show/hide elements on the canvas upon certain triggers firing.<br /><br />A user visiting a URL in APEX will have their HTML page dynamically generated by PL/SQL, with a variety of conditions on components that decide if they're included in the render.<br /><br />After the page is delivered to the browser, Dynamic Actions then respond to events that may happen on the page before the next page submit, which allows validation and processing of all the values on the page, or a page redirect, which just opens the target, leaving page data behind.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-SojatG7C7Vo/W6wzTbz8nuI/AAAAAAAAT9E/joJQpvcQPDcsMbj9qQ3UVYa4sSwxx8n6ACLcBGAs/s1600/rendering.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="42" data-original-width="480" src="https://2.bp.blogspot.com/-SojatG7C7Vo/W6wzTbz8nuI/AAAAAAAAT9E/joJQpvcQPDcsMbj9qQ3UVYa4sSwxx8n6ACLcBGAs/s1600/rendering.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Render, Interaction, or Page Process?</td></tr></tbody></table><br />The behavioural difference to remember is that the database knows nothing about the values on the web page until you either<br />1) submit the page (Processing)<br />2) execute a PL/SQL dynamic action that submits page items to session state<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-BnoT208Fdxk/W6wyb7QbQsI/AAAAAAAAT84/ZHc77tgpP_gK9XKM0Y-zKi0AnhkqaaLfQCLcBGAs/s1600/exec_da.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="193" data-original-width="346" src="https://3.bp.blogspot.com/-BnoT208Fdxk/W6wyb7QbQsI/AAAAAAAAT84/ZHc77tgpP_gK9XKM0Y-zKi0AnhkqaaLfQCLcBGAs/s1600/exec_da.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">PL/SQL Dynamic Action</td></tr></tbody></table><br />Many of your initial problems will probably relate to forgetting to submit/return these values.<br /><br /><h3>Object Navigator Components</h3><div><br /></div><h4>Triggers</h4>Straight into a topic with conceptually different behaviours between Forms &amp; APEX. Triggers in Forms drove pretty much everything. You're responding to some event that user has manifested in some way, often driven by moving the cursor.<br /><br />In a stateful environment, this behaviour is fine, and made Forms powerful. In the web environment, these triggers don't have much of a 1-to-1 translation, but the main analog here might be <a href="https://www.oracle.com/webfolder/technetwrk/tutorials/obe/db/apex/r51/dynamic_actions/dynamic_actions.html" target="_blank">Dynamic Actions</a>.<br /><br />Many APEX pages might handle processing when you submit the page, so you may have validations, computations, and processes that fire, based on flexible conditions.<br /><br />Interactive pages may have dynamic actions that respond to specific clicks, but not submit or refresh the entire page, just some of it. This reduces network traffic, and enables clever user experiences.<br /><br /><h4>Alerts</h4>Half your messages may come the process that fires when you submit the page, to be shown on the subsequent page.<br /><br />For instance, you could set the value of a common item P0_RESULT within your process, and display it as the success message using the <code>&amp;ITEM.</code> substitution syntax.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-TFpukTEj23E/W6wzEdLPh6I/AAAAAAAAT9A/HrdVsrOSIWsaIe8x1KYOIbPujL8CpF9cACLcBGAs/s1600/page_process.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="529" data-original-width="330" src="https://3.bp.blogspot.com/-TFpukTEj23E/W6wzEdLPh6I/AAAAAAAAT9A/HrdVsrOSIWsaIe8x1KYOIbPujL8CpF9cACLcBGAs/s1600/page_process.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Page Process</td></tr></tbody></table><br /><br />For Dynamic Actions interacting with the database, you may want to display the same style message.<br />Check out <a href="https://www.talkapex.com/2018/03/custom-apex-notification-messages/" target="_blank">this example</a> from Martin using the <a href="https://docs.oracle.com/database/apex-18.1/AEAPI/apex-message-namespace.htm#AEAPI-GUID-B896DF40-8145-426A-889B-657CBC288769" target="_blank">Supplied API</a>.<br /><br />Or for dialog behaviour where you control button naming, you might consider using a plugin such as <a href="https://apex.oracle.com/pls/apex/f?p=64237:30:0:" target="_blank">Alertify</a>&nbsp;or <a href="http://apex.pretius.com/apex/f?p=105:NOTIFICATIONS" target="_blank">Pretius Enhanced Notifications</a>.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-Q0Qfw7HjbUc/W6s6ypWtjII/AAAAAAAAT8M/Cg1wij4FMQIRBhjCoj-49Lw0FWH44GMUgCLcBGAs/s1600/alertify.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="536" data-original-width="335" src="https://3.bp.blogspot.com/-Q0Qfw7HjbUc/W6s6ypWtjII/AAAAAAAAT8M/Cg1wij4FMQIRBhjCoj-49Lw0FWH44GMUgCLcBGAs/s1600/alertify.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Alertify Dynamic Action instance</td></tr></tbody></table><br /><h4>Attached Libraries</h4>APEX takes care of the JavaScript and CSS libraries that support the Universal Theme, which supports all the components you need for flexible, dynamic applications.<br /><br />You can include your own JavaScript and CSS in several ways, mostly via the page attributes.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-_LCQIzjMvIo/W6s7hYd1rjI/AAAAAAAAT8U/o0iMOcmHKNAu0hhTksXxDsmAYbcELbjWgCLcBGAs/s1600/css_Attribs.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="213" data-original-width="335" src="https://4.bp.blogspot.com/-_LCQIzjMvIo/W6s7hYd1rjI/AAAAAAAAT8U/o0iMOcmHKNAu0hhTksXxDsmAYbcELbjWgCLcBGAs/s1600/css_Attribs.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Page CSS attributes</td></tr></tbody></table><br />You can choose to add inline code, reference files that exist either in the database as a BLOB (#APP_IMAGES#), or sitting on the middle tier, typically served by ORDS, perhaps sitting on a Web Logic Server, prefixing the file location with #IMAGE_PREFIX#.<br /><br />If you use a decent amount of custom JavaScript, you may wish to consider <a href="https://github.com/OraOpenSource/apex-nitro" target="_blank">APEX Nitro</a>.<br /><br /><h4>Data Blocks</h4>As a Forms developer, I remember spending a lot of time managing details of the data block, and they generally either broke up the page into chunks of data, or held buttons &amp; hidden items.<br /><br />In APEX, you could say similar things about Regions. Each page is broken up into a bunch of regions, which could come in many forms. Check out the <a href="https://apex.oracle.com/pls/apex/f?p=42:3000" target="_blank">Component Templates</a> available in the Universal Theme.<br /><br />You can even construct master-detail relationships in APEX. There are no Relations to define, but relationship properties are set within the Region attributes.<br /><br /><h4>Editors</h4>I don't recall using Editors much in Forms, but if you want to handle large objects of the character variety, then you might consider the <a href="https://github.com/OraOpenSource/apex-plugin-clob-load" target="_blank">OraOpenSource plugin</a>.<br /><br /><h4>Events</h4>I don't remember using Events, but I believe they allow die-hard Forms developers to extend their application with JavaBeans.<br /><br />If there is something that APEX doesn't do out of the box, it will probably be worth looking to see if anyone has built a plugin for APEX to do so. Some of these are <a href="http://dgielis.blogspot.com/2018/07/my-top-5-apex-181-plugins.html" target="_blank">absolute crackers</a>. Once I did a session on <a href="http://www.grassroots-oracle.com/2013/11/apex-plugin-tutorial-application.html" target="_blank">consuming plugins</a>.<br /><br /><h4>LOVs</h4>I think the Record Group element is manifested as an LOV definition now, that can be shared in a number of places.<br /><br />An LOV in APEX is more coupled with the Item type. A radio group works well with a small handful of values, Select Lists for middle sized sets, and perhaps the <a href="https://apex.oracle.com/pls/apex/f?p=64237:20" target="_blank">Select2</a> or I really like the <a href="https://github.com/mennooo/orclapex-modal-lov" target="_blank">Modal LOV</a> plugin for larger sets to be dynamically queried, while still mastering the keyboard entry.<br />Or you might even define your own modal page to fetch a value.<br />There is a native Popup LOV, but I don't like it.<br /><br /><h4>Object Groups</h4>Object Groups and Property Classes in Forms are little more vague than the rest, since this was the sort of thing that would be set up once in a blue moon, utilised many times.<br /><br />I think a comparison for grouping objects in APEX might be item plugins, possibly project specific.<br /><br />Or maybe <a href="https://docs.oracle.com/database/apex-18.1/HTMDB/using-blueprints.htm#HTMDB-GUID-80752E99-4216-44FB-B7FE-7FA9B2B0EAEA" target="_blank">blueprints</a>.<br /><br /><h4>Parameters</h4>Page Items are populated between pages to pass information to the next page, such as the selected record in a report.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-nmRltq2V2y8/W6wxOyGVSLI/AAAAAAAAT8s/_M0lwnQ5XEEK_x0l26kdpgFOii-BPESmgCLcBGAs/s1600/target.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="278" data-original-width="519" src="https://3.bp.blogspot.com/-nmRltq2V2y8/W6wxOyGVSLI/AAAAAAAAT8s/_M0lwnQ5XEEK_x0l26kdpgFOii-BPESmgCLcBGAs/s1600/target.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Declarative Page Target</td></tr></tbody></table><br /><br />Larger forms with a number of items are generally submitted as a whole, where the page process handles the data, and branches to the next page.<br /><br />These values can be protected from URL tampering by session state security, at item, page, and application levels, often by default.<br /><br /><h4>Popup Menus</h4>I've seen explorations of contextual popup menus <a href="https://apex.oracle.com/pls/apex/f?p=42:1306:::NO:::" target="_blank">here</a>, and <a href="http://hardlikesoftware.com/weblog/2015/07/13/apex-5-0-custom-menus/" target="_blank">here</a>.<br /><br />The APEX team have implemented them within the Page Designer - my favourite is the <a href="https://www.youtube.com/watch?v=Zu1WwRiMVWg" target="_blank">duplicate option</a>.<br /><br /><h4>Program Units</h4>When I used Forms, the general mantra was to keep code out of item/block level events, and manage packaged procedure calls from within program units.<br /><br />But we've all seen Forms written with a spectrum of best practices applied. This is where many of the performance problems could lie, especially poorly used post-query triggers.<br /><br />For Forms to APEX migration projects, this is probably where most of your gold lies - all the business rules you want to keep. Depending on how well the application is written, you might get to re-use a lot of it, but in my experience, few Forms projects used <a href="http://stevenfeuersteinonplsql.blogspot.com/2018/05/the-smartdb-resource-center.html" target="_blank">SmartDB</a> concepts.<br /><br />If you're aiming for a certain % of re-use, don't aim too high. The code in here can be good guide for the developer in refactoring behaviour, but the APEX page(s) could end up looking and behaviour different to what you had in Forms, if only because you're now in a browser. Thought it could be because you've reviewed the business process since the Form was written 2 decades ago, or you've replaced a lot of the keystrokes with button taps.<br /><br /><h4>Property Classes</h4>Property Classes in Forms allowed the developer to utilise common attributes among each instance of a component.<br /><br />In APEX we can define <a href="https://www.packtpub.com/mapt/book/application_development/9781849684002/1/ch01lvl1sec14/user-interface-defaults" target="_blank">User Interface Defaults</a> in the data dictionary, so that each time items or reports are created for specific tables or columns, the same features are applied by default.<br /><br />As for the style of the application, classes could be applied to components that carry a particular look &amp; feel. The Universal Theme has a default skin that can be reconfigured declaratively.<br /><br /><h4>Record Groups</h4>Record groups where just the SQL component of the LOV.<br /><br />Head to an application's Shared Components, then locate LOVs. They can be dynamically driven by a SQL query, or be statically defined. Static definition allows a variety of conditions to be applied to each entry.<br /><br />These LOVs can then be associated with Items such as Radio Groups &amp; Select Lists, or with a column in a report, to translate a code to a label.<br /><br /><h4>Reports</h4>Reporting in APEX is a deep rabbit hole. Conceptually, all your reporting can now be inline - live.<br />Your power users can be given Interactive Reports with a number of runtime manipulation options.<br />Oracle JET charts can respond to clicks, allowing drill down functionality, in whatever way you want.<br /><br />Or you could go down the yellow brick road and <a href="https://www.slideshare.net/LinoSchildenfeld/apex-rd-apex-5-printing" target="_blank">choose</a>&nbsp;a <a href="https://apex.oracle.com/pls/apex/f?p=LS_DEMO:APEX5_PRINTING" target="_blank">tool</a> to dynamically generate PDF documents, Excel spreadsheets, Word files etc.<br /><br /><h4>Visual Attributes</h4>Template Options seem to be a fair comparison here, where common group of settings can be tailored to each instance of a component.<br /><br /><h4>Windows</h4>Application workflow differs between Forms and APEX due to the nature of their environments.<br /><br />In APEX most interactions happen within the browser window, within an inline modal (just a special looking page region), within a page modal. From APEX 5.x this became native and easy, allowing modals to have validations and branches, just like standard pages.<br /><br /><h4>Menus</h4>Forms had specific menu files, controlled by database roles, and there had to be no active users to be able to update the .mmx file.<br /><br />The menu in APEX can either be across the top, or down the left side. These menus can be statically defined, or dynamically driven, even by the meta-data that is apex_application_pages view. (my link)<br /><br />Static navigation entries could be controlled by authorisation schemes, or custom conditions.<br /><a href="http://www.grassroots-oracle.com/2013/05/css-pull-down-menu-using-apex-list.html" target="_blank">Dynamic menus</a> can have security tables integrated within the SQL.<br /><br />There are a few list templates that follow the same data structure, just rendered in <a href="https://apex.oracle.com/pls/apex/f?p=42:1305:::NO:::" target="_blank">different ways</a>.<br /><br />There is a smaller Navigation Bar at the top right, typically starting with the login/logout buttons.<br /><br /><h4>Canvas</h4>Forms is WYSIWYG, I'm sorry for your loss. An APEX page needs to be rendered in a variety of devices sizes, so items go where the responsive templates tell them to go. You can impact this using the grid layout, but it can take a little while to get the hang of it. Showing the columns helps, particularly with item layout.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/--5WJAahwUdA/W6w8Xtqeo2I/AAAAAAAAT9U/s-fWnZvW8Eg5QAl_kuwMg5tYMBGfqBx5ACLcBGAs/s1600/show_columns.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="286" data-original-width="712" height="257" src="https://3.bp.blogspot.com/--5WJAahwUdA/W6w8Xtqeo2I/AAAAAAAAT9U/s-fWnZvW8Eg5QAl_kuwMg5tYMBGfqBx5ACLcBGAs/s640/show_columns.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Show Layout Columns</td></tr></tbody></table>APEX also includes a palette of components ready to drag onto the layout editor, which I primarily use to check if items/regions are set to Start New Row or not.<br /><br /><h3>Properties</h3>The Page Designer introduced in APEX 5.0 is rather reminiscent of Oracle Forms, particularly with regard to the ability to edit multiple components at once, only intersecting attributes, and obscuring heterogenous values.<br /><br />As with Forms, <i>finding </i>the right property can be tricky, or even being aware of its existence.<br /><br />I highly recommend you take note of the inline help associated with each attribute. I'm sure this content improves with every version, even without inline feedback (hint hint).<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-q7s_AplE7YQ/W6ww16X0kRI/AAAAAAAAT8k/YeE0r6eOr-o5lWqBqoxJZbIc81oQr4vVACLcBGAs/s1600/field_help.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="311" data-original-width="753" height="264" src="https://4.bp.blogspot.com/-q7s_AplE7YQ/W6ww16X0kRI/AAAAAAAAT8k/YeE0r6eOr-o5lWqBqoxJZbIc81oQr4vVACLcBGAs/s640/field_help.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Inline Attribute Help</td></tr></tbody></table><br />Let me know if you think I've forgotten something vital here, or misaligned features.<br /><br />Here are some other links on the topic of Forms transition to APEX:<br /><br /><a href="http://www.explorer.uk.com/blog-forms-to-apex-projects-get-thorny/" target="_blank">When Forms to APEX Projects get thorny</a> - Rodrigo also responding to the AskTom session<br /><a href="http://www.grassroots-oracle.com/2018/07/oracle-forms-migration-to-APEX.html" target="_blank">Oracle Forms Migration</a> - Some recent thoughts (that need some revision)<br /><a href="https://prezi.com/un7pkjyalgo5/apex-5-page-designer/" target="_blank">APEX 5 Page Designer walkthrough</a> - my prezi session looking specifically at the Page Designer IDE.<br /><a href="https://devgym.oracle.com/pls/apex/asktom.search?tag=oracle-forms-v-oracle-apex-check-list" target="_blank">AskTom Checklist</a><br /><a href="https://apex.oracle.com/en/solutions/oracle-forms/apex-office-hours/" target="_blank">Office Hours Q&amp;A</a> Scott Wesley tag:blogger.com,1999:blog-4818542164384221282.post-6115163587900824801 Thu Sep 27 2018 00:00:00 GMT-0400 (EDT) Setting up SQL*Plus with the help of an Oracle Docker container https://apextips.blogspot.com/2018/09/setting-up-sqlplus-with-help-of-oracle.html Working with Oracle Database's I like to install the Oracle instant client - probably the biggest reason for me is that it gives me access to SQL*Plus. Personally, I think the installation is very straight forward, but the number one complaint I hear is its too difficult to set up.<br /><br />So, how can you get access to SQL*Plus without this "difficult" installation process?<br /><br />Say hello to the Oracle instant client docker container.<br /><br />If you head over to <a href="https://container-registry.oracle.com/">https://container-registry.oracle.com</a>, navigate to the database section, you will notice 3 repositories:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-_58jQJm97Hs/W6wKiFGwrMI/AAAAAAAAI4Q/hAK6U1jWy3Uzz-ZV5yQLiJ0LV0I7geE0gCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-09-26%2B18-38-35.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="299" data-original-width="586" height="163" src="https://1.bp.blogspot.com/-_58jQJm97Hs/W6wKiFGwrMI/AAAAAAAAI4Q/hAK6U1jWy3Uzz-ZV5yQLiJ0LV0I7geE0gCLcBGAs/s320/Screenshot%2Bfrom%2B2018-09-26%2B18-38-35.png" width="320" /></a></div><br /><br />So, you will see the second one in the list is named "instantclient" - exactly what we need!<br /><br /><i><b>side note: </b>this container is a little out of date, being last updated over a year ago, but I'd say the latest version isn't crucial for most needs.</i><br /><br />So, if you click into instantclient, you will need to sign in first so that you can accept the license agreement. You will also need to sign into the registry from your shell. Once that is done, we can grab that image with:<br /><br /><pre>docker pull container-registry.oracle.com/database/instantclient:latest</pre><br />With that installed, you will now want to create an alias on your OS. So, go ahead an run the following in your shell:<br /><br /><pre>alias sqlplus='docker run -ti --rm container-registry.oracle.com/database/instantclient sqlplus'</pre><br />Now, if you run:<br /><br /><pre>type -a sqlplus</pre><br />You should see that SQL*Plus is now aliased to run that docker container.<br /><br />I happen to have a VirtualBox VM running with an Oracle XE database, with the schema vmtest. It is on my local network with the IP address 192.168.0.104. So, now if I run:<br /><br /><pre>sqlplus vmtest/vmtest@//192.168.0.104/xe</pre><br /><br />I'll be connected to the database, which the following screenshot demonstrates.<br /><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-DGwwfrCFhYQ/W6wM4dhCH4I/AAAAAAAAI4c/Nq4DCA1mkbQ3JiHpDoYcCFuzFdnTd_VGQCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-09-26%2B18-48-46.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="482" data-original-width="1470" height="130" src="https://4.bp.blogspot.com/-DGwwfrCFhYQ/W6wM4dhCH4I/AAAAAAAAI4c/Nq4DCA1mkbQ3JiHpDoYcCFuzFdnTd_VGQCLcBGAs/s400/Screenshot%2Bfrom%2B2018-09-26%2B18-48-46.png" width="400" /></a></div><br />How simple is that! I didn't need to go through any rigorous process to install the instant client, and I now have SQL*Plus at my disposal. trent tag:blogger.com,1999:blog-8785176694082881912.post-4794987643512109143 Wed Sep 26 2018 19:11:00 GMT-0400 (EDT) apex.oracle.com ha sido actualizado a APEX 18.2 este fin de semana! http://feedproxy.google.com/~r/DescubriendoElMundoDeOracle/~3/hyctUy8EEEc/apexoraclecom-ha-sido-actualizado-apex.html <br />Según el&nbsp;Statement of Direction del 6 de agosto de este año, Oracle APEX 18.2 es la primera actualización de APEX 18.1 e incluye numerosas correcciones de errores y una serie de nuevas características y mejoras. Está previsto incorporar lo siguiente:<br /><br /><br /><ul><li>Asistente mejorado para el aprovisionamiento del espacio de trabajo, con opciones adicionales para agilizar las nuevas solicitudes de servicio.</li><li>Nuevo tipo de página maestra de detalles de lado a lado disponible en el asistente Crear Página.</li><li>Nuevo tipo de página Dashboard disponible en el asistente Crear Página.</li><li>Advertencias mejoradas dentro del taller REST para evitar la pérdida de definiciones personalizadas.</li><li>Una documentación de API de JavaScript más completa.</li><li>Posibilidad de actualizar hojas de estilos APEX para fuentes y archivos de fuentes independientes de las versiones APEX de Oracle.</li><li>La instalación de Samples Datasets permitirá la creación de una aplicación de ejemplo que incluye el Dashboard y los informes drill down.</li><li>El conjunto de datos de ejemplo de EMP/DEPT estará disponible en inglés, chino, checo, francés, alemán, japonés, coreano, polaco, ruso y español.</li><li>Actualizaciones de aplicacioones de ejemplo y de productividad</li></ul><div><br /><a name='more'></a></div><b>Release Revisado ​​y Convenciones de Nombre</b><br /><br />Oracle APEX 18.1 fue el primer lanzamiento importante en el año calendario 2018. El próximo lanzamiento en el mismo año calendario será APEX 18.2. Oracle APEX ya no proporcionará versiones de parches, como APEX 18.1.1, sino que solo ofrecerá versiones completas. El primer lanzamiento en el año calendario 2019 será APEX 19.1.<br /><br /><i><b>Nota</b>: las excepciones de conjunto de parches (PSE) se seguirán entregando para los defectos principales y generalmente se comunicarán en la página Problemas conocidos de Oracle APEX. Algunos PSE se entregarán en un paquete de PSE, en lugar de individualmente. Asegúrese de leer la solución provista y buscar el número de error especificado en la página Problemas conocidos de Oracle APEX. Para los paquetes de PSE revise el archivo Léame para determinar todas las correcciones de errores incluidas en el paquete.</i><br /><br />Este cambio en la estrategia de lanzamiento es de gran beneficio tanto para la implementación en la nube como en las instalaciones de Oracle APEX. La principal ventaja de esta estrategia de lanzamiento es la reducción del tiempo de inactividad al actualizar una instalación Oracle APEX existente. La arquitectura también brinda la posibilidad de volver a retroceder de forma inmediata si es necesario. La utilización de conjuntos de parches, en lugar de una versión completa, requiere significativamente más tiempo de inactividad y no hay una manera fácil de deshacer la instalación del conjunto de parches. Este cambio en la estrategia de lanzamiento también proporciona un vehículo para que las características se presenten antes a nuestros clientes.<br /><br /><br /><img src="http://feeds.feedburner.com/~r/DescubriendoElMundoDeOracle/~4/hyctUy8EEEc" height="1" width="1" alt=""/> Clarisa J. Maman Orfali tag:blogger.com,1999:blog-1315583943401206186.post-8898644097562818684 Sun Sep 23 2018 14:19:00 GMT-0400 (EDT) Oracle APEX is coming to India! https://blogs.oracle.com/apex/oracle-apex-is-coming-to-india <p><a href="https://apex.oracle.com" target="_blank">Oracle APEX</a> is coming to India!&nbsp;</p> <p>Oracle APEX team members <a href="https://twitter.com/chaitanya_in" target="_blank">Chaitanya Koratamaddi</a> and <a href="https://twitter.com/shakeeb" target="_blank">Shakeeb Rahman</a> will be visiting three APEX meetups in India in October!&nbsp; If you&#39;re in Hyderabad, Chennai, or Bengaluru, please don&#39;t miss this opportunity to meet and learn directly from members of the APEX product development team!</p> <p>At these meetups, you will learn about what&#39;s new in Oracle APEX 18 and how you can use APEX to build beautiful, responsive apps using Universal Theme.&nbsp;</p> <p>In Chennai, there is a full day of APEX learning, including workshops, deep dives, and customer success stories.<br /> &nbsp;<br /> The schedule of the Oracle APEX India Tour is:</p> <p style="margin-left: 40px;"><a href="https://apex.oracle.com/go/hyd2018" target="_blank">October 3, 2018:&nbsp; Hyderabad</a></p> <p style="margin-left: 40px;"><a href="https://apex.oracle.com/go/chennai2018" target="_blank">October 6, 2018:&nbsp; Chennai</a></p> <p style="margin-left: 40px;"><a href="https://apex.oracle.com/go/blr2018" target="_blank">October 8, 2018:&nbsp; Bengaluru</a></p> <p>Please register in advance.&nbsp; We hope to see you there!</p> Joel Kallman https://blogs.oracle.com/apex/oracle-apex-is-coming-to-india Sat Sep 22 2018 12:03:00 GMT-0400 (EDT) Oracle APEX is coming to India! https://blogs.oracle.com/apex/oracle-apex-is-coming-to-india <p><a href="https://apex.oracle.com" target="_blank">Oracle APEX</a> is coming to India!&nbsp;</p> <p>Oracle APEX team members <a href="https://twitter.com/chaitanya_in" target="_blank">Chaitanya Koratamaddi</a> and <a href="https://twitter.com/shakeeb" target="_blank">Shakeeb Rahman</a> will be visiting three APEX meetups in India in October!&nbsp; If you&#39;re in Hyderabad, Chennai, or Bengaluru, please don&#39;t miss this opportunity to meet and learn directly from members of the APEX product development team!</p> <p>At these meetups, you will learn about what&#39;s new in Oracle APEX 18 and how you can use APEX to build beautiful, responsive apps using Universal Theme.&nbsp;</p> <p>In Chennai, there is a full day of APEX learning, including workshops, deep dives, and customer success stories.<br /> &nbsp;<br /> The schedule of the Oracle APEX India Tour is:</p> <p style="margin-left: 40px;"><a href="https://apex.oracle.com/go/hyd2018" target="_blank">October 3, 2018:&nbsp; Hyderabad</a></p> <p style="margin-left: 40px;"><a href="https://apex.oracle.com/go/chennai2018" target="_blank">October 6, 2018:&nbsp; Chennai</a></p> <p style="margin-left: 40px;"><a href="https://apex.oracle.com/go/blr2018" target="_blank">October 8, 2018:&nbsp; Bengaluru</a></p> <p>Please register in advance.&nbsp; We hope to see you there!</p> Joel Kallman https://blogs.oracle.com/apex/oracle-apex-is-coming-to-india Sat Sep 22 2018 12:03:00 GMT-0400 (EDT) Oracle SQL – Das umfassende Handbuch http://feedproxy.google.com/~r/CC13com/~3/D_hugfMSSHY/ <p>Meine <a href="http://www.cc13.com/wordpress_21/2017/12/10/oracle-apex-das-umfassende-handbuch/" class="liinternal">letzte Buchbesprechung</a> ist schon ein paar Monate zurück. Das liegt aber nur zum Teil am Umfang des mir nun vorliegenden Buches. Schnell mal durchgelesen ist &#8222;Oracle SQL &#8211; Das umfassende Handbuch&#8220; allerdings nicht. Aber dazu später mehr.</p> <h3>Titel: <a href="https://www.rheinwerk-verlag.de/oracle-apex_4376/" class="liexternal" target="_blank" rel="noopener"><strong>Oracle SQL – Das umfassende Handbuch</strong></a><br /> Autor: <b>Jürgen Sieben</b><br /> Verlag: <strong><a href="https://www.rheinwerk-verlag.de/" class="liexternal" target="_blank" rel="noopener">Rheinwerk-Verlag</a></strong><br /> Erscheinungsdatum: <strong>2018</strong><br /> ISBN: <strong>978-3-8362-6242-2</strong><span class="s1"><br /> Seitenzahl: <strong>1047</strong></span></h3> <p>Wie auch <a href="http://www.cc13.com/wordpress_21/2017/12/10/oracle-apex-das-umfassende-handbuch/" class="liinternal">&#8222;Oracle Apex&#8220;</a> ist dieses Buch von Jürgen Sieben verfasst. Dieser zeigt mit seiner Schreibweise, das Fachliteratur nicht trocken sein muss. Er mischt das zu vermittelnde Fachwissen mit Erfahrungen/Projekten aus seinem Berufsleben und erklärt somit, weshalb er bestimmten Code genau so vermittelt, obwohl es auch andere Wege gibt.</p> <div id="attachment_896" style="width: 160px" class="wp-caption aligncenter"><a href="https://www.rheinwerk-verlag.de/oracle-sql_4627/" class="liimagelink"><img class="size-thumbnail wp-image-896" src="http://www.cc13.com/wordpress_21/wp-content/uploads/2018/09/9783836262422_267-150x150.png" alt="Oracle SQL - Das umfassende Handbuch" width="150" height="150" /></a><p class="wp-caption-text">Oracle SQL &#8211; Das umfassende Handbuch</p></div> <p>Auf das Inhaltsverzeichnis werde ich hier nicht extra eingehen, dieses findet man auf der <a href="https://www.rheinwerk-verlag.de/oracle-sql_4627/" target="_blank" rel="noopener" class="liexternal">Webseite</a> zum Buch, genauso wie die Materialien zum Download. Mit diesen können die Code Beispiele selber ausprobiert werden. Es ist sogar zu empfehlen, die Skripte zu installieren, um die gleichen Daten in der eigenen Datenbank wie der Autor zu haben.</p> <p>Und da komme ich schon zum ersten Kritikpunkt, der mich beim Durcharbeiten aufgehalten hat. Im Buch auf Seite 51 wird beschrieben, wie man das Beispielschema in seine Oracle Datenbank bekommt. Jürgen Sieben erklärt, wo man das Paket herunterlädt, dass man es entpacken und sich dann in einem Konsolenfenster in das eben entpackte Archiv begeben soll (enthält mksample.sql). Nachdem man sich per sqlplus mit der Datenbank verbunden hat, reicht ein Aufruf von &#8222;@mksample.sql&#8220;. Und das hat bei mir leider nicht funktioniert. Nach ein wenig Recherche fand ich den Hinweis auf der <a href="https://github.com/oracle/db-sample-schemas" target="_blank" rel="noopener" class="liexternal">GitHub-Seite</a> des Pakets unter Punkt 2.3. Dort steht, dass man in allen Skripten den Pfad auf seine Umgebung anpassen muss. Damit lief das Skript durch und legte die gewünschte Umgebung an. Da fällt z.B. der &#8222;kleine&#8220; Fehler im Skript auf Seite 378 schon gar nicht mehr ins Gewicht. Wo &#8222;emp_dept_20 v&#8220; definiert, aber &#8222;s.empno&#8220; referenziert wird. Es sollte also &#8222;v.empno&#8220; heißen. Allerdings nehme ich solche Fehler sportlich und als Übung, das Gelernte anzuwenden.</p> <p>Jürgen Sieben bietet in seinem Buch ein großes Themenfeld für die Arbeit mit Oracle SQL Datenbanken. Der Leser erfährt vom Konzept der relationalen Datenbanken und wie er die Tabellen entsprechend anlegt, abfragt, mit Daten füllt oder Daten verändert. Ein extra Kapitel beschäftigt sich mit dem Aufbau der Oracle Datenbank und den Sicherheitseinstellungen. Für eine nächste Auflage würde ich mir wünschen, dass der Autor noch erklärt, wie die Umgebung einzurichten ist, damit man von einem anderen Computer darauf zugreifen kann. Somit konnte ich die Datenbank in einer virtuellen Maschine auf meinem NAS installieren und bequem mit dem Laptop auf der Couch sitzend, die Code-Beispiele durchgehen.</p> <p>Auch &#8222;moderne&#8220; Techniken, wie z.B. XML, JSON, Pivotabfragen und Objektorientierung in der Oracle Datenbank werden im Buch beschrieben. Abgerundet wird das Buch mit einem Kapitel für Performanzoptimierung und zu guter Letzt geht es um Datenmodellierung.</p> <p>Zusammenfassend kann ich sagen, dass Jürgen Sieben auch in diesem Buch sein Wissen gut vermittelt. Man merkt ihm die Erfahrung aus der Praxis an. Der Leser sollte die Beispiele selber nachvollziehen, um den Code zu verstehen. Als Nachschlagewerk dient das Buch weniger, da viele Code Beispiele sich über mehrere Seite aufbauen. Allerdings geht der Autor an einigen Stellen im Buch explizit auf die Online Oracle Dokumentation ein, sollte ein Befehl oder dessen Syntax unklar bleiben.</p> <p><em>Disclaimer: Das Buch wurde mir vom Rheinwerk Computing Verlag kostenfrei zur Verfügung gestellt.</em></p> <p>Der Beitrag <a rel="nofollow" href="http://www.cc13.com/wordpress_21/2018/09/21/oracle-sql-das-umfassende-handbuch/">Oracle SQL &#8211; Das umfassende Handbuch</a> erschien zuerst auf <a rel="nofollow" href="http://www.cc13.com/wordpress_21">CC13.com</a>.</p> cc13 http://www.cc13.com/wordpress_21/?p=895 Fri Sep 21 2018 09:14:46 GMT-0400 (EDT) So, does my business need REST Services? https://insum.ca/so-does-my-business-need-rest-services/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/09/Does-my-business-need-REST-services-100x100.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Does my business need REST services" srcset="https://insum.ca/wp-content/uploads/2018/09/Does-my-business-need-REST-services-100x100.jpg 100w, https://insum.ca/wp-content/uploads/2018/09/Does-my-business-need-REST-services-150x150.jpg 150w, https://insum.ca/wp-content/uploads/2018/09/Does-my-business-need-REST-services-600x600.jpg 600w, https://insum.ca/wp-content/uploads/2018/09/Does-my-business-need-REST-services-300x300.jpg 300w, https://insum.ca/wp-content/uploads/2018/09/Does-my-business-need-REST-services-50x50.jpg 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p>We sometimes get questions about REST. “What is it exactly?” “How does it work?”. In its long form, &#8220;Representational State Transfer&#8221; doesn&#8217;t make it easier to understand. Nor do the words usually associated with it, such as in “Should I have a REST API?” or “Should I have RESTful Services?”. And, if we give a basic definition like &#8220;REST is an architectural style for the design of Web services&#8221;, that kind of leaves you hanging as well. So, in this post, we&#8217;ll do our best to put the concepts in an order that will help you understand.</p> <p>Web services is a good place to start.</p> <h2>First, Web Services</h2> <p>A Web service is a means by which two applications can talk to each other over the web. It is a framework for their conversations. Often, these conversations are going on without human interaction. They do need to be carefully set up by a developer, however.</p> <h2>Good reasons to use Web Services</h2> <p>So why would applications be talking to each other over the web without human interaction? Interoperability with a minimum of human intervention. Web services exist mainly to get things to work together smoothly on the web, no matter what kind of platform, software, architecture etc. is involved. For example, your company might be using a web service to help its old (legacy) finance software communicate its information to a more modern application at the head office. Perhaps another web service enables mobile users to work in the system even if it wasn’t built with mobile users in mind. Another example:  your customer order system needs to pull information from the shipping company it uses, to establish the cost of each shipment in real time and present it to the customer on a web page so the customer can agree to it.</p> <h2>Another good reason: Web Services can help save on development time</h2> <p>Web services are also very helpful for developers: Instead of building an application from scratch, the developer can have his application call upon web services for certain tasks. This can save your company a lot of development time and a lot of money.</p> <h2>How Web Services Operate</h2> <p>The way two applications talk to each other in a Web service can be compared to when you are using your web browser. You type something into your web browser (let’s say it’s Google Chrome) and it responds by searching for and presenting results to your request. This is a client-server situation. Your computer is the client and Google is the server.</p> <p>Web services also need to work in a client-server relationship. The application playing the role of the client sends a request, the server application processes the request and sends back information. In the case of web services, the information usually isn’t human-readable. It’s data. The client application then feeds the data it has received into another application or acts upon it directly, depending on what is required at its end.</p> <h2>Communication Protocols</h2> <p>Of course, two applications having a conversation over the web might differ greatly from each other. They might be running in very different environments, too. The client might be an Apple iPad with an Apple operating system and the server might be an Oracle Cloud server running a Program using language that your iPad has never even heard of. This is why rules had to be created for web service communications.</p> <p>When web services started getting popular, back in the early 2000s, protocols were established to make their set up and operation easier.  The better-known ones were SOAP (Simple Object Access Protocol) XML RPC (Extensible Markup Language-Remote Procedure Call) and JSON-RPC (JavaScript Object Notation-Remote Procedure Call).</p> <p>REST, although it appeared roughly at the same time for the same reasons, is often compared to these protocols. But, it&#8217;s different. As stated above, it is an architectural style.</p> <h2>REST</h2> <p>REST gradually became the most popular way to manage web services because of its flexibility. For example, SOAP requires the use of XML language, and JSON-RPC requires the use of JSON. REST can allow XML, JSON, HTML, Plain text and more. It is more flexible, and consequently, a more natural fit for Web developers.</p> <p>What&#8217;s more, a RESTful service follows universally accepted methods when taking actions on the web (in the HTTP protocol). POST to create data, GET to retrieve, PUT to edit, and DELETE.</p> <p>For a detailed technical explanation of REST&#8217;s properties, have a look at this excellent blog post by <a href="http://www.kennethlange.com/posts/What-are-RESTful-Web-Services.html">Kenneth Lange</a>. If you want to find out more on how REST came about, look up this <a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">dissertation by Roy Fielding, it&#8217;s inventor</a>.</p> <p>So, back to <strong>RE</strong>presentational <strong>S</strong>tate <strong>T</strong>ransfer.  In the client-server relationship mentioned earlier, there is a transfer of server data in its representational State, meaning whatever state the resource requested by the client is represented in. The resource, a type of data (example: a customer’s account information) is identified by a URL. Its representational state can vary, depending on the language used.</p> <h2>API</h2> <p>You’ll notice I haven’t even mentioned APIs yet. The reason for this is that the two expressions are often run together without being explained separately.</p> <p>API stands for Application Program Interface. This is a set of tools to build applications. There are APIs for Operating Systems, Databases and software libraries. None of these are necessarily on the Web. However, the APIs that we are talking about here, are for the Web. To take advantage of a web service, the developer needs to familiarize himself with its API. The Web Service API includes the communication protocol, chosen format, the description of how to perform actions or get data from the remote computer, libraries for the development language used and any other instructions or information the developer needs to get the web service operational for his needs. When a developer chooses a web service to use, he must immediately familiarize himself with its API.</p> <h2>RESTful API</h2> <p>A RESTful API gives the developer more flexibility in choosing the language used for the Server&#8217;s response. It also ensures that everything needed for the communication between the client and server is included in the communication itself. This way, the communication doesn&#8217;t depend on any other outside source to be complete. It, therefore, lowers the risk of failure. REST APIs also enable you to more easily scale your request.</p> <p>More flexibility, more reliability, more simplicity and scalability make REST the preferred method of setting up a web service.</p> <h2>Conclusion</h2> <p>So, does your business need RESTful Services? You first need to answer the question &#8220;what Web services do I need&#8221; or &#8220;what Web services do I need to build?&#8221;. Of course, using RESTful APIs is the best way to build them.</p> <p>Insum are application development experts. We can build custom applications for you. Interested? <a href="https://insum.ca/contact/">Contact us!</a></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>The post <a rel="nofollow" href="https://insum.ca/so-does-my-business-need-rest-services/">So, does my business need REST Services?</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Francis Mignault https://insum.ca/?p=13129 Thu Sep 20 2018 16:09:42 GMT-0400 (EDT) So, does my business need REST Services? https://insum.ca/so-does-my-business-need-rest-services/ <p>We sometimes get questions about REST. “What is it exactly?” “How does it work?”. In its long form, &#8220;Representational State Transfer&#8221; doesn&#8217;t make it easier to understand. Nor do the words usually associated with it, such as in “Should I have a REST API?” or “Should I have RESTful Services?”. And, if we give a basic definition like &#8220;REST is an architectural style for the design of Web services&#8221;, that kind of leaves you hanging as well. So, in this post, we&#8217;ll do our best to put the concepts in an order that will help you understand.</p> <p>Web services is a good place to start.</p> <h2>First, Web Services</h2> <p>A Web service is a means by which two applications can talk to each other over the web. It is a framework for their conversations. Often, these conversations are going on without human interaction. They do need to be carefully set up by a developer, however.</p> <h2>Good reasons to use Web Services</h2> <p>So why would applications be talking to each other over the web without human interaction? Interoperability with a minimum of human intervention. Web services exist mainly to get things to work together smoothly on the web, no matter what kind of platform, software, architecture etc. is involved. For example, your company might be using a web service to help its old (legacy) finance software communicate its information to a more modern application at the head office. Perhaps another web service enables mobile users to work in the system even if it wasn’t built with mobile users in mind. Another example:  your customer order system needs to pull information from the shipping company it uses, to establish the cost of each shipment in real time and present it to the customer on a web page so the customer can agree to it.</p> <h2>Another good reason: Web Services can help save on development time</h2> <p>Web services are also very helpful for developers: Instead of building an application from scratch, the developer can have his application call upon web services for certain tasks. This can save your company a lot of development time and a lot of money.</p> <h2>How Web Services Operate</h2> <p>The way two applications talk to each other in a Web service can be compared to when you are using your web browser. You type something into your web browser (let’s say it’s Google Chrome) and it responds by searching for and presenting results to your request. This is a client-server situation. Your computer is the client and Google is the server.</p> <p>Web services also need to work in a client-server relationship. The application playing the role of the client sends a request, the server application processes the request and sends back information. In the case of web services, the information usually isn’t human-readable. It’s data. The client application then feeds the data it has received into another application or acts upon it directly, depending on what is required at its end.</p> <h2>Communication Protocols</h2> <p>Of course, two applications having a conversation over the web might differ greatly from each other. They might be running in very different environments, too. The client might be an Apple iPad with an Apple operating system and the server might be an Oracle Cloud server running a Program using language that your iPad has never even heard of. This is why rules had to be created for web service communications.</p> <p>When web services started getting popular, back in the early 2000s, protocols were established to make their set up and operation easier.  The better-known ones were SOAP (Simple Object Access Protocol) XML RPC (Extensible Markup Language-Remote Procedure Call) and JSON-RPC (JavaScript Object Notation-Remote Procedure Call).</p> <p>REST, although it appeared roughly at the same time for the same reasons, is often compared to these protocols. But, it&#8217;s different. As stated above, it is an architectural style.</p> <h2>REST</h2> <p>REST gradually became the most popular way to manage web services because of its flexibility. For example, SOAP requires the use of XML language, and JSON-RPC requires the use of JSON. REST can allow XML, JSON, HTML, Plain text and more. It is more flexible, and consequently, a more natural fit for Web developers.</p> <p>What&#8217;s more, a RESTful service follows universally accepted methods when taking actions on the web (in the HTTP protocol). POST to create data, GET to retrieve, PUT to edit, and DELETE.</p> <p>For a detailed technical explanation of REST&#8217;s properties, have a look at this excellent blog post by <a href="http://www.kennethlange.com/posts/What-are-RESTful-Web-Services.html">Kenneth Lange</a>. If you want to find out more on how REST came about, look up this <a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">dissertation by Roy Fielding, it&#8217;s inventor</a>.</p> <p>So, back to <strong>RE</strong>presentational <strong>S</strong>tate <strong>T</strong>ransfer.  In the client-server relationship mentioned earlier, there is a transfer of server data in its representational State, meaning whatever state the resource requested by the client is represented in. The resource, a type of data (example: a customer’s account information) is identified by a URL. Its representational state can vary, depending on the language used.</p> <h2>API</h2> <p>You’ll notice I haven’t even mentioned APIs yet. The reason for this is that the two expressions are often run together without being explained separately.</p> <p>API stands for Application Program Interface. This is a set of tools to build applications. There are APIs for Operating Systems, Databases and software libraries. None of these are necessarily on the Web. However, the APIs that we are talking about here, are for the Web. To take advantage of a web service, the developer needs to familiarize himself with its API. The Web Service API includes the communication protocol, chosen format, the description of how to perform actions or get data from the remote computer, libraries for the development language used and any other instructions or information the developer needs to get the web service operational for his needs. When a developer chooses a web service to use, he must immediately familiarize himself with its API.</p> <h2>RESTful API</h2> <p>A RESTful API gives the developer more flexibility in choosing the language used for the Server&#8217;s response. It also ensures that everything needed for the communication between the client and server is included in the communication itself. This way, the communication doesn&#8217;t depend on any other outside source to be complete. It, therefore, lowers the risk of failure. REST APIs also enable you to more easily scale your request.</p> <p>More flexibility, more reliability, more simplicity and scalability make REST the preferred method of setting up a web service.</p> <h2>Conclusion</h2> <p>So, does your business need RESTful Services? You first need to answer the question &#8220;what Web services do I need&#8221; or &#8220;what Web services do I need to build?&#8221;. Of course, using RESTful APIs is the best way to build them.</p> <p>Insum are application development experts. We can build custom applications for you. Interested? <a href="https://insum.ca/contact/">Contact us!</a></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>The post <a rel="nofollow" href="https://insum.ca/so-does-my-business-need-rest-services/">So, does my business need REST Services?</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Francis Mignault https://insum.ca/?p=12171 Thu Sep 20 2018 15:13:52 GMT-0400 (EDT) Eliminar los servicios de Windows despues de desinstalar la Base de Datos Oracle http://feedproxy.google.com/~r/DescubriendoElMundoDeOracle/~3/JYHQX0iYD-c/eliminar-los-servicios-de-windows.html <div class="MsoNormal"><span lang="ES-AR" style="font-size: 13.5pt; line-height: 107%;">Hola en esta oportunidad te dejo algo muy simple pero conveniente de saber. Cuando desinstalamos la base de datos Oracle en un entorno Windows también debemos eliminar los servicios asociados.</span><span lang="ES-AR"><o:p></o:p></span></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-g5BSEdrixVM/W6OfI--r07I/AAAAAAAAMLY/gq8KEUt0Uh4cmNhfJvKTEdwkSLiOqlawgCLcBGAs/s1600/img1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="337" data-original-width="1055" height="127" src="https://2.bp.blogspot.com/-g5BSEdrixVM/W6OfI--r07I/AAAAAAAAMLY/gq8KEUt0Uh4cmNhfJvKTEdwkSLiOqlawgCLcBGAs/s400/img1.png" width="400" /></a></div>Para ello abrimos una ventana de comandos del CMD y escribimos:<br /><br /><span style="font-family: Courier New, Courier, monospace;">C:\ ds delete &lt;nombre_del_servico&gt;</span><br /><br /><a name='more'></a><br />Por ejemplo:<br /><br /><br /><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">C:\WINDOWS\system32&gt;sc delete oracleVssWriterORCL<o:p></o:p></span></div><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">[SC] DeleteService SUCCESS<o:p></o:p></span></div><div class="MsoNormal"><br /></div><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">C:\WINDOWS\system32&gt;sc delete OracleServiceORCL<o:p></o:p></span></div><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">[SC] DeleteService SUCCESS<o:p></o:p></span></div><div class="MsoNormal"><br /></div><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">C:\WINDOWS\system32&gt;sc delete OracleOraDB18Home1TNSListener<o:p></o:p></span></div><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">[SC] DeleteService SUCCESS<o:p></o:p></span></div><div class="MsoNormal"><br /></div><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">C:\WINDOWS\system32&gt;sc delete OracleOraDB18Home1MTSRecoveryService<o:p></o:p></span></div><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">[SC] DeleteService SUCCESS<o:p></o:p></span></div><div class="MsoNormal"><br /></div><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">C:\WINDOWS\system32&gt;sc delete OracleJobSchedulerORCL<o:p></o:p></span></div><div class="MsoNormal"><span style="font-family: Courier New, Courier, monospace;">[SC] DeleteService SUCCESS<o:p></o:p></span></div><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-z7_i8MEU-9M/W6OfkYEGikI/AAAAAAAAMLg/h80Dr8hbF_wAXIDh0bdLaiJ_XQaIP4kjACLcBGAs/s1600/img2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="804" data-original-width="1223" height="262" src="https://3.bp.blogspot.com/-z7_i8MEU-9M/W6OfkYEGikI/AAAAAAAAMLg/h80Dr8hbF_wAXIDh0bdLaiJ_XQaIP4kjACLcBGAs/s400/img2.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">Y asi simplemente eliminamos los servicios de Windows.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><br /></div><br /><img src="http://feeds.feedburner.com/~r/DescubriendoElMundoDeOracle/~4/JYHQX0iYD-c" height="1" width="1" alt=""/> Clarisa J. Maman Orfali tag:blogger.com,1999:blog-1315583943401206186.post-6844195343986403255 Thu Sep 20 2018 09:26:00 GMT-0400 (EDT) When Forms to APEX Projects get thorny http://www.explorer.uk.com/blog-forms-to-apex-projects-get-thorny/ <p>Oracle Forms and Oracle Application Express (APEX) are both technologies used to build data centric applications.</p> <p>APEX uses the best of the modern web to create native web applications. Oracle Forms uses NPAPI plugins relying on Java technologies to render the page. Whilst we could go on and on describing the advantages of one over the other and believe us, there are strong opinions on both sides. We, as APEX enthusiasts, acknowledge that whilst many a Forms-to-APEX redevelopment project can be a trouble-free experience &#8211; there are some Oracle Forms features that makes the redevelopment a bit sticky.</p> <p>Many of these thorny features are due to browser security vs. a standalone client-server application and some are just old-school features which don’t have an easy equivalent in a web application.</p> <p>Let’s start with a list of Webutil features which cause a problem within APEX. The vast majority of Webutil features are going to be difficult to overcome in APEX. If you’ve never heard of Webutil, it’s an Oracle Forms Library that was built to provide access to modules which typically interact with the clients PC e.g. file system, environment variables, etc. If you try to think of any web page which tries to move files around, start programs or read information about the client PC well… that sounds a little scary, but luckily due to browser security we are protected. It’s that same browser security which prevents an APEX page from leaping outside of the browser performing those undesirable actions.</p> <p>Let’s look at our list…</p> <p><u>Running the Host command</u>: Once again, due to browser security, we are unable to run a host command from a web application, and some Oracle Forms needed it to run simple Microsoft windows apps like a calculator or even execute .bat files as part of their functionality.</p> <p><u>Manipulate client side files</u>: Typically functionality includes, creating a folder on the clients HDD, checking if it exists and creating files in that folder. It’s not uncommon to have this functionality within an Oracle Forms application, and would definitely not be the norm within a web page.</p> <p><u>Read information from the client machine</u> (Tool_Env): We can easily authenticate on an APEX application using Active Directory however the browser cannot easily detect the user currently logged to the OS (without some trickery). The username and other client data are not accessible from the browser.</p> <p><u>Read and write client side images:</u> Within Oracle Forms, you can easily read and write images on the client side without any user interaction.</p> <p><u>Integrate with client side OLE2 (e.g. Word and Excel):</u> This feature enables Oracle Forms to open a local copy of Word/Excel on the clients machine, get and set values, and provides many other features including saving and printing. For the same reasons above, your web browser will restrict any OLE2 attempts from APEX; however a typical workaround involves moving that code to the Database and have the Database Server interact with  local copies of Word/Excel. (Its not recommended)</p> <p>In Addition to WebUtil there are some general challenges when comparing a standalone client side application (Forms) to a Web Browser one (APEX).</p> <p><u>Print Screen</u>: This takes a picture of your Oracle Form and sends it to the printer; whilst attempting the same in APEX (or any web page) would send a responsive A4 layout version to the printer.</p> <p><u>Java Beans</u>: You can probably run java from your apex application, but you need to do additional work to make it work properly. In Oracle Forms this is straightforward with a java beans area.</p> <p><u>Pixel Perfect Positioning</u>: In Oracle Forms your items are placed at precise x / y coordinates; in APEX/Rest of the web, the layouts are responsive to the screen size and orientation – this is simplified for the APEX developer by using Universal Theme. Even if you can set the height and weight of items in the browser, it can differ between different browsers.</p> <p><u>Multiple Forms Open in the same Run-Time</u>: On Forms you can open another form (or even the same form) without closing the previous one.</p> <p><u>Function Keys</u>: You probably do not need the mouse to work on a form screen, this makes the user experience quite agile, when you move to a web application you lose the ability create shortcuts using function keys as these are reserved for the browser itself.</p> <p><u>POST</u>: From our experience, this is the most challenging thing to replicate in an APEX environment. Some Oracle Form applications, post the data to make it available through different forms or use it to fire some database trigger validations.</p> <p><u>Text_IO</u>: With TEXT_IO I can create a file and save it to a local folder. In a web environment, this automatic integration becomes very complicated.</p> <p>Given the above list, it’s necessary to select the best approach either to replicate that tricky functionality or identify alternatives. There is no simple rule and it is a case of adapting each thorny issue as you encounter them<span style="text-decoration: line-through;">;</span></p> <p>A Dynamic Action could be a good or a bad choice to replicate an Oracle Forms Trigger. An Interactive Grid could replace the multi-row data block or you could be in for a world of trouble. There is no tool that takes an Oracle Form and magically creates an APEX page. The approach varies from Form to Form – sometimes two Forms can become one APEX page, and one Form can become many APEX pages.</p> <p>Conclusion: Absolutely APEX is the best choice to redevelop your legacy Oracle Forms application. Developers can re-apply their SQL &amp; PL/SQL skills to APEX development – making the leap easier. The larger the forms application, the larger the project&#8230; naturally. Those thorny issues may cause you to scratch your head; but it’s unlikely that an alternative cannot be found. APEX continues to be the best option for the future direction of your forms application.</p> <p>The post <a rel="nofollow" href="http://www.explorer.uk.com/blog-forms-to-apex-projects-get-thorny/">When Forms to APEX Projects get thorny</a> appeared first on <a rel="nofollow" href="http://www.explorer.uk.com">Explorer | Award Winning UK Oracle Partner</a>.</p> Devon Page http://www.explorer.uk.com/?p=7570 Thu Sep 20 2018 07:50:51 GMT-0400 (EDT) Remove duplicate from APEX collection http://www.grassroots-oracle.com/2018/09/remove-duplicate-from-oracle-apex-collection.html One of my favourite SQL analytic functions is <code>row_number()</code>, and I've used it in the past to identify, then remove duplicates.<br /><br />In this case, I have an APEX collection that represents a session based view history of products/people/events, or whatever your users might be browsing.<br /><br />I've created an option to consolidate that view history, and remove any record you might have opened more than once.<br /><br />Collections are a little hard to play with outside of APEX, so I use the <a href="https://oos-utils.readthedocs.io/en/latest/oos_util_apex/#create_session" target="_blank">create session</a> procedure in the OraOpenSource libraries to simulate an APEX session within SQL Developer.<br /><br /><code>exec oos_util_apex.create_session(120,'WESLEYS')</code><br /><br />For my test case I simulate adding a few entries in my collection, varying a date column slightly.<br /><pre class="brush:sql">begin<br />apex_collection.create_or_truncate_collection('TEST');<br />apex_collection.add_member('TEST', 'Scott', p_d001 =&gt; sysdate - 5);<br />apex_collection.add_member('TEST', 'Dmitri', p_d001 =&gt; sysdate - 2);<br />apex_collection.add_member('TEST', 'Lino', p_d001 =&gt; sysdate - 4);<br />apex_collection.add_member('TEST', 'Scott', p_d001 =&gt; sysdate - 3);<br />apex_collection.add_member('TEST', 'Joel', p_d001 =&gt; sysdate - 2);<br />apex_collection.add_member('TEST', 'Sabine', p_d001 =&gt; sysdate - 4);<br />apex_collection.add_member('TEST', 'Penny', p_d001 =&gt; sysdate - 5);<br />apex_collection.add_member('TEST', 'Scott', p_d001 =&gt; sysdate - 6);<br />apex_collection.add_member('TEST', 'Jackie', p_d001 =&gt; sysdate - 3);<br />apex_collection.add_member('TEST', 'Joel', p_d001 =&gt; sysdate - 1);<br />end;<br />/</pre><br />Here is a query that will use an analytical function to add a computed column that identifies the most recent entry for any name, and assign it a 1. Any subsequent entries for that name will get a 2, 3, 4 etc.<br /><pre class="brush:sql">select seq_id, c001 name<br /> ,row_number() over <br /> (partition by c001 -- look for duplicates in this set of columns<br /> order by d001 desc -- put records I want to keep first<br /> ) rn<br /> ,d001 dt<br />from apex_collections<br />where collection_name = 'TEST'<br />order by name;</pre><br />In this case, seq_id 1, 5 &amp; 6 represent the records I want to trim from the list.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-CONnenOQB5Q/W6ETLF1od_I/AAAAAAAAT68/W52fJOz58CkMvoqeFYHiDsEJpnyO9hDEgCLcBGAs/s1600/coll_cnt.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="222" data-original-width="217" src="https://2.bp.blogspot.com/-CONnenOQB5Q/W6ETLF1od_I/AAAAAAAAT68/W52fJOz58CkMvoqeFYHiDsEJpnyO9hDEgCLcBGAs/s1600/coll_cnt.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Duplicate entries highlighted</td></tr></tbody></table><br /><div class="separator" style="clear: both; text-align: center;"></div>Turn the query into an in-line view to filter out any records where the row_number() is not 1, as we are not allowed to have window functions in the where clause (ORA-30483).<br /><pre class="brush:sql">select seq_id, rn from<br /> (select seq_id, row_number() over (partition by c001 order by d001 desc) rn<br /> from apex_collections<br /> where collection_name = 'TEST'<br />) where rn != 1;<br /><br /> SEQ_ID RN<br />---------- ----------<br /> 6 2<br /> 1 2<br /> 5 3</pre><br />Reverse the order by, and I'll keep the first entry instead.<br />Got more columns that signify uniqueness? Expand the partition by clause.<br /><br />A standard aggregate query would be able to identify the names of those duplicates, plus how many you have, but no set of records with the unique identifiers to remove. Using <code>min(seq_id)</code> would be insufficient once you more than two entries.<br /><pre class="brush:sql">select count(*), c001 name, min(seq_id)<br />from apex_collections<br />where collection_name = 'TEST'<br />group by c001<br />having count(*) &gt; 1<br /><br /> C NAME MN<br />--- ---------- ---<br /> 2 Joel 6<br /> 3 Scott 1</pre><br />We can fold the analytical query into a PL/SQL loop and remove the duplicates from my collection.<br /><pre class="brush:sql">begin<br /> &lt;&lt; remove_duplicates &gt;&gt;<br /> for r_rec in (<br /> select seq_id, rn from<br /> (select seq_id, row_number() over (partition by c001 order by d001 desc) rn<br /> from apex_collections<br /> where collection_name = 'TEST'<br /> ) where rn != 1<br /> ) loop<br /> APEX_COLLECTION.DELETE_MEMBER<br /> (p_collection_name =&gt; 'TEST'<br /> ,p_seq =&gt; r_rec.seq_id);<br /> end loop remove_duplicates;<br />end anon;<br />/</pre><br />Where the resulting collection is minus the older duplicate.<br /><pre>SEQ_ID NAME RN DT <br />---------- ---------- --- ----------<br /> 2 Dmitri 1 2018-09-16<br /> 9 Jackie 1 2018-09-15<br /> 10 Joel 1 2018-09-17<br /> 3 Lino 1 2018-09-14<br /> 8 Penny 1 2018-09-13<br /> 7 Sabine 1 2018-09-14<br /> 4 Scott 1 2018-09-15</pre><br />Of course, this is not limited to APEX collections, but it gave me a chance to play with more toys. Scott Wesley tag:blogger.com,1999:blog-4818542164384221282.post-5654382881766689240 Tue Sep 18 2018 20:47:00 GMT-0400 (EDT) Exactly a Year http://c2anton.blogspot.com/2018/09/exactly-year.html Wow, this is awful. It looks like it has been OVER a year since I last made a blog post. That's really inexcusable. OVER a year would be way too long. Fortunately, it turns out that I did not go OVER a year between blog posts. I just switched to the Insum blog. You can read my APEX Sitemap blog there:<br /><br /><a href="https://insum.ca/search-engine-optimization-with-apex-creating-a-google-sitemap/">https://insum.ca/search-engine-optimization-with-apex-creating-a-google-sitemap/</a><br /><br />&nbsp;As astute readers will note, I did not cross the year boundary between blog posts. Anonymous tag:blogger.com,1999:blog-24686153.post-6663098177840739620 Tue Sep 18 2018 17:31:00 GMT-0400 (EDT) Get to the facts – Your Business Will Be the Better For It https://insum.ca/get-to-the-facts-your-business-will-be-the-better-for-it/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/09/Get-to-the-Facts-Your-Business-will-be-the-Better-For-It-Insum-100x100.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Get to the Facts -Your Business will be the Better For It-Insum" srcset="https://insum.ca/wp-content/uploads/2018/09/Get-to-the-Facts-Your-Business-will-be-the-Better-For-It-Insum-100x100.jpg 100w, https://insum.ca/wp-content/uploads/2018/09/Get-to-the-Facts-Your-Business-will-be-the-Better-For-It-Insum-150x150.jpg 150w, https://insum.ca/wp-content/uploads/2018/09/Get-to-the-Facts-Your-Business-will-be-the-Better-For-It-Insum-600x600.jpg 600w, https://insum.ca/wp-content/uploads/2018/09/Get-to-the-Facts-Your-Business-will-be-the-Better-For-It-Insum-300x300.jpg 300w, https://insum.ca/wp-content/uploads/2018/09/Get-to-the-Facts-Your-Business-will-be-the-Better-For-It-Insum-50x50.jpg 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p><em>Lack of time, lack of knowledge and too many preconceptions can hold back your business, especially when it comes to its technological evolution. Where does this problem come from? How can you solve it? Start by seeking out the facts.  </em></p> <p>These days, it’s getting harder to rely on newspapers, social networks, radio and television to understand political or economic issues. The saying “Stick to the facts” is increasingly maligned. Which version of the facts would you like?</p> <p>So many play the game of using half-truths or even outright lies to convince their audience of the relevance and accuracy of their ideology. In this era of being bombarded from all sides with contradictory information and fake news, I would even say this has become a major societal challenge.</p> <p>Clearly, ordinary mortals must be ever more discerning and do their best to rely on facts and not some third party’s interpretation of them</p> <h4><strong>It’s the Same in IT</strong></h4> <p>It’s pretty much the same in our industry, too. In the ever-fast-moving realm of IT, one must be careful not to be influenced by information that is often incomplete or erroneous.</p> <p>It’s sad when corporate executives make decisions (sometimes very expensive ones), without taking the proper time to mull them over. Sadder still when they rely on hearsay from specialists, who are often in good faith but who can push for less efficient solutions and even invoke false pretences to discredit proven innovations, simply out of dogmatism or ignorance.</p> <p>No technological solution is perfect, I agree, but be we should be wary of the apostles of the status quo. Where would we be today if accountants had resisted computerization and stuck to the reliable, tried and tested abacus? I’m exaggerating of course, but you’ll agree that it’s amazing to see technology experts unabashedly determining the inability of a new tool to solve business problems without even bench-testing it. Or, at the very least, made some calls to known references to assess the tool’s potential.</p> <p>So, if it’s technology’s nature to be constantly evolving, what drives these &#8216;experts&#8217; to spread false information and hold things back?</p> <h4><strong>Lack of Time</strong></h4> <p>Huge demand for digitization or modernization of business systems puts relentless pressure on IT and development teams. These end up crumbling under the weight of their work. Lack of time leads to tough choices. For example, foregoing research into productivity tools and missing out on time and money-saving benefits these could bring to the organization. The initial investment in time and careful research is perceived as too taxing.  Yet, this prevents them from better equipping themselves (and their company) for the future.</p> <h4><strong>Lack of Knowledge</strong></h4> <p>Due to natural insecurity, some people don’t want to question decisions that often date back several years. Lack of continuing education and deficient natural curiosity mean that they’ll always be reluctant to change, for lack of knowledge.</p> <h4><strong>Risk Tolerance</strong></h4> <p>Making technological changes in an organization is fraught with danger and many administrations fall victim to the phrase &#8216;If it works, don’t fix it&#8217;. This way of managing can lead to a significant technological delay and make a company uncompetitive. You’ve got to know how to mitigate the risk and proceed in stages to minimize it, because a well-calculated risk can bring very large benefits.</p> <h4><strong>The False Impression</strong></h4> <p>&#8216;If it&#8217;s simple, it&#8217;s not good&#8217; is another expression often heard in our wonderful techno setting. This kind of logic automatically discredits all &#8216;RAD&#8217; or &#8216;Low code&#8217; type solutions. In complete contradiction to this, we’re daily noting a strong adoption of these technologies by the business community to solve critical operational issues.</p> <p>In short, lack of information coupled with persistent biases deprives companies of innovative, affordable and proven solutions.</p> <p>&nbsp;</p> <h2>Time to Thwart Immobilism</h2> <p>With a little time, curiosity and energy, it’s possible to thwart this immobilism. It is possible to overcome false judgments, lack of knowledge and bad recommendations. Here&#8217;s how.</p> <h4><strong>Go to the Source</strong></h4> <p>Ask the supplier about the tool. Check out the website, the case studies, the white papers and the &#8216;statement of direction&#8217;. Make sure the company is serious and lists its customers. Ensure the long-term viability of the solution and its costs.</p> <h4><strong>Read Blogs</strong></h4> <p>Blogs are teeming with relevant information, but it’s also important to ensure the author&#8217;s credibility with the target community. A large sample of content helps better filter the relevance of the information.</p> <h4><strong>Watch Webinars</strong></h4> <p>A webinar that speaks directly to your issues and answers your questions can be very useful. Don’t hesitate to contact the presenter to deepen the topic and make sure you understand how your issues will be addressed.</p> <h4><strong>Attend User Conferences</strong></h4> <p>User conferences with multiple information sessions are extremely useful. Although they can be costly to attend, they allow you to speak directly to the vendor, developers, and service providers. They are the best places to find multiple answers in a very short time.</p> <h4><strong>Talk to Customers, Peers</strong></h4> <p>Nothing beats the experience of a company that has just completed a successful IT selection process and implementation. Request references from the supplier so that you can ask all your questions in a neutral manner. Nothing is perfect, but to know in advance certain pitfalls decreases the level of stress.</p> <h4><strong>Ask for a Proof of Concept</strong></h4> <p>Don&#8217;t fall into the trap of wanting to do everything at once. A proof of concept on a small application enables you to put the infrastructure in place and test the new technology in its organizational context. A small-scale success bodes well for the future and it&#8217;s extremely reassuring.</p> <h4><strong>Be Supported</strong></h4> <p>It is very difficult to master a new tool as soon as it&#8217;s first used. Don&#8217;t hesitate to take advice from companies that can give you training and ongoing support. Building on a solid foundation makes for the long-term viability of the solution. Conversely, a lack of experience can be disastrous and lead to the abandonment of the solution by thinking that it does not meet the needs. Good coaching can save a lot of time, money and frustration and thus ensure the success of the project.</p> <h4><strong>Get to the Facts</strong></h4> <p>It is clear that whatever the choice of your next technological tool, you will have to be wary of hasty conclusions and minimal research. Be open to investing a minimum of time and money in order to position yourself favourably for your next challenges. Innovate, because the survival of your business depends on it.</p> <p>&nbsp;</p> <p><strong><em>Oracle Application Express (APEX) can be used to generate functioning applications </em></strong><strong><em>with very little coding, resulting in unequaled ROI for your business. It will allow your </em></strong><strong><em>developers to build robust, complex and highly scalable applications, fast. Find out more. <a href="https://insum.ca/contact/">Contact us.</a></em></strong></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>The post <a rel="nofollow" href="https://insum.ca/get-to-the-facts-your-business-will-be-the-better-for-it/">Get to the facts – Your Business Will Be the Better For It</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Michel St-Amour https://insum.ca/?p=13127 Tue Sep 18 2018 13:10:21 GMT-0400 (EDT) Get to the facts – Your Business Will Be the Better For It https://insum.ca/get-to-the-facts-your-business-will-be-the-better-for-it/ <p><em>Lack of time, lack of knowledge and too many preconceptions can hold back your business, especially when it comes to its technological evolution. Where does this problem come from? How can you solve it? Start by seeking out the facts.  </em></p> <p>These days, it’s getting harder to rely on newspapers, social networks, radio and television to understand political or economic issues. The saying “Stick to the facts” is increasingly maligned. Which version of the facts would you like?</p> <p>So many play the game of using half-truths or even outright lies to convince their audience of the relevance and accuracy of their ideology. In this era of being bombarded from all sides with contradictory information and fake news, I would even say this has become a major societal challenge.</p> <p>Clearly, ordinary mortals must be ever more discerning and do their best to rely on facts and not some third party’s interpretation of them</p> <h4><strong>It’s the Same in IT</strong></h4> <p>It’s pretty much the same in our industry, too. In the ever-fast-moving realm of IT, one must be careful not to be influenced by information that is often incomplete or erroneous.</p> <p>It’s sad when corporate executives make decisions (sometimes very expensive ones), without taking the proper time to mull them over. Sadder still when they rely on hearsay from specialists, who are often in good faith but who can push for less efficient solutions and even invoke false pretences to discredit proven innovations, simply out of dogmatism or ignorance.</p> <p>No technological solution is perfect, I agree, but be we should be wary of the apostles of the status quo. Where would we be today if accountants had resisted computerization and stuck to the reliable, tried and tested abacus? I’m exaggerating of course, but you’ll agree that it’s amazing to see technology experts unabashedly determining the inability of a new tool to solve business problems without even bench-testing it. Or, at the very least, made some calls to known references to assess the tool’s potential.</p> <p>So, if it’s technology’s nature to be constantly evolving, what drives these &#8216;experts&#8217; to spread false information and hold things back?</p> <h4><strong>Lack of Time</strong></h4> <p>Huge demand for digitization or modernization of business systems puts relentless pressure on IT and development teams. These end up crumbling under the weight of their work. Lack of time leads to tough choices. For example, foregoing research into productivity tools and missing out on time and money-saving benefits these could bring to the organization. The initial investment in time and careful research is perceived as too taxing.  Yet, this prevents them from better equipping themselves (and their company) for the future.</p> <h4><strong>Lack of Knowledge</strong></h4> <p>Due to natural insecurity, some people don’t want to question decisions that often date back several years. Lack of continuing education and deficient natural curiosity mean that they’ll always be reluctant to change, for lack of knowledge.</p> <h4><strong>Risk Tolerance</strong></h4> <p>Making technological changes in an organization is fraught with danger and many administrations fall victim to the phrase &#8216;If it works, don’t fix it&#8217;. This way of managing can lead to a significant technological delay and make a company uncompetitive. You’ve got to know how to mitigate the risk and proceed in stages to minimize it, because a well-calculated risk can bring very large benefits.</p> <h4><strong>The False Impression</strong></h4> <p>&#8216;If it&#8217;s simple, it&#8217;s not good&#8217; is another expression often heard in our wonderful techno setting. This kind of logic automatically discredits all &#8216;RAD&#8217; or &#8216;Low code&#8217; type solutions. In complete contradiction to this, we’re daily noting a strong adoption of these technologies by the business community to solve critical operational issues.</p> <p>In short, lack of information coupled with persistent biases deprives companies of innovative, affordable and proven solutions.</p> <p>&nbsp;</p> <h2>Time to Thwart Immobilism</h2> <p>With a little time, curiosity and energy, it’s possible to thwart this immobilism. It is possible to overcome false judgments, lack of knowledge and bad recommendations. Here&#8217;s how.</p> <h4><strong>Go to the Source</strong></h4> <p>Ask the supplier about the tool. Check out the website, the case studies, the white papers and the &#8216;statement of direction&#8217;. Make sure the company is serious and lists its customers. Ensure the long-term viability of the solution and its costs.</p> <h4><strong>Read Blogs</strong></h4> <p>Blogs are teeming with relevant information, but it’s also important to ensure the author&#8217;s credibility with the target community. A large sample of content helps better filter the relevance of the information.</p> <h4><strong>Watch Webinars</strong></h4> <p>A webinar that speaks directly to your issues and answers your questions can be very useful. Don’t hesitate to contact the presenter to deepen the topic and make sure you understand how your issues will be addressed.</p> <h4><strong>Attend User Conferences</strong></h4> <p>User conferences with multiple information sessions are extremely useful. Although they can be costly to attend, they allow you to speak directly to the vendor, developers, and service providers. They are the best places to find multiple answers in a very short time.</p> <h4><strong>Talk to Customers, Peers</strong></h4> <p>Nothing beats the experience of a company that has just completed a successful IT selection process and implementation. Request references from the supplier so that you can ask all your questions in a neutral manner. Nothing is perfect, but to know in advance certain pitfalls decreases the level of stress.</p> <h4><strong>Ask for a Proof of Concept</strong></h4> <p>Don&#8217;t fall into the trap of wanting to do everything at once. A proof of concept on a small application enables you to put the infrastructure in place and test the new technology in its organizational context. A small-scale success bodes well for the future and it&#8217;s extremely reassuring.</p> <h4><strong>Be Supported</strong></h4> <p>It is very difficult to master a new tool as soon as it&#8217;s first used. Don&#8217;t hesitate to take advice from companies that can give you training and ongoing support. Building on a solid foundation makes for the long-term viability of the solution. Conversely, a lack of experience can be disastrous and lead to the abandonment of the solution by thinking that it does not meet the needs. Good coaching can save a lot of time, money and frustration and thus ensure the success of the project.</p> <h4><strong>Get to the Facts</strong></h4> <p>It is clear that whatever the choice of your next technological tool, you will have to be wary of hasty conclusions and minimal research. Be open to investing a minimum of time and money in order to position yourself favourably for your next challenges. Innovate, because the survival of your business depends on it.</p> <p>&nbsp;</p> <p><strong><em>Oracle Application Express (APEX) can be used to generate functioning applications </em></strong><strong><em>with very little coding, resulting in unequaled ROI for your business. It will allow your </em></strong><strong><em>developers to build robust, complex and highly scalable applications, fast. Find out more. <a href="https://insum.ca/contact/">Contact us.</a></em></strong></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>The post <a rel="nofollow" href="https://insum.ca/get-to-the-facts-your-business-will-be-the-better-for-it/">Get to the facts – Your Business Will Be the Better For It</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Michel St-Amour https://insum.ca/?p=12152 Tue Sep 18 2018 11:52:31 GMT-0400 (EDT) Ladies and gentleman: start your engines! http://nielsdebr.blogspot.com/2018/09/ladies-and-gentleman-start-your-engines.html <div><br /></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-dOkET_RCd-A/W6C2KwOoOOI/AAAAAAAAAnM/tYf5bvsRUyELpPpa_9ThYrdCfNrjZedPgCLcBGAs/s1600/Screen%2BShot%2B2018-09-18%2Bat%2B10.14.32.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="323" data-original-width="1392" height="91" src="https://2.bp.blogspot.com/-dOkET_RCd-A/W6C2KwOoOOI/AAAAAAAAAnM/tYf5bvsRUyELpPpa_9ThYrdCfNrjZedPgCLcBGAs/s400/Screen%2BShot%2B2018-09-18%2Bat%2B10.14.32.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div><br /></div><div>I'm happy to announce the official start of <a href="https://apex.doag.org/en/speakers/speakers/">Call for Papers</a> for our 5th edition of DOAG <a href="https://apex.doag.org/">APEX Connect</a>. Until 8-NOV, everybody can submit their abstract for a 45 minute presentation (incl. Q&amp;A) about Oracle Application Express, SQL, PL/SQL or JavaScript. The conference will take place in Bonn from 07-MAY up to 09-MAY at the flashy <a href="https://www.kamehabonn.de/">Kameha Grand Hotel</a>. As a presenter, you will get free entrance during the whole conference including all DOAG events that take place.</div><div>If you are not sure what it takes to submit a compelling abstract, I suggest you have a look at our guide: <a href="https://apex.doag.org/en/news/details/?tx_news_pi1%5Bnews%5D=1773&amp;tx_news_pi1%5Bcontroller%5D=News&amp;tx_news_pi1%5Baction%5D=detail&amp;cHash=585056d1c5bb7f55c1018ca21f465e1c">Eleven steps to a succesful submission of your presentation</a>. I encourage everybody to submit an abstract, as it is a great experience to be part of the conference as a presenter.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-znTZw11fmu8/W6CzGtcV-OI/AAAAAAAAAm0/I1EXouVKLIEUKpEEJmfmP67wL9kXhMIgwCEwYBhgL/s1600/Universal.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="884" data-original-width="1600" height="220" src="https://1.bp.blogspot.com/-znTZw11fmu8/W6CzGtcV-OI/AAAAAAAAAm0/I1EXouVKLIEUKpEEJmfmP67wL9kXhMIgwCEwYBhgL/s400/Universal.jpg" width="400" /></a></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"></div><div><br /></div><div>Due to time constraints, Christian Schwitalla and Peter Raganitsch had to gave up their seat in the conference committee. All I can say is: THANK YOU for your hard work in your spare time and making APEX Connect to what it is! +1</div><div><br /></div><div>Let me take this opportunity to welcome our newest members in the conference committee: Sabine Heimsath will cover the SQL &amp; PL/SQL track and Tobias Arnhold the APEX track. Together with Kai Donato (JavaScript) and Simone Fischer (Project Lead) we are determined to bring APEX Connect 2019 to the next level. A sneak preview of what we have planned will be uncovered at the DOAG conference in Nürnberg, so stay tuned.</div><div><br /></div><div><br /></div><div><br /></div> Niels de Bruijn tag:blogger.com,1999:blog-4976295728511735178.post-8499834827419595240 Tue Sep 18 2018 10:21:00 GMT-0400 (EDT) Ladies and gentleman: start your engines! http://nielsdebr.blogspot.com/2018/09/ladies-and-gentleman-start-your-engines.html <div><br /></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-dOkET_RCd-A/W6C2KwOoOOI/AAAAAAAAAnM/tYf5bvsRUyELpPpa_9ThYrdCfNrjZedPgCLcBGAs/s1600/Screen%2BShot%2B2018-09-18%2Bat%2B10.14.32.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="323" data-original-width="1392" height="91" src="https://2.bp.blogspot.com/-dOkET_RCd-A/W6C2KwOoOOI/AAAAAAAAAnM/tYf5bvsRUyELpPpa_9ThYrdCfNrjZedPgCLcBGAs/s400/Screen%2BShot%2B2018-09-18%2Bat%2B10.14.32.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div><br /></div><div>I'm happy to announce the official start of <a href="https://apex.doag.org/en/speakers/speakers/">Call for Papers</a> for our 5th edition of DOAG <a href="https://apex.doag.org/">APEX Connect</a>. Until 8-NOV, everybody can submit their abstract for a 45 minute presentation (incl. Q&amp;A) about Oracle Application Express, SQL, PL/SQL or JavaScript. The conference will take place in Bonn from 07-MAY up to 09-MAY at the flashy <a href="https://www.kamehabonn.de/">Kameha Grand Hotel</a>. As a presenter, you will get free entrance during the whole conference including all DOAG events that take place.</div><div>If you are not sure what it takes to submit a compelling abstract, I suggest you have a look at our guide: <a href="https://apex.doag.org/en/news/details/?tx_news_pi1%5Bnews%5D=1773&amp;tx_news_pi1%5Bcontroller%5D=News&amp;tx_news_pi1%5Baction%5D=detail&amp;cHash=585056d1c5bb7f55c1018ca21f465e1c">Eleven steps to a succesful submission of your presentation</a>. I encourage everybody to submit an abstract, as it is a great experience to be part of the conference as a presenter.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-znTZw11fmu8/W6CzGtcV-OI/AAAAAAAAAm0/I1EXouVKLIEUKpEEJmfmP67wL9kXhMIgwCEwYBhgL/s1600/Universal.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="884" data-original-width="1600" height="220" src="https://1.bp.blogspot.com/-znTZw11fmu8/W6CzGtcV-OI/AAAAAAAAAm0/I1EXouVKLIEUKpEEJmfmP67wL9kXhMIgwCEwYBhgL/s400/Universal.jpg" width="400" /></a></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"></div><div><br /></div><div>Due to time constraints, Christian Schwitalla and Peter Raganitsch had to gave up their seat in the conference committee. All I can say is: THANK YOU for your hard work in your spare time and making APEX Connect to what it is! +1</div><div><br /></div><div>Let me take this opportunity to welcome our newest members in the conference committee: Sabine Heimsath will cover the SQL &amp; PL/SQL track and Tobias Arnhold the APEX track. Together with Kai Donato (JavaScript) and Simone Fischer (Project Lead) we are determined to bring APEX Connect 2019 to the next level. A sneak preview of what we have planned will be uncovered at the DOAG conference in Nürnberg, so stay tuned.</div><div><br /></div><div><br /></div><div><br /></div> Niels de Bruijn tag:blogger.com,1999:blog-4976295728511735178.post-8499834827419595240 Tue Sep 18 2018 10:21:00 GMT-0400 (EDT) ODTUG Board of Directors Nominations Close in 3 Days! https://www.odtug.com/p/bl/et/blogaid=828&source=1 This is your opportunity to nominate the person you believe will best provide leadership and policy development for ODTUG. For more information, please click here. All nominees must be paid ODTUG members in good standing. ODTUG https://www.odtug.com/p/bl/et/blogaid=828&source=1 Mon Sep 17 2018 09:56:58 GMT-0400 (EDT) Hide region if no data found http://www.grassroots-oracle.com/2018/09/orcle-apex-hide-region-if-no-data-found.html I have a diagnostic page where I hide classic report regions that aren't relevant - ie, have no data returned.<br /><br />Here I create a dynamic action that executes After Refresh of the relevant region.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-ZnUEPcskIfA/W58Aunkj-oI/AAAAAAAAT6I/PIA29f7-bSgR9GPnYdniyGyUTZF6pkXgwCLcBGAs/s1600/ar_nodatafound.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="291" data-original-width="342" src="https://3.bp.blogspot.com/-ZnUEPcskIfA/W58Aunkj-oI/AAAAAAAAT6I/PIA29f7-bSgR9GPnYdniyGyUTZF6pkXgwCLcBGAs/s1600/ar_nodatafound.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Dynamic Action definition</td></tr></tbody></table><br />The&nbsp;<i>client-side&nbsp;</i>condition evaluates the presence of the <code>.nodatafound</code> class within a classic report, which is present only when no records are returned.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-5Sl3yZCiuJA/W58ByYHJ-UI/AAAAAAAAT6c/wuROsOtXlyQE5m-6s9P6hBROI1UBqKFwwCLcBGAs/s1600/ar_class.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="216" data-original-width="620" src="https://1.bp.blogspot.com/-5Sl3yZCiuJA/W58ByYHJ-UI/AAAAAAAAT6c/wuROsOtXlyQE5m-6s9P6hBROI1UBqKFwwCLcBGAs/s1600/ar_class.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Inspect element of region with no records</td></tr></tbody></table><br />The dynamic action then shows/hides the region, depending on the result of the JavaScript expression:<br /><code>$(this.triggeringElement).find('.nodatafound').length == 1</code><br /><br />The triggering element is the region, so find the class within that region, count the result set, and compare to value 1.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-CA658Ohynp4/W58AumW0ZSI/AAAAAAAAT6M/5WTeqVs3ArMtuLZ9MHuvAUPQ9NFDNYDMACLcBGAs/s1600/ar_da.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="132" data-original-width="168" src="https://4.bp.blogspot.com/-CA658Ohynp4/W58AumW0ZSI/AAAAAAAAT6M/5WTeqVs3ArMtuLZ9MHuvAUPQ9NFDNYDMACLcBGAs/s1600/ar_da.png" /></a></div><br />Instead of the region itself, this could relate to other components only relevant when records are returned.<br /><br />As Maxime pointed out in the comments, here I was focussing on classic report regions. The relevant classes you may be looking for include:<br /><br /><ul><li>Classic Report (versatile): <code>nodatafound</code></li><li>Interactive Report (IR): <code>a-IRR-noDataMsg</code></li><li>Interactive Grid (IG): <code>a-GV-noDataMsg</code></li></ul><br />This can mean there is no need for a server-side condition to test for existence.<br /><br />With this dynamic action, the region could re-appear upon refresh with results, making the page more interactive without requiring full page submission. Scott Wesley tag:blogger.com,1999:blog-4818542164384221282.post-6799938654785814523 Sun Sep 16 2018 21:29:00 GMT-0400 (EDT) Clearing error state of an Interactive Grid column https://apextips.blogspot.com/2018/09/clearing-error-state-of-interactive.html <br />On a recent project, there was a requirement that when they save data they don't want any validations to come into play, and it's only when they go to submit the transaction that validation errors should appear.<br /><br />So I had a set up where the Save button (AJAX) was removed from interactive grid toolbar, and the form page form has two buttons: "SAVE" and "SUBMIT".<br /><br /><br />Following this design pattern, if I click SUBMIT with a validation failure in the data, the relevant row would be highlighted in the interactive grid:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-q_8CYdHaLBk/W55xWihAzII/AAAAAAAAI20/TeB53MVNmeQpHALij3f5F_u1zmdlbG7YgCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-09-16%2B11-05-40.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="153" data-original-width="358" src="https://1.bp.blogspot.com/-q_8CYdHaLBk/W55xWihAzII/AAAAAAAAI20/TeB53MVNmeQpHALij3f5F_u1zmdlbG7YgCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-09-16%2B11-05-40.png" /></a></div><br />Now as a user I decide I don't want to submit the page anymore, but rather just do a save. <br /><br />However, clicking save I won't be able to get the page submitted without changing the value of that field (or as an alternate situation, the validation may be dependent on some other page item, which I could have corrected but still the error state of the grid/line will be present). APEX will not submit the page and I would get an error that I need to correct any errors first.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-11I47z8cicA/W55xwQ9CQ6I/AAAAAAAAI28/GzXzsrFlrmMaHuZ6iRrx8A7fkrAsr0LTQCLcBGAs/s1600/Screenshot%2Bfrom%2B2018-09-16%2B11-07-13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="166" data-original-width="404" height="130" src="https://2.bp.blogspot.com/-11I47z8cicA/W55xwQ9CQ6I/AAAAAAAAI28/GzXzsrFlrmMaHuZ6iRrx8A7fkrAsr0LTQCLcBGAs/s320/Screenshot%2Bfrom%2B2018-09-16%2B11-07-13.png" width="320" /></a></div><br />So, what we need to do is change the button behaviour to first clear the error state to ensure I can submit the page.<br /><br />If you are using interactive grid, you hopefully know it is built up of multiple components, and one such component is the model (apex.model). When our validation caused a failure, the model has flagged it as not valid. So, before we submit/save the page, we need to clear that validity state which will enable the page submission to occur.<br /><br />So, rather than a straight submit button, we can alter our button to run the following JavaScript code (submitting the page only after our data is set to a valid state):<br /><br /><pre>var gridView = apex.region("emp").widget().interactiveGrid("getViews", "grid"),<br /> model = gridView.model;<br /><br />model.forEach(function clearIgErrorState(record, recordIndex, recordId){<br /> model.setValidity("valid", recordId, "COMM")<br />});<br /><br />apex.page.submit("SAVE")<br /></pre><br />In this example, I am specifically making it so that the "COMM" column is no logger flagged as having an error.<br /><br />To see this function specs, refer to the <a href="https://docs.oracle.com/database/apex-18.1/AEXJS/model.html#setValidity">documentation</a> to see what other inputs it accepts. trent tag:blogger.com,1999:blog-8785176694082881912.post-6475927353572700462 Sun Sep 16 2018 17:02:00 GMT-0400 (EDT) Updating Exadata Software summary http://jaffardba.blogspot.com/2018/09/updating-exadata-software-summary.html <div dir="ltr" style="text-align: left;" trbidi="on"><div style="text-align: justify;">Updating an Exadata software is one of the crucial tasks for any Database Machine Administrator (DMA). Though not necessarily one has to patch the environments whenever there is a new patch released by Oracle, but, it is highly recommended to patch the systems at least twice a year to fix any known &amp;unknown bugs, security vulnerabilities and other issues.</div><br /><div style="text-align: justify;">This blog post summarizes the overall overview of software updates on an Exadata Database Machine. The post explains what components are needed the updates, the update order of components, pre-requisites and etc.</div><br />Typically, Exadata database machine updates are divided in the following categories:<br /><br /><ul style="text-align: left;"><li>Exadata Infrastructure Software&nbsp;</li><li>Grid Infrastructure and Oracle Database Software</li></ul><br />Updating the Exadata Software comprises of following components:<br /><br /><ul style="text-align: left;"><li>Storage Servers</li><li>Database Servers</li><li>InfiniBand Switches</li></ul><div>Software upgrade for Cell and DB nodes typically contains the updates for the following:</div><div><ul style="text-align: left;"><li>OLE OS</li><li>Exadata Software</li><li>Firmware (Disk, Flash, RAID Controller, HCA, ILOM etc)</li></ul></div><br /><u>Pre-requisites</u><br /><br />The following pre-upgrade activities are highly recommended before upgrading the Exadata software in any environment:<br /><br /><ul style="text-align: left;"><li>Review MOS Doc 888828.1 and download the target version software</li><li>Download observer.patch.zip from MOS Doc 1553103.1</li><li>Review MOS Doc 1270094.1 for any critical issues</li><li>Run the latest version of ExaCHK utility. Fix any FAIL and WARNINGS issues reported in the ExaCHK report. Also, review version recommendations in the MAA scoreboard section</li><li>Ensure you have latest upgrade/patching utilities, such as, patchmgr, opatch etc. (MOS Doc 1070954.1)</li><li>Perform prerequisites checks</li><li>Backup the Exadata database servers before the update&nbsp;</li></ul><div><u>Rolling vs Non-rolling upgrades</u></div><div><br /></div><div>Software updates can be performed online or offline (rolling or non-rolling) fashion. For online updates, it is highly recommended ASM high level disk group redundancy to avoid any data or service loss.</div><div><br /></div><div>As part of best practices, the following is update order is recommended and treated as safe:</div><div><ol style="text-align: left;"><li>GI and Oracle Database home</li><li>Database Servers</li><li>Storage Servers</li><li>IB Switches</li></ol><div><u>patchmgr update utiity</u></div></div><div><br /></div><div>patchmgr update utility is used to patch the Exadata infrastructure components. &nbsp;Following are the capabilities of patchmgr:</div><div><ul style="text-align: left;"><li>Single invocation for Database servers, storage servers and IB Switches</li><li>updates firmware, OS and Exadata softwares</li><li>Online update advantage</li></ul><div>Conclusion: Though the procedure looks pretty straight forward &amp; simply when reading, with my past experience, patching each environments comes up with surprises and we need to be ready, unless we are very lucky on the particular day to have a smooth patching experience.</div></div><div><br /></div><div>In the upcoming posts, I will talk about how to use patchmgr and other update utilizes to update Exadata software, Database, Storage servers and IB Switches.</div></div> The Human Fly tag:blogger.com,1999:blog-19771507.post-4775139811026040505 Sat Sep 15 2018 08:06:00 GMT-0400 (EDT) Search Engine Optimization With APEX: Creating a Google Sitemap https://insum.ca/search-engine-optimization-with-apex-creating-a-google-sitemap/ <p><img width="100" height="100" src="https://insum.ca/wp-content/uploads/2018/09/Search-Engine-Optimization-With-APEX-Creating-a-Google-Sitemap-100x100.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Search Engine Optimization With APEX Creating a Google Sitemap" srcset="https://insum.ca/wp-content/uploads/2018/09/Search-Engine-Optimization-With-APEX-Creating-a-Google-Sitemap-100x100.jpg 100w, https://insum.ca/wp-content/uploads/2018/09/Search-Engine-Optimization-With-APEX-Creating-a-Google-Sitemap-150x150.jpg 150w, https://insum.ca/wp-content/uploads/2018/09/Search-Engine-Optimization-With-APEX-Creating-a-Google-Sitemap-1000x1000.jpg 1000w, https://insum.ca/wp-content/uploads/2018/09/Search-Engine-Optimization-With-APEX-Creating-a-Google-Sitemap-600x600.jpg 600w, https://insum.ca/wp-content/uploads/2018/09/Search-Engine-Optimization-With-APEX-Creating-a-Google-Sitemap-300x300.jpg 300w, https://insum.ca/wp-content/uploads/2018/09/Search-Engine-Optimization-With-APEX-Creating-a-Google-Sitemap-50x50.jpg 50w" sizes="(max-width: 100px) 100vw, 100px" /></p><p>Search engine optimization (SEO) is a complex combination of website qualities that combine to improve the site&#8217;s ranking by search engines. As we all should hope, the most important factor is content. The goal of search engines is to display the most relevant, compelling and current content to users. Accordingly, the most effective use of time related to SEO is to ensure that you are providing the best content you can. Once you have met that very high bar, it is time to consider the many other factors that affect search engine rankings. A good place to start, particularly with APEX applications, is to create and register a Google Sitemap.</p> <h2>Why register a Google Sitemap?</h2> <p>Google&#8217;s default crawling algorithm is likely to miss a lot of content within an APEX application. The APEX URL format consists of the pattern https://[host]/[ords_mapping]/f?p=&#8230;&#8230;.. This is essentially a single location with a parameter. Google may continue to crawl subsequent links but it often will not. This URL format often represents an extensive list of catalogue options or other content that search engines discount as less relevant. Registering a sitemap lets Google (and others) know that you want the pages to be indexed and shown in search results.</p> <p>The range of APEX applications is vast and SEO may not apply to a significant portion. I&#8217;ll focus on the most likely scenario for this example: a public application (or application with significant public portions) that has some pages that are parameterized. There are techniques to index content behind paywalls and logins. These techniques may show up in a subsequent post. Additionally, it is difficult to index modal APEX pages. I have developed a technique for this which may also show up as a subsequent post.</p> <p>The general process follows:</p> <p>Create a sitemap in the Google format<br /> Create a REST service to make the sitemap available via a URL<br /> Register your sitemap<br /> Wait for all the new traffic <img src="https://s.w.org/images/core/emoji/11/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p> <h2>Create a Sitemap in the Google Format</h2> <p>You can simply follow the instructions in this blog post to get a functional Google sitemap. To fully understand Google sitemaps, though, you should start at the link below.<br /> https://support.google.com/webmasters/answer/183668?hl=en</p> <p>This blog post provides code and instructions to create a basic XML sitemap in the Google format:</p> <pre class="line-numbers"><code class="language-markup">&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"&gt; &lt;url&gt; &lt;loc&gt;http://www.example.com/foo.html&lt;/loc&gt; &lt;/url&gt; &lt;/urlset&gt;</code></pre> <p>I utilize a package to generate the XML and a REST service to expose it via a URL. The package below has two procedures that demonstrate different aspects of a sitemap.</p> <p>PAGE_XML can be used with any APEX application. It does not require any non-APEX tables or any specific pages. Below is an example of XML generated by this procedure.</p> <pre><code class="language-markup">&lt;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:1:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:3:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:5:0&lt;/loc&gt; &lt;/url&gt; ... &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:12:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:44:0&lt;/loc&gt; &lt;/url&gt; &lt;/urlset&gt;</code></pre> <p>CATALOG_XML requires an additional table, MY_CATALOG, and the application is expected to have PAGE 123456 as a detail page that does not have session state enabled. This code provides examples of how to add parameterized pages to your sitemap. Below is an example of XML generated by this procedure.</p> <pre class="line-numbers"><code class="language-markup"></code></pre> <pre class="line-numbers"><code class="language-markup">&lt;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:1:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:3:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:5:0&lt;/loc&gt; &lt;/url&gt;</code></pre> <p>&#8230;</p> <pre class="line-numbers"><code class="language-markup">&lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:12:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:44:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:1&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:2&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:3&lt;/loc&gt; &lt;/url&gt;</code></pre> <p>&#8230;</p> <pre class="line-numbers"><code class="language-markup">&lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:241&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:242&lt;/loc&gt; &lt;/url&gt; &lt;/urlset&gt;</code></pre> <p>The package spec and body are below. You&#8217;ll want to comment out CATALOG_XML or modify it to meet your table structure needs. This package needs to reside in the APEX workspace database schema because it relies on APEX workspace views. In this example, I am using the schema ANTON. (Note: I may use the terms &#8220;schema&#8221; and &#8220;user&#8221; interchangeably to reference a classic Oracle database user account.)</p> <pre class="line-numbers"><code class="language-sql">create or replace package MY_SITEMAP as -- This procedure creates a sitemap that includes all public pages -- in the application with p_app_id with the following exceptions: -- - pages that have a build set that is not "Include" -- - modal pages -- - pages without URL access, e.g. page 0 -- - page 101 because it is typically the login page procedure page_xml(p_app_id in number); -- This procedure is specific to an application that utilizes the table "MY_CATALOG." -- -- -- This procedure creates a sitemap that includes all public pages -- in the application with p_app_id with the following exceptions: -- - pages that have a build set that is not "Include" -- - modal pages -- - pages without URL access, e.g. page 0 -- - page 101 because it is typically the login page -- -- Additionally, this procedre will generate sitemap entries for a specific -- parameterized page (page 123456). procedure catalog_xml; end; /</code></pre> <pre class="line-numbers"><code class="language-sql">create or replace package body MY_SITEMAP as -- see package spec for usage procedure page_xml (p_app_id in number) as l_xml xmltype; begin begin select xmlElement("urlset", xmlattributes('http://www.sitemaps.org/schemas/sitemap/0.9' as "xmlns") , xmlAgg( xmlElement("url", xmlElement("loc", APEX_UTIL.HOST_URL (p_option =&gt; null) || '/apex/f?p=' || aap.application_id ||':'|| aap.page_id ||':0') the_xml ) ) ) the_xml into l_xml from apex_applications aa inner join APEX_APPLICATION_PAGES aap on aap.application_id = aa.application_id left outer join apex_application_build_options bo on bo.build_option_name = aap.build_option and bo.application_id = aap.application_id where aa.application_id = p_app_id -- do not return modal pages and aap.page_mode = 'Normal' -- only show public pages and (aap.page_requires_authentication = 'No' or aa.authentication_scheme_type = 'No Authentication') -- do not return pages without URL access, e.g. page 0 and aap.page_access_protection != 'No URL Access' -- do not return login page and aap.page_id not in (101) -- check build status and (bo.build_option_status is null or bo.build_option_status = 'Include'); htp.p('&lt;?xml version="1.0" encoding="UTF-8"?&gt;'); -- Note! This will only output 32K. -- If you anticipate more than 32K, consider chunking or other options. htp.p(l_xml.getClobVal()); exception when others then htp.p('Err: ' || sqlerrm); raise; end; end page_xml; -- -- -- see package spec for usage procedure catalog_xml as l_app_id integer := 373373; l_page_id integer := 123456; l_param_name varchar2(128) := 'P123456_ID'; l_xml xmltype; begin begin select xmlElement("urlset", xmlattributes('http://www.sitemaps.org/schemas/sitemap/0.9' as "xmlns") -- URLs for all the standard (not parameterized pages) , (select xmlAgg( xmlElement("url", xmlElement("loc", APEX_UTIL.HOST_URL (p_option =&gt; null) || '/apex/f?p=' || aap.application_id ||':'|| aap.page_id ||':0') ) ) from apex_applications aa inner join APEX_APPLICATION_PAGES aap on aap.application_id = aa.application_id left outer join apex_application_build_options bo on bo.build_option_name = aap.build_option and bo.application_id = aap.application_id where aa.application_id = l_app_id -- do not return modal pages and aap.page_mode = 'Normal' -- only show public pages and (aap.page_requires_authentication = 'No' or aa.authentication_scheme_type = 'No Authentication') -- do not return pages without URL access, e.g. page 0 and aap.page_access_protection != 'No URL Access' -- do not return login page and aap.page_id not in (101, l_page_id) -- check build status and (bo.build_option_status is null or bo.build_option_status = 'Include') ) -- URLs for the parameterized page l_page_id -- repeat this section for each parameterized page , (select xmlAgg( xmlElement("url", xmlElement("loc", APEX_UTIL.HOST_URL (p_option =&gt; null) || '/apex/f?p=' || l_app_id ||':'|| l_page_id ||':0::::'||l_param_name||':' || mc.id) ) ) from my_catalog mc ) --) )the_xml into l_xml from dual; htp.p('&lt;?xml version="1.0" encoding="UTF-8"?&gt;'); -- Note! This will only output 32K. -- If you anticipate more than 32K, consider chunking or other options. htp.p(l_xml.getClobVal()); exception when others then htp.p('Err: ' || sqlerrm); raise; end; end catalog_xml; end; /</code></pre> <h2>Create a REST service to make the Sitemap available via a URL</h2> <p>The easiest way to make the PL/SQL procedures available is to use Oracle REST Data Services (ORDS) to create a REST service. It is my preference to create a separate schema with limited privileges.</p> <p><strong>Create a user for REST services</strong><br /> Log in as a privileged/DBA user and create a user for REST services.</p> <p>create user anton_rest identified by mySuperSecretAndLongPassword;<br /> grant create session to anton_rest;</p> <p><strong>Grant execute on my_sitemap</strong><br /> Log in as the workspace owner and grant execute on my_sitemap.</p> <p>grant execute on my_sitemap to anton_rest;</p> <p><strong>Create the REST Service</strong></p> <p>Using Oracle SQL Developer (version 4 or higher) Log in as the REST user (anton_rest).</p> <p>Just to make sure we have everything working, we&#8217;ll test the output of our sitemap.</p> <p style="padding-left: 30px;"><strong>Show OWA Output so that you can view the results of the </strong>htp<strong> commands used in the procedure within SQL Developer.</strong></p> <p><img class="alignnone wp-image-12095" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-with-APEX-htp-commands-in-SQL-developer.png" alt="" width="376" height="345" /></p> <p>Enable the OWA Output for your connected session.</p> <p><img class="alignnone wp-image-12096" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-with-APEX-htp-commands-in-SQL-developer-1.png" alt="" width="434" height="398" /></p> <p><img class="alignnone wp-image-12097" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-OWA-Output.png" alt="" width="409" height="263" /></p> <p><img class="alignnone wp-image-12098" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-select-connection.png" alt="" width="420" height="158" /></p> <p>Run the following code and view the OWA Output. Be sure to use set p_app_id to an application that has at least one public page.</p> <p><img class="alignnone size-full wp-image-12099" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-worksheet.png" alt="" width="425" height="193" /></p> <pre class="line-numbers"><code class="language-sql">begin anton.my_sitemap.page_xml(p_app_id =&gt; 373373); end; /</code></pre> <p><img class="alignnone wp-image-12100" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-page-end-600x198.png" alt="" width="430" height="142" /></p> <p>&nbsp;</p> <p>Your OWA Output will be one long string. Scroll to see that it contains your anticipated output.</p> <p style="padding-left: 30px;"><strong>Use ORDS features to create the service</strong></p> <p>Enable REST for the schema by right-clicking on the connection name and selecting REST Services &gt; Enable REST Services.</p> <p><img class="alignnone wp-image-12101" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Enable-REST-for-the-Schema-600x539.png" alt="" width="435" height="391" /></p> <p>On the subsequent screen, check Enable Schema. If you wish to hide the schema name from the URL, you can put another name in the alias.</p> <p><img class="alignnone wp-image-12102" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-anther-name-in-the-Alias-600x452.png" alt="" width="427" height="321" /></p> <p>Click Next and Finish to allow you to build REST services.</p> <p>Expand REST Data Services, right click on Modules, and create a new module.</p> <p><img class="alignnone size-full wp-image-12106" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-1.png" alt="" width="296" height="484" /></p> <p><img class="alignnone wp-image-12107" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-2-600x451.png" alt="" width="459" height="345" /></p> <p>Specify Template</p> <p><img class="alignnone wp-image-12108" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Specify-template-600x458.png" alt="" width="469" height="358" /></p> <p>When specifying the template, you can use a bind variable. In this case, I&#8217;m creating a template that allows me to create a sitemap for any application based upon :APP_ID by entering the URI Pattern</p> <p>/pages/:APP_ID</p> <p>Click Next and Finish.</p> <p>At this point we have a template but have not told it how to handle a request. There are several types of http requests (GET, POST, PUT, DELETE) each of which can be handled separately. In our case, we&#8217;ll create a GET handler.</p> <p><img class="alignnone size-full wp-image-12109" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-create-get-handler.png" alt="" width="435" height="448" /></p> <p>Create a Source Type of PL/SQL.</p> <p><img class="alignnone wp-image-12110" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-sourcetype-of-PLSQL.png" alt="" width="440" height="446" /></p> <p>Paste in the code used to generate the sitemap XML using the bind variable:</p> <pre class="line-numbers"><code class="language-sql">begin anton.my_sitemap.page_xml(p_app_id =&gt; :APP_ID); end;</code></pre> <p><img class="alignnone wp-image-12113" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Generate-Sitemap-XML.png" alt="" width="471" height="172" /></p> <p>In order to edit the GET handler in the future, right-click on the handler and Edit.</p> <p><img class="alignnone wp-image-12114" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Edit-the-Get-Handler.png" alt="" width="476" height="289" /></p> <p>At this point, you have a functioning REST service and sitemap. You can test it at:</p> <p>https://yourmachine/ords/other_name/sitemap/pages/373373</p> <p>other_name = the schema alias entered when you enable REST services on the schema<br /> sitemap = module URI prefix<br /> pages = URI pattern<br /> 373373 = your application ID</p> <p>If you enter the URL in your browser you will see the output. If you view the page source you will see the XML.</p> <h2><strong>Register your sitemap</strong></h2> <p>You have to tell Google that your sitemap exists and where to find it. You can either use the Google webmaster tools or add the sitemap to your robots.txt file. Both methods are covered in the link below.</p> <p>https://support.google.com/webmasters/answer/183668?hl=en</p> <p>Note: At one point Google required your sitemap to have a url that appeared to be a static file, e.g. https://yourmachine/ords/other_name/sitemap/pages373373.xml. This is not currently a requirement, but if it returns, you can create a URI template pages373373.xml with a GET handler containing the following code:</p> <pre class="line-numbers"><code class="language-sql">begin anton.my_sitemap.page_xml(p_app_id =&gt; 373373); end;</code></pre> <p>Similarly, you can create URI templates for sitemaps that include catalogs of content.</p> <h2><strong>Wait for all the new traffic</strong></h2> <p>Prior to implementing your sitemap, you should determine your current traffic level. Then you&#8217;ll be able to compare your results after implementing the sitemap and registering it with Google. I&#8217;d love to hear your results.</p> <p>The post <a rel="nofollow" href="https://insum.ca/search-engine-optimization-with-apex-creating-a-google-sitemap/">Search Engine Optimization With APEX: Creating a Google Sitemap</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Anton Nielsen https://insum.ca/?p=13123 Fri Sep 14 2018 10:11:37 GMT-0400 (EDT) Search Engine Optimization With APEX: Creating a Google Sitemap https://insum.ca/search-engine-optimization-with-apex-creating-a-google-sitemap/ <p>Search engine optimization (SEO) is a complex combination of website qualities that combine to improve the site&#8217;s ranking by search engines. As we all should hope, the most important factor is content. The goal of search engines is to display the most relevant, compelling and current content to users. Accordingly, the most effective use of time related to SEO is to ensure that you are providing the best content you can. Once you have met that very high bar, it is time to consider the many other factors that affect search engine rankings. A good place to start, particularly with APEX applications, is to create and register a Google Sitemap.</p> <h2>Why register a Google Sitemap?</h2> <p>Google&#8217;s default crawling algorithm is likely to miss a lot of content within an APEX application. The APEX URL format consists of the pattern https://[host]/[ords_mapping]/f?p=&#8230;&#8230;.. This is essentially a single location with a parameter. Google may continue to crawl subsequent links but it often will not. This URL format often represents an extensive list of catalogue options or other content that search engines discount as less relevant. Registering a sitemap lets Google (and others) know that you want the pages to be indexed and shown in search results.</p> <p>The range of APEX applications is vast and SEO may not apply to a significant portion. I&#8217;ll focus on the most likely scenario for this example: a public application (or application with significant public portions) that has some pages that are parameterized. There are techniques to index content behind paywalls and logins. These techniques may show up in a subsequent post. Additionally, it is difficult to index modal APEX pages. I have developed a technique for this which may also show up as a subsequent post.</p> <p>The general process follows:</p> <p>Create a sitemap in the Google format<br /> Create a REST service to make the sitemap available via a URL<br /> Register your sitemap<br /> Wait for all the new traffic <img src="https://s.w.org/images/core/emoji/11/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p> <h2>Create a Sitemap in the Google Format</h2> <p>You can simply follow the instructions in this blog post to get a functional Google sitemap. To fully understand Google sitemaps, though, you should start at the link below.<br /> https://support.google.com/webmasters/answer/183668?hl=en</p> <p>This blog post provides code and instructions to create a basic XML sitemap in the Google format:</p> <pre class="line-numbers"><code class="language-markup">&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"&gt; &lt;url&gt; &lt;loc&gt;http://www.example.com/foo.html&lt;/loc&gt; &lt;/url&gt; &lt;/urlset&gt;</code></pre> <p>I utilize a package to generate the XML and a REST service to expose it via a URL. The package below has two procedures that demonstrate different aspects of a sitemap.</p> <p>PAGE_XML can be used with any APEX application. It does not require any non-APEX tables or any specific pages. Below is an example of XML generated by this procedure.</p> <pre><code class="language-markup">&lt;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:1:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:3:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:5:0&lt;/loc&gt; &lt;/url&gt; ... &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:12:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:44:0&lt;/loc&gt; &lt;/url&gt; &lt;/urlset&gt;</code></pre> <p>CATALOG_XML requires an additional table, MY_CATALOG, and the application is expected to have PAGE 123456 as a detail page that does not have session state enabled. This code provides examples of how to add parameterized pages to your sitemap. Below is an example of XML generated by this procedure.</p> <pre class="line-numbers"><code class="language-markup"></code></pre> <pre class="line-numbers"><code class="language-markup">&lt;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:1:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:3:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:5:0&lt;/loc&gt; &lt;/url&gt;</code></pre> <p>&#8230;</p> <pre class="line-numbers"><code class="language-markup">&lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:12:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:44:0&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:1&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:2&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:3&lt;/loc&gt; &lt;/url&gt;</code></pre> <p>&#8230;</p> <pre class="line-numbers"><code class="language-markup">&lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:241&lt;/loc&gt; &lt;/url&gt; &lt;url&gt; &lt;loc&gt;https://insum.ca//apex/f?p=373373:123456:0::::P123456_ID:242&lt;/loc&gt; &lt;/url&gt; &lt;/urlset&gt;</code></pre> <p>The package spec and body are below. You&#8217;ll want to comment out CATALOG_XML or modify it to meet your table structure needs. This package needs to reside in the APEX workspace database schema because it relies on APEX workspace views. In this example, I am using the schema ANTON. (Note: I may use the terms &#8220;schema&#8221; and &#8220;user&#8221; interchangeably to reference a classic Oracle database user account.)</p> <pre class="line-numbers"><code class="language-sql">create or replace package MY_SITEMAP as -- This procedure creates a sitemap that includes all public pages -- in the application with p_app_id with the following exceptions: -- - pages that have a build set that is not "Include" -- - modal pages -- - pages without URL access, e.g. page 0 -- - page 101 because it is typically the login page procedure page_xml(p_app_id in number); -- This procedure is specific to an application that utilizes the table "MY_CATALOG." -- -- -- This procedure creates a sitemap that includes all public pages -- in the application with p_app_id with the following exceptions: -- - pages that have a build set that is not "Include" -- - modal pages -- - pages without URL access, e.g. page 0 -- - page 101 because it is typically the login page -- -- Additionally, this procedure will generate sitemap entries for a specific -- parameterized page (page 123456). procedure catalog_xml; end; /</code></pre> <pre class="line-numbers"><code class="language-sql">create or replace package body MY_SITEMAP as -- see package spec for usage procedure page_xml (p_app_id in number) as l_xml xmltype; begin begin select xmlElement("urlset", xmlattributes('http://www.sitemaps.org/schemas/sitemap/0.9' as "xmlns") , xmlAgg( xmlElement("url", xmlElement("loc", APEX_UTIL.HOST_URL (p_option =&gt; null) || '/apex/f?p=' || aap.application_id ||':'|| aap.page_id ||':0') the_xml ) ) ) the_xml into l_xml from apex_applications aa inner join APEX_APPLICATION_PAGES aap on aap.application_id = aa.application_id left outer join apex_application_build_options bo on bo.build_option_name = aap.build_option and bo.application_id = aap.application_id where aa.application_id = p_app_id -- do not return modal pages and aap.page_mode = 'Normal' -- only show public pages and (aap.page_requires_authentication = 'No' or aa.authentication_scheme_type = 'No Authentication') -- do not return pages without URL access, e.g. page 0 and aap.page_access_protection != 'No URL Access' -- do not return login page and aap.page_id not in (101) -- check build status and (bo.build_option_status is null or bo.build_option_status = 'Include'); htp.p('&lt;?xml version="1.0" encoding="UTF-8"?&gt;'); -- Note! This will only output 32K. -- If you anticipate more than 32K, consider chunking or other options. htp.p(l_xml.getClobVal()); exception when others then htp.p('Err: ' || sqlerrm); raise; end; end page_xml; -- -- -- see package spec for usage procedure catalog_xml as l_app_id integer := 373373; l_page_id integer := 123456; l_param_name varchar2(128) := 'P123456_ID'; l_xml xmltype; begin begin select xmlElement("urlset", xmlattributes('http://www.sitemaps.org/schemas/sitemap/0.9' as "xmlns") -- URLs for all the standard (not parameterized pages) , (select xmlAgg( xmlElement("url", xmlElement("loc", APEX_UTIL.HOST_URL (p_option =&gt; null) || '/apex/f?p=' || aap.application_id ||':'|| aap.page_id ||':0') ) ) from apex_applications aa inner join APEX_APPLICATION_PAGES aap on aap.application_id = aa.application_id left outer join apex_application_build_options bo on bo.build_option_name = aap.build_option and bo.application_id = aap.application_id where aa.application_id = l_app_id -- do not return modal pages and aap.page_mode = 'Normal' -- only show public pages and (aap.page_requires_authentication = 'No' or aa.authentication_scheme_type = 'No Authentication') -- do not return pages without URL access, e.g. page 0 and aap.page_access_protection != 'No URL Access' -- do not return login page and aap.page_id not in (101, l_page_id) -- check build status and (bo.build_option_status is null or bo.build_option_status = 'Include') ) -- URLs for the parameterized page l_page_id -- repeat this section for each parameterized page , (select xmlAgg( xmlElement("url", xmlElement("loc", APEX_UTIL.HOST_URL (p_option =&gt; null) || '/apex/f?p=' || l_app_id ||':'|| l_page_id ||':0::::'||l_param_name||':' || mc.id) ) ) from my_catalog mc ) --) )the_xml into l_xml from dual; htp.p('&lt;?xml version="1.0" encoding="UTF-8"?&gt;'); -- Note! This will only output 32K. -- If you anticipate more than 32K, consider chunking or other options. htp.p(l_xml.getClobVal()); exception when others then htp.p('Err: ' || sqlerrm); raise; end; end catalog_xml; end; /</code></pre> <h2>Create a REST service to make the Sitemap available via a URL</h2> <p>The easiest way to make the PL/SQL procedures available is to use Oracle REST Data Services (ORDS) to create a REST service. It is my preference to create a separate schema with limited privileges.</p> <p><strong>Create a user for REST services</strong><br /> Log in as a privileged/DBA user and create a user for REST services.</p> <p>create user anton_rest identified by mySuperSecretAndLongPassword;<br /> grant create session to anton_rest;</p> <p><strong>Grant execute on my_sitemap</strong><br /> Log in as the workspace owner and grant execute on my_sitemap.</p> <p>grant execute on my_sitemap to anton_rest;</p> <p><strong>Create the REST Service</strong></p> <p>Using Oracle SQL Developer (version 4 or higher) Log in as the REST user (anton_rest).</p> <p>Just to make sure we have everything working, we&#8217;ll test the output of our sitemap.</p> <p style="padding-left: 30px;"><strong>Show OWA Output so that you can view the results of the </strong>htp<strong> commands used in the procedure within SQL Developer.</strong></p> <p><img class="alignnone wp-image-12095" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-with-APEX-htp-commands-in-SQL-developer.png" alt="" width="376" height="345" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-with-APEX-htp-commands-in-SQL-developer.png 556w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-with-APEX-htp-commands-in-SQL-developer-300x276.png 300w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-with-APEX-htp-commands-in-SQL-developer-450x414.png 450w" sizes="(max-width: 376px) 100vw, 376px" /></p> <p>Enable the OWA Output for your connected session.</p> <p><img class="alignnone wp-image-12096" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-with-APEX-htp-commands-in-SQL-developer-1.png" alt="" width="434" height="398" /></p> <p><img class="alignnone wp-image-12097" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-OWA-Output.png" alt="" width="409" height="263" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-OWA-Output.png 432w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-OWA-Output-300x193.png 300w" sizes="(max-width: 409px) 100vw, 409px" /></p> <p><img class="alignnone wp-image-12098" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-select-connection.png" alt="" width="420" height="158" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-select-connection.png 415w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-select-connection-300x113.png 300w" sizes="(max-width: 420px) 100vw, 420px" /></p> <p>Run the following code and view the OWA Output. Be sure to use set p_app_id to an application that has at least one public page.</p> <p><img class="alignnone size-full wp-image-12099" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-worksheet.png" alt="" width="425" height="193" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-worksheet.png 425w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-worksheet-300x136.png 300w" sizes="(max-width: 425px) 100vw, 425px" /></p> <pre class="line-numbers"><code class="language-sql">begin anton.my_sitemap.page_xml(p_app_id =&gt; 373373); end; /</code></pre> <p><img class="alignnone wp-image-12100" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-page-end-600x198.png" alt="" width="430" height="142" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-page-end-600x198.png 600w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-page-end-300x99.png 300w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-page-end-450x149.png 450w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-page-end.png 721w" sizes="(max-width: 430px) 100vw, 430px" /></p> <p>&nbsp;</p> <p>Your OWA Output will be one long string. Scroll to see that it contains your anticipated output.</p> <p style="padding-left: 30px;"><strong>Use ORDS features to create the service</strong></p> <p>Enable REST for the schema by right-clicking on the connection name and selecting REST Services &gt; Enable REST Services.</p> <p><img class="alignnone wp-image-12101" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Enable-REST-for-the-Schema-600x539.png" alt="" width="435" height="391" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Enable-REST-for-the-Schema-600x539.png 600w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Enable-REST-for-the-Schema-300x270.ng 300w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Enable-REST-for-the-Schema-450x404.png 450w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Enable-REST-for-the-Schema.png 631w" sizes="(max-width: 435px) 100vw, 435px" /></p> <p>On the subsequent screen, check Enable Schema. If you wish to hide the schema name from the URL, you can put another name in the alias.</p> <p><img class="alignnone wp-image-12102" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-anther-name-in-the-Alias-600x452.png" alt="" width="427" height="321" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-anther-name-in-the-Alias-600x452.png 600w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-anther-name-in-the-Alias-300x226.png 300w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-anther-name-in-the-Alias-450x339.png 450w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-anther-name-in-the-Alias.png 644w" sizes="(max-width: 427px) 100vw, 427px" /></p> <p>Click Next and Finish to allow you to build REST services.</p> <p>Expand REST Data Services, right click on Modules, and create a new module.</p> <p><img class="alignnone size-full wp-image-12106" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-1.png" alt="" width="296" height="484" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-1.png 296w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-1-183x300.png 183w" sizes="(max-width: 296px) 100vw, 296px" /></p> <p><img class="alignnone wp-image-12107" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-2-600x451.png" alt="" width="459" height="345" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-2-600x451.png 600w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-2-300x226.png 300w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-2-450x338.png 450w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-new-module-2.png 645w" sizes="(max-width: 459px) 100vw, 459px" /></p> <p>Specify Template</p> <p><img class="alignnone wp-image-12108" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Specify-template-600x458.png" alt="" width="469" height="358" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Specify-template-600x458.png 600w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Specify-template-300x229.png 300w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Specify-template-450x343.png 450w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Specify-template.png 641w" sizes="(max-width: 469px) 100vw, 469px" /></p> <p>When specifying the template, you can use a bind variable. In this case, I&#8217;m creating a template that allows me to create a sitemap for any application based upon :APP_ID by entering the URI Pattern</p> <p>/pages/:APP_ID</p> <p>Click Next and Finish.</p> <p>At this point we have a template but have not told it how to handle a request. There are several types of http requests (GET, POST, PUT, DELETE) each of which can be handled separately. In our case, we&#8217;ll create a GET handler.</p> <p><img class="alignnone size-full wp-image-12109" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-create-get-handler.png" alt="" width="435" height="448" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-create-get-handler.png 435w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-create-get-handler-291x300.png 291w" sizes="(max-width: 435px) 100vw, 435px" /></p> <p>Create a Source Type of PL/SQL.</p> <p><img class="alignnone wp-image-12110" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-sourcetype-of-PLSQL.png" alt="" width="440" height="446" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-sourcetype-of-PLSQL.png 453w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-sourcetype-of-PLSQL-296x300.png 296w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-sourcetype-of-PLSQL-100x100.png 100w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Create-sourcetype-of-PLSQL-450x456.png 450w" sizes="(max-width: 440px) 100vw, 440px" /></p> <p>Paste in the code used to generate the sitemap XML using the bind variable:</p> <pre class="line-numbers"><code class="language-sql">begin anton.my_sitemap.page_xml(p_app_id =&gt; :APP_ID); end;</code></pre> <p><img class="alignnone wp-image-12113" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Generate-Sitemap-XML.png" alt="" width="471" height="172" srcset="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Generate-Sitemap-XML.png 597w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Generate-Sitemap-XML-300x110.png 300w, https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Generate-Sitemap-XML-450x164.png 450w" sizes="(max-width: 471px) 100vw, 471px" /></p> <p>In order to edit the GET handler in the future, right-click on the handler and Edit.</p> <p><img class="alignnone wp-image-12114" src="https://insum.ca/wp-content/uploads/2018/09/Google-Sitemap-Edit-the-Get-Handler.png" alt="" width="476" height="289" /></p> <p>At this point, you have a functioning REST service and sitemap. You can test it at:</p> <p>https://yourmachine/ords/other_name/sitemap/pages/373373</p> <p>other_name = the schema alias entered when you enable REST services on the schema<br /> sitemap = module URI prefix<br /> pages = URI pattern<br /> 373373 = your application ID</p> <p>If you enter the URL in your browser you will see the output. If you view the page source you will see the XML.</p> <h2><strong>Register your sitemap</strong></h2> <p>You have to tell Google that your sitemap exists and where to find it. You can either use the Google webmaster tools or add the sitemap to your robots.txt file. Both methods are covered in the link below.</p> <p>https://support.google.com/webmasters/answer/183668?hl=en</p> <p>Note: At one point Google required your sitemap to have a url that appeared to be a static file, e.g. https://yourmachine/ords/other_name/sitemap/pages373373.xml. This is not currently a requirement, but if it returns, you can create a URI template pages373373.xml with a GET handler containing the following code:</p> <pre class="line-numbers"><code class="language-sql">begin anton.my_sitemap.page_xml(p_app_id =&gt; 373373); end;</code></pre> <p>Similarly, you can create URI templates for sitemaps that include catalogs of content.</p> <h2><strong>Wait for all the new traffic</strong></h2> <p>Prior to implementing your sitemap, you should determine your current traffic level. Then you&#8217;ll be able to compare your results after implementing the sitemap and registering it with Google. I&#8217;d love to hear your results.</p> <p>The post <a rel="nofollow" href="https://insum.ca/search-engine-optimization-with-apex-creating-a-google-sitemap/">Search Engine Optimization With APEX: Creating a Google Sitemap</a> appeared first on <a rel="nofollow" href="https://insum.ca">Insum</a>.</p> Anton Nielsen https://insum.ca/?p=12087 Fri Sep 14 2018 08:03:33 GMT-0400 (EDT) How to set IG default values for email fields when downloading report http://apexbyg.blogspot.com/2018/09/hot-to-set-ig-default-values-for-email.html <div dir="ltr" style="text-align: left;" trbidi="on">Few days ago I've got interesting APEX question (I don't mind that the question was sent by mail, but there's <a href="https://community.oracle.com/community/technology_network_community/database/developer-tools/application_express" target="_blank">Oracle Community Forum</a>&nbsp;where you can get quicker answer and more people will benefit from it).<br /><br />..and the question is: how to define default values for fields that are shown when you want to download Interactive Grid report and send it by the e-mail.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-ch2H2n6oj-M/W5uIg936AdI/AAAAAAAAPvI/pq7W0e3tUsch8rAguTNjbNaVml1ts7-CQCLcBGAs/s1600/Screen%2BShot%2B2018-09-14%2Bat%2B12.05.43.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="955" data-original-width="800" height="640" src="https://4.bp.blogspot.com/-ch2H2n6oj-M/W5uIg936AdI/AAAAAAAAPvI/pq7W0e3tUsch8rAguTNjbNaVml1ts7-CQCLcBGAs/s640/Screen%2BShot%2B2018-09-14%2Bat%2B12.05.43.png" width="536" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">Maybe I'm wrong but I think there's no native way to do this so I found a workaround.</div><div class="separator" style="clear: both; text-align: left;">You can do this for a specific region/page or globally by using global page (page 0).</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">First of all you need to create on click dynamic action triggered on checkbox item "Send as Email":</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-uGuWB3aKsqk/W5uJ6un0zmI/AAAAAAAAPy0/GD7Ao9-dJpsDSy73BfihNAzCh5vbK7VCgCLcBGAs/s1600/Screen%2BShot%2B2018-09-14%2Bat%2B12.12.34.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="540" data-original-width="550" src="https://3.bp.blogspot.com/-uGuWB3aKsqk/W5uJ6un0zmI/AAAAAAAAPy0/GD7Ao9-dJpsDSy73BfihNAzCh5vbK7VCgCLcBGAs/s1600/Screen%2BShot%2B2018-09-14%2Bat%2B12.12.34.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">The Event Scope attribute must be set to Dynamic and if you want to restrict this dynamic action to the specific region you should define Static Container (jQuery Selector) property with static ID of IG region (for example #emp, if static ID of a region is emp).</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">You also need to create true dynamic action of a type Execute JavaScript Code where you can define items and values that you want to set:</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-BPpeLMidnC8/W5uVw1sqdQI/AAAAAAAAQIQ/ZWfMXwzEz5Ydu04uQSOSALjKULyyzloEACLcBGAs/s1600/Screen%2BShot%2B2018-09-14%2Bat%2B13.04.04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="267" data-original-width="550" src="https://2.bp.blogspot.com/-BPpeLMidnC8/W5uVw1sqdQI/AAAAAAAAQIQ/ZWfMXwzEz5Ydu04uQSOSALjKULyyzloEACLcBGAs/s1600/Screen%2BShot%2B2018-09-14%2Bat%2B13.04.04.png" /></a></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><br /></div>Demo is available <a href="https://apex.oracle.com/pls/apex/f?p=100309:54" target="_blank">here</a>.<br /><br />Tested in APEX 18.1.0.00.45.<br /><br />Enjoy!</div> Marko Gorički tag:blogger.com,1999:blog-1003209687173038896.post-7959220380407100100 Fri Sep 14 2018 07:12:00 GMT-0400 (EDT) Exadata and Capacity on Demand (CoD) http://jaffardba.blogspot.com/2018/09/exadata-and-capacity-on-demand-cod.html <div dir="ltr" style="text-align: left;" trbidi="on">As most of us knew that the Exadata Database Machine comes in different sizes with different resource capacity. Not sure how many of you aware that Capacity on Demand (CoD) option can enable customers to start with limited active cores processors and increase them dynamically on demand. If CoD option is not enabled during the initial EDM configuration, then, all active cores are enabled by default and can't be reduced any further.<br /><br />With X4-2 or higher, number of active cores can be reduced during the installation and can be increased based on the demand. &nbsp;For X4-2, cores are increased in two (2) core increment, where as X4-8 increased in eight (8) core factor, see the table below.<br /><br />Below example demonstrates the procedure to increase the active core processors:<br /><br />Using DBMCLI utility:<br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><br /></span><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">DBMCLI&gt; LIST DBSERVER attributes coreCount</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><br /></span><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">DBMCLI&gt; ALTER DBSERVER pendingCoreCount = new_core_count</span><br /><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><br /></span><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">DBMCLI&gt; LIST DBSERVER attributes coreCount</span><br /><br /><i>Note: Once active cores are enabled (increased), there is no procedure to reduce them again.</i><br /><br />Restart the database servers after increasing the core count.<br /><br />Below table depicts the capacity-on-demand core configuration for various EDM types and releases:<br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-MngXLeG00sM/W5uUFfvhnTI/AAAAAAAAf0Q/Ns1jAL49e-ILLunWOhDMfuAPeHk7_Bt7QCLcBGAs/s1600/Screen%2BShot%2B2018-09-14%2Bat%2B1.56.43%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1082" data-original-width="1600" height="432" src="https://2.bp.blogspot.com/-MngXLeG00sM/W5uUFfvhnTI/AAAAAAAAf0Q/Ns1jAL49e-ILLunWOhDMfuAPeHk7_Bt7QCLcBGAs/s640/Screen%2BShot%2B2018-09-14%2Bat%2B1.56.43%2BPM.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-DIN0iKa3yEo/W5uUR-wXc4I/AAAAAAAAf0Y/VJcj5CT-Ca4N0yO1su08QpMOve1xCDbQwCLcBGAs/s1600/Screen%2BShot%2B2018-09-14%2Bat%2B1.57.57%2BPM.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="527" data-original-width="1600" height="210" src="https://1.bp.blogspot.com/-DIN0iKa3yEo/W5uUR-wXc4I/AAAAAAAAf0Y/VJcj5CT-Ca4N0yO1su08QpMOve1xCDbQwCLcBGAs/s640/Screen%2BShot%2B2018-09-14%2Bat%2B1.57.57%2BPM.png" width="640" /></a></div><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><b>Updates (10-Oct-2018):</b><br />Came across of the below blog post where the author described the procedure how to reduce the core count on Exadata.<br />I haven't tested though, and also not sure whether this is an Oracle approved approach to reduce the core factor on Exadata. However, its good to know the procedure.<br /><br />https://grepora.com/2018/10/08/reduce-exadata-core-count/<br /><br /></div> The Human Fly tag:blogger.com,1999:blog-19771507.post-7295491091539222487 Fri Sep 14 2018 07:10:00 GMT-0400 (EDT) Add record count to collapsed region http://www.grassroots-oracle.com/2018/09/add-record-count-to-collapsed-region-orclapex.html I have a diagnostics page where I wanted to display how many records are in a collapsible region's title.<br /><br />The following is a simple solution, but will only work properly if all records are displayed, and no pagination is used.<br />Otherwise, check this <a href="http://www.grassroots-oracle.com/2013/12/count-number-of-rows-returned-in-apex.html" target="_blank">past post</a> for alternative methods to get the number of rows in a region.<br /><br />Pick a column in the region and add a class. I chose "cnt".<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-Y-1Kl5HYvNw/W5s1RQlPQTI/AAAAAAAAT5U/tdRmieJRdEMf7B6k2gFsouAGYgjKamNoACLcBGAs/s1600/cnt_class.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="189" data-original-width="328" src="https://2.bp.blogspot.com/-Y-1Kl5HYvNw/W5s1RQlPQTI/AAAAAAAAT5U/tdRmieJRdEMf7B6k2gFsouAGYgjKamNoACLcBGAs/s1600/cnt_class.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Column attribute</td></tr></tbody></table><br />To be selective, it's always handy to add a static ID to the region.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-dc0XzQssFa8/W5s1RmP4_RI/AAAAAAAAT5c/NAdaHVzOCH4gRojyxrA3u0JH0AMDz3L4QCLcBGAs/s1600/cnt_static.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="81" data-original-width="329" src="https://4.bp.blogspot.com/-dc0XzQssFa8/W5s1RmP4_RI/AAAAAAAAT5c/NAdaHVzOCH4gRojyxrA3u0JH0AMDz3L4QCLcBGAs/s1600/cnt_static.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">This is not an 'advanced' feature</td></tr></tbody></table><br />Now we're ready to create an After Refresh Dynamic Action on the region, executing the following JavaScript, also firing on initialisation<br /><br /><code>$('#p99_share .t-Region-title').text('Sharing ('+$('#p99_share .cnt').length+')');</code><br /><br />It will relabel region title with the amount of <code>.cnt</code> classes it could find in the region.<br /><br />The final result looks like this:<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-4_ZQOrzsXn0/W5s1RckqIpI/AAAAAAAAT5Y/ADRGQXHmKrIfFQgNSaOxqvyN0Xwx1GnvACLcBGAs/s1600/cnt_region.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="74" data-original-width="220" src="https://4.bp.blogspot.com/-4_ZQOrzsXn0/W5s1RckqIpI/AAAAAAAAT5Y/ADRGQXHmKrIfFQgNSaOxqvyN0Xwx1GnvACLcBGAs/s1600/cnt_region.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Collapsible region with modified title</td></tr></tbody></table><br />An alternative that skips the need for a static region ID would be<br /><br /><span style="font-family: monospace;">$(this.trigginerElement).find('.t-Region-title')</span><br /><span style="font-family: monospace;">&nbsp; &nbsp;.text('Sharing ('+</span><span style="font-family: monospace;">$(this.trigginerElement).find('.</span><span style="font-family: monospace;">cnt').length+')');</span><br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td><a href="https://2.bp.blogspot.com/-EFICB0MUon0/W5s4JYsgt7I/AAAAAAAAT54/lfDZvtAzCPwzGubehKUbLKBQ3EkaBQpNwCLcBGAs/s1600/cnt_da.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="486" data-original-width="343" src="https://2.bp.blogspot.com/-EFICB0MUon0/W5s4JYsgt7I/AAAAAAAAT54/lfDZvtAzCPwzGubehKUbLKBQ3EkaBQpNwCLcBGAs/s1600/cnt_da.png" /></a></td></tr><tr><td class="tr-caption" style="font-size: 12.8px;">After Refresh Dynamic Action</td></tr></tbody></table><i>Edit </i>- Trent offered a <a href="https://twitter.com/trentschafer/status/1040715801249103873" target="_blank">more declarative</a> example.<br /><br />Relatively simple, but effective.<br /><br /><br /> Scott Wesley tag:blogger.com,1999:blog-4818542164384221282.post-6067382143608154134 Fri Sep 14 2018 00:27:00 GMT-0400 (EDT) ODTUG Kscope Session Highlights - Part 2 https://www.odtug.com/p/bl/et/blogaid=826&source=1 Part 2 - Curious about the content you'll see at ODTUG Kscope19? As we look ahead to opening abstract submissions in the coming weeks, we would like to share some of the content highlights from ODTUG Kscope18. ODTUG https://www.odtug.com/p/bl/et/blogaid=826&source=1 Thu Sep 13 2018 13:14:04 GMT-0400 (EDT) Cloud Access Security Broker (CASB) for Oracle Cloud Infrastructure (OCI) http://jaffardba.blogspot.com/2018/09/customer-adoption-to-cloud-services.html <div dir="ltr" style="text-align: left;" trbidi="on">Customer adoption to cloud services (IaaS, PaaS, SaaS) &nbsp;has been rapidly grown and growing. The most challenging aspect moving to cloud is the ability to secure the application and data that is put on the cloud. Oracle's hetrogenous security solution Cloud Access Security Broker (CASB) helps customers protecting their cloud-based infrastructure, platforms, applications across vendors. CASBs have emerged as &nbsp;the go-to cloud security solution. CASB has the ability to provide security to entire cloud footprint (SaaS, PaaS, IaaS).<br /><br />Most essentially, for all Oracle Cloud Infrastructure (OCI) deployments, it provides visibility, threat protection, data security and complaince. Following are a few key advantages of CASB:<br /><br /><br /><ul style="text-align: left;"><li>Governance of privileged activities</li><li>Unified incident management</li><li>Proactive remediation</li><li>Continuous security compliance for OCI deployments</li></ul><div>As part of complete visibility, it provides holistic view of entire cloud environment, including users and devices.</div><div><br /></div><div>Threat Detection with User Behavior Analytics (UBA) builds a baseline for typical behavior, down to the user and application. Also, maintain a log when and how a user deviates from the baseline. With the help of predictive analytics, you can easily identify the risky users who performs folder permission change, changing user privileges , or tampering with the configuration settings.</div><div><br /></div><div>All your cloud compliance configuration settings can be easily maintained. Once the settings are made, CASB monitoring the settings and alerts you whenever there is a change in the setting.</div><div></div><div>CASB provides three key components to secure your data in cloud:</div><div><ol style="text-align: left;"><li>Data visibility</li><li>Data inspection</li><li>Data Accessibility</li></ol><div>It can easily integrate with the existing cloud security solutions, such as, SWG, NGF, IDaaS, DLP and SIEM.</div></div><div><br />For more details and information, visit Oracle website:<br /><br />https://www.oracle.com/cloud/paas/casb-cloud-service.html<br /><br /></div><div><br /></div></div> The Human Fly tag:blogger.com,1999:blog-19771507.post-3101599544061157431 Thu Sep 13 2018 09:33:00 GMT-0400 (EDT) ODTUG Kscope18 Session Recordings & Presentations Now Available to ODTUG Members https://www.odtug.com/p/bl/et/blogaid=827&source=1 If you are a paid ODTUG member who was unable to attend ODTUG Kscope18, we have great news for you! The ODTUG Kscope18 session presentations and recordings are NOW AVAILABLE to you! ODTUG https://www.odtug.com/p/bl/et/blogaid=827&source=1 Wed Sep 12 2018 10:14:04 GMT-0400 (EDT) All about 'Autonomous Transaction Processing' - Part I http://jaffardba.blogspot.com/2018/09/all-about-autonomous-transaction.html <div dir="ltr" style="text-align: left;" trbidi="on">There has been a lot of buzz about 'Self driving &amp; Self tuning database', 'autonomous', 'automation', etc. since Oracle 18c announced. I have decided to do my homework and test/validate some of them. So, this blog post will focus about 'Autonomous Transaction Processing (ATP)', how this is helpful to an organization and what role a DBA can play.<br /><br />Its nothing but another typical cloud offering from Oracle. To begin with, Oracle ATP is built upon Oracle database and is designed, optimized to deliver scalable transaction performance across all standard business applications. As a service, ATP doesn't require DBA and no DBA intervention for any installation,configuration or management related activities. It handles all the DB related activities, such as, DB creation, backup, patching, upgrade, space management etc.<br /><br />Its completely elastic service, where you can dynamically increase and decrease the resources (OCPU and storage capacity) without having any service interruption or database downtime. Using the cloud based console, you can easily manage the service, such as, scaling the service and monitoring. Additionally, cloud based notebook application provides easy querying, colobration and &nbsp;data-visualization capabilities.<br /><br />Below picture (source : Oracle documentation) describes the ATP architecture:<br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-9ZReIhM1RJo/W5jM72i8nAI/AAAAAAAAfz8/QIBA7yIJuukeJVRoHffORsFddEQ6oudCACEwYBhgL/s1600/Screen%2BShot%2B2018-09-12%2Bat%2B11.20.46%2BAM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="950" data-original-width="1356" height="448" src="https://3.bp.blogspot.com/-9ZReIhM1RJo/W5jM72i8nAI/AAAAAAAAfz8/QIBA7yIJuukeJVRoHffORsFddEQ6oudCACEwYBhgL/s640/Screen%2BShot%2B2018-09-12%2Bat%2B11.20.46%2BAM.png" width="640" /></a></div><br />Below are some of the key features of Oracle Autonomous Transaction Processing:<br /><br /><ul style="text-align: left;"><li>Simplified management of : rapid provisioning of new database, dynamic resource management (allocation and de-allocation of cpu and storage), patching &amp; upgrades and backup &amp; recovery</li><li>complete elastic service</li><li>Supports: existing, cloud and on-prime applications</li><li>supports high query performance and concurrent workloads</li><li>Easy data migration</li><li>BI tools support</li><li>Building reports and dashboards with analytics</li><li>All data stores in encrypted formatted to secure the data</li><li>Strong authenticity for connection and data access control</li></ul><div>In part II, I will discuss details subscription, creating and users management.<br /></div><div>Trying to avail 30 days free account on Oracle could. If I succeed to have the credentials, I will run through practically and post the configuration and management tasks.</div></div> The Human Fly tag:blogger.com,1999:blog-19771507.post-9098296268425679118 Wed Sep 12 2018 04:47:00 GMT-0400 (EDT) ODTUG Board of Directors Nomination Deadline is September 20! https://www.odtug.com/p/bl/et/blogaid=825&source=1 Are you a paid ODTUG member (or will you be as of September 30, 2018)? Do you have a lot to offer the ODTUG community? Do you have a passion for ODTUG and time to commit to serving on the board? If so, then I encourage you to submit your name to be considered for the 2019-2020 BOD. ODTUG https://www.odtug.com/p/bl/et/blogaid=825&source=1 Tue Sep 11 2018 09:30:20 GMT-0400 (EDT) Welcome to ODTUG Kscope19! https://www.odtug.com/p/bl/et/blogaid=824&source=1 Welcome to a new ODTUG Kscope conference planning year! After a much needed hiatus, the team has kicked off the new conference season, and we are super excited about going back to Seattle! ODTUG https://www.odtug.com/p/bl/et/blogaid=824&source=1 Mon Sep 10 2018 16:51:00 GMT-0400 (EDT) Increasing Maximum Web Service Requests in Oracle APEX 18.1 http://dgielis.blogspot.com/2018/09/increasing-maximum-web-service-requests.html While running our final tests of <a href="https://www.apexofficeprint.com/">APEX Office Print (AOP) 18.1</a> we hit "ORA-20000: Issue calling Main AOP Service (REST call: ): ORA-20001: You have exceeded the maximum number of web service requests per workspace."<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-DAhbJ47WjM8/W5bR-_4y78I/AAAAAAAAJYU/j0jOQxVzm-AGm2qIm2kKGeCSN4fSAcyBwCLcBGAs/s1600/maximum_number_of_web_service_requests.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="538" data-original-width="900" height="239" src="https://4.bp.blogspot.com/-DAhbJ47WjM8/W5bR-_4y78I/AAAAAAAAJYU/j0jOQxVzm-AGm2qIm2kKGeCSN4fSAcyBwCLcBGAs/s400/maximum_number_of_web_service_requests.png" width="400" /></a></div><br />When you login into the Internal Workspace and navigate to a workspace, there's a setting for &nbsp;Maximum Web Service Requests. The default value is 1000 requests per 24h (rolling window).<br /><br />If you know that AOP has next to hundreds of server tests, also around 500 automated tests through APEX, we hit this limit after the second full run. After setting the value to 20000, we are able to continue our final testing :)<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-cxHywsCUBnA/W5bTLL3RHII/AAAAAAAAJYg/BunAHj-sjcQJkVJBtXsKUznpHzKokTEbACLcBGAs/s1600/workspace_isolation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1135" data-original-width="1600" height="454" src="https://3.bp.blogspot.com/-cxHywsCUBnA/W5bTLL3RHII/AAAAAAAAJYg/BunAHj-sjcQJkVJBtXsKUznpHzKokTEbACLcBGAs/s640/workspace_isolation.png" width="640" /></a></div>I guess the chances are small you will hit the limit in a normal APEX app, but if you do, it's easy to fix by setting a higher value for your workspace. Dimitri Gielis tag:blogger.com,1999:blog-21122514.post-5127324399465853204 Mon Sep 10 2018 16:29:00 GMT-0400 (EDT) Enhancing the APEX Error Handling Function with Logger http://www.grassroots-oracle.com/2018/09/enhance-oracle-apex-error-handling-function-logger.html Many, many moons ago, I created an error handling function for Oracle APEX, just like the original sample provided by <a href="http://www.inside-oracle-apex.com/apex-4-1-error-handling-improvements-part-1/" target="_blank">Patrick Wolf</a> for the 4.1 error handling feature. You'll probably find a strong correlation between the two events.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-lq8oOkLoCDc/W5ZL3Q2Dc9I/AAAAAAAAT34/q7Bz5LnXAMMOuzbQHQzLh_JEKqOflG6dgCLcBGAs/s1600/error_bland.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="189" data-original-width="408" src="https://4.bp.blogspot.com/-lq8oOkLoCDc/W5ZL3Q2Dc9I/AAAAAAAAT34/q7Bz5LnXAMMOuzbQHQzLh_JEKqOflG6dgCLcBGAs/s1600/error_bland.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">OK, now what?</td></tr></tbody></table>We normally see this if an exception was propagated within a PL/SQL Dynamic Action.<br />In this case I thought it was time for a little upgrade.<br /><br />I noticed the sample code, now part of the&nbsp;<a href="https://docs.oracle.com/database/apex-18.1/AEAPI/Example-of-an-Error-Handling-Function.htm#GUID-2CD75881-1A59-4787-B04B-9AAEC14E1A82" target="_blank">APEX_ERROR documentation</a>,&nbsp;suggested including a reference ID, perhaps from some logging package.<br />Conveniently, we use such a package, a popular one among the PL/SQL community called <a href="https://github.com/OraOpenSource/Logger" target="_blank">Logger</a>.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-LQJC3gJ-p64/W5ZL3n2Kv5I/AAAAAAAAT38/i37r6_Zik84uEaQYwjqeNNzzrKZRyOgOgCLcBGAs/s1600/error_documentation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="485" data-original-width="760" height="254" src="https://1.bp.blogspot.com/-LQJC3gJ-p64/W5ZL3n2Kv5I/AAAAAAAAT38/i37r6_Zik84uEaQYwjqeNNzzrKZRyOgOgCLcBGAs/s400/error_documentation.png" width="400" /></a></div><br />I glanced through the package specification, and for a moment I thought it was missing a function that returned the new log ID.<br /><br />I found a procedure with an OUT parameter instead, so here I log some contextual information about the error.<br /><pre class="brush:sql;highlight:11">logger_user.logger.ins_logger_logs(<br /> p_unit_name =&gt; 'error_handler' ,<br /> p_scope =&gt; 'apx_util.error_handler' ,<br /> p_logger_level =&gt; logger.g_error,<br /> p_extra =&gt; p_error.component.name<br /> ||'~'||p_error.component.type<br /> ||'~'||p_error.message,<br /> p_text =&gt; 'apx_util.error_handler()',<br /> p_call_stack =&gt; dbms_utility.format_call_stack,<br /> p_line_no =&gt; null,<br /> po_id =&gt; l_reference_id<br />);</pre>Now the user has some context to report. I figured the wording could be softened a little, too ;p<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-qVyQYREyxpc/W5ZL4lzrwAI/AAAAAAAAT4E/HvcID-oHs6QGV1Mo4P8fw7bxm_I1EX_9ACLcBGAs/s1600/error_with_ref.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="196" data-original-width="417" src="https://4.bp.blogspot.com/-qVyQYREyxpc/W5ZL4lzrwAI/AAAAAAAAT4E/HvcID-oHs6QGV1Mo4P8fw7bxm_I1EX_9ACLcBGAs/s1600/error_with_ref.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Standard error message, with reference</td></tr></tbody></table><br />So if we were to execute the following SQL, we could see further details.<br /><pre class="brush:sql">select time_stamp, module, client_identifier, extra<br />from logger_user.logger_logs<br />where id = 12292314;</pre>The log message prior to this ID may also help to provide clues as to the problem.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-4SI7N736CtE/W5ZL4NdKjhI/AAAAAAAAT4A/fIQmcer1wf8broGW6f-lv1DFgjbx4GQpwCLcBGAs/s1600/error_logger.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="48" data-original-width="1118" height="24" src="https://3.bp.blogspot.com/-4SI7N736CtE/W5ZL4NdKjhI/AAAAAAAAT4A/fIQmcer1wf8broGW6f-lv1DFgjbx4GQpwCLcBGAs/s640/error_logger.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">SQL results, slightly redacted</td></tr></tbody></table><br />I also wanted to add some convenience to the developer, so I added this same information to the error popup, but only when an active session is also present within the App Builder (or some special privilege present).<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-fLDr7GbrYrc/W5ZL3anhrfI/AAAAAAAAT30/3JTGY4HvrmknEX8qneqrnGmqIdAAnw3HQCLcBGAs/s1600/error_dev.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="284" data-original-width="423" src="https://4.bp.blogspot.com/-fLDr7GbrYrc/W5ZL3anhrfI/AAAAAAAAT30/3JTGY4HvrmknEX8qneqrnGmqIdAAnw3HQCLcBGAs/s1600/error_dev.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Immediate context for the developer</td></tr></tbody></table><br />This is toggled by checking a built in <a href="https://docs.oracle.com/database/apex-18.1/HTMDB/understanding-substitution-strings.htm#GUID-62FE6E65-265A-4BE4-B04B-F90BDA317328" target="_blank">substitution string</a>&nbsp;(or my application item). I note this built-in was only documented from 18.1, but I believe it has been present for a while. It's certainly returns a value in 5.1.<br /><pre class="brush:sql;">l_result.message := 'We had a problem completing this request. '||<br /> 'Please contact IT Support'||<br /> ' for further investigation. Reference: '||l_reference_id<br /> ||case when v('F_SEC_DEV') = 'Y' -- anyone with privilege<br /> -- or has builder open (from oos_util_apex.is_developer)<br /> or coalesce(apex_application.g_edit_cookie_session_id<br /> ,v('APP_BUILDER_SESSION')) is not null then<br /> ' Dev only: '||p_error.component.name<br /> ||' ~ '||p_error.component.type<br /> ||' ~ '||p_error.message<br /> end;</pre>This brightened the day of some of my colleagues. Scott Wesley tag:blogger.com,1999:blog-4818542164384221282.post-8483778542300012931 Mon Sep 10 2018 10:07:00 GMT-0400 (EDT) IG toolbar customization using a function http://lschilde.blogspot.com/2018/09/ig-toolbar-customization-using-function.html <div dir="ltr" style="text-align: left;" trbidi="on"><h2 class="MsoNormal" style="line-height: normal; text-align: justify;"><b><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;; font-size: 18.0pt;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;">IG to<span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;">olbar customizati<span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;">on</span></span></span></span></span></span></span></span></span></span></b></h2><h2 class="MsoNormal" style="line-height: normal; text-align: justify;"></h2><h3 class="MsoNormal" style="line-height: normal; text-align: left;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;">&nbsp;</span></span></span></span></span></h3><h3 class="MsoNormal" style="line-height: normal; text-align: left;"></h3><h4 class="MsoNormal" style="line-height: normal; text-align: left;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;">Life-saving Interactive grid tips</span></span></span></h4><h3 class="MsoNormal" style="line-height: normal; text-align: left;"></h3><h4 class="MsoNormal" style="line-height: normal; text-align: left;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;">&nbsp;</span></h4><h4 class="MsoNormal" style="line-height: normal; text-align: left;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;"><span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;">Reduce <span style="font-family: &quot;arial&quot; , &quot;sans-serif&quot;;">IG initialization</span> code ideas</span></span></span></span></span></h4><div style="text-align: justify;"><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Futher to my p<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">re<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">vio<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">us <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">post just an idea on how to configure and change your Interactive Gri<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">d toolbar by also avoiding to </span></span></span></span></span></span><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">us<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">e</span> <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">J</span>ava<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">S</span>cript initialization code</span> for the same reason.&nbsp;</span></span></span></span></span></span></span></span></span><br /><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Luckily <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">you do not need to <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">create</span> a plugin as this has already been done by <a href="https://apex.world/ords/f?p=100:710:532263331600::::P710_PLG_ID:HR.BILOG.EXTENDIGTOOLBAR" target="_blank">Marko <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">G</span>oricki</a><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">.</span></span></span></span></span></span></span></span></span></span></span> </span></span></span></span></span></span></span></span></span><br /><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Usually what we<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"> would do is&nbsp;used something similar to<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">:&nbsp;</span></span></span></span></span></span></span></span></span></span></span><br /><blockquote class="tr_bq"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">function(config) {<br />&nbsp; var $ = apex.jQuery,<br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">&nbsp;</span> toolbarData = $.apex.interactiveGrid.copyDefaultToolbar(),<br />&nbsp;toolbarGroup = toolbarData.toolbarFind("actions4"); <br />&nbsp; // add a Download button next to the Reset button<br />&nbsp; toolbarGroup.controls.push( {<br />&nbsp;&nbsp;&nbsp; type: "BUTTON",<br />&nbsp;&nbsp;&nbsp; action: "show-download-dialog"<br />&nbsp; });<br />&nbsp; <br />&nbsp; config.toolbarData = toolbarData;<br />&nbsp; return config;<br />}</span></span></span></span></span> </span></span></blockquote></div><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">This e<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">xample shows how to <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">add Dow<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">nload b<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">utton to your IG tool<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">bars</span></span></span></span><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">. In order to reduce this being cop<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">ied across you can u<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">se On page load function similar to:&nbsp;</span></span></span></span></span></span></span></span><br /><blockquote class="tr_bq"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">&nbsp;<span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">function addToolbarButton(groupName, regionID){<br />&nbsp;&nbsp; // get plugin attributes<br />&nbsp;&nbsp;&nbsp; var vGroup&nbsp;&nbsp;&nbsp; = groupName;<br />&nbsp;&nbsp;&nbsp; // get Region<br />&nbsp;&nbsp;&nbsp; var vRegionId = regionID;<br />&nbsp;&nbsp;&nbsp; // Get Widget<br />&nbsp;&nbsp;&nbsp; var vWidget$ = apex.region(vRegionId).widget();<br />&nbsp;&nbsp;&nbsp; // Grid created<br />&nbsp;&nbsp;&nbsp; var toolbar = vWidget$.interactiveGrid("getToolbar");&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; var vaButton = {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: "BUTTON",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; action: "show-download-dialog"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; let config = $.extend(true, {}, toolbar.toolbar('option'))&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; var toolbarData = config.data;<br />&nbsp;&nbsp;&nbsp; var toolbarGroup = toolbarData.filter(function (group) {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return group.id === vGroup&nbsp; <br />&nbsp;&nbsp;&nbsp; })[0]&nbsp; <br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; toolbarGroup.controls.push(vaButton);<br /><br />&nbsp;&nbsp;&nbsp; toolbar.toolbar('option', 'data', config.data); <br />&nbsp;&nbsp;&nbsp;&nbsp; // refresh grid<br />&nbsp;&nbsp;&nbsp; toolbar.toolbar('refresh');<br /><br />}</span></span></span></span></span></span></span></span></span></blockquote><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">when</span> we want to <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">do the same</span><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"> <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">but from a func<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">t<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">ion</span></span></span>.<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"> And then just trigger on page load using <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">add<span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">T</span>ool<span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">bar</span>Button('actions4','dept');&nbsp;</span></span></span></span></span><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><br /></span></span></span></span></span><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">I<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">t does <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">make<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"> more sense to use <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">M</span>arko<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">'</span>s</span> plugin so use the above as an example only. ;)</span></span></span></span></span></span></span><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">&nbsp;</span></span></span></span></span><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"></span></span></span></span></span></span></span></span></span></span></span><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">P</span></span></span></span></span></span></span></span></span><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">lease make sure you check out <a href="https://apex.world/ords/f?p=100:700" target="_blank">apex.world</a> for la<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">test <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">plugins</span>. </span>&nbsp;&nbsp;</span></span></span></span></span></span></span></span><br /><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Happy APEXing,</span></span><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Lino&nbsp;</span></span><br /><br /><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">p.s all credits of the <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">addButton code</span> <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">go<span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"> to <a href="http://apexbyg.blogspot.com/" target="_blank"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Marko</span></a><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">. <span style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Thank you for an awesome plugin</span>!</span></span></span></span></span></span></div> SLino tag:blogger.com,1999:blog-8185384792158425670.post-8436796681138761642 Mon Sep 10 2018 04:15:00 GMT-0400 (EDT)