Gerger Blog

TROUG e-Business Suite SIG Toplantısı

E-Business Suite SIG etkinliği ile TROUG adına güzel bir günü daha geride bıraktık. Bu ayki etkinliğimizi Kıraça’nın sponsorluğunda Pera Müzesi’nde gerçekleştirdik. Bizlere teknoloji ile sanatı bir arada hissettiren Kıraça’ya çok teşekkür ederiz.

Gün boyunca birbirinden güzel ve faydalı sunumlar izledik.

Açılış

Güne açılış konuşmaları ile başlandı. TROUG’un kurucularından H. Tonguç Yılmaz yaptığı giriş konuşmasında TROUG’un kuruluş süreci, amaçları ve etkinlikleri hakkında açıklamalarda bulundu.

Açılış Konuşması – H. Tonguç Yılmaz



Kıraça adına ise açılış konuşmasını Kıraça Holding A.Ş Bilgi Sistemleri Direktörü Sn. Hakan Akmeriç yaptı. Hakan Bey önce Kıraça hakkında bilgi verdikten sonra TROUG ile ilgili düşüncelerini ve fikirlerini paylaştı.

Açılış Konuşması – Hakan Akmeriç


Sunumlar

Güne Aysun Tüfekçi’nin “Oracle EBS Üzerinde Risk ve Uyumluluk Yönetimi” başlıklı sunumu ile başladık. Aysun Hanım, Oracle Fusion GRC ile işletmelerin risk ve uyumluluk yönetimi alanında neler yapabileceği hakkında detaylı bilgi verdi.

Oracle EBS Üzerinde Risk ve Uyumluluk Yönetimi – Aysun Tüfekçi



Daha sonra Yargı Çağlar’ın “Oracle iSupplier Portal ile diğer ERP Entegrasyonu” sunumu ile devam ettik. Bu sunumda satın alma ve tedarik süreçlerine sahip işletmelerin bir Portal ihtiyacı sebeplerine kısaca göz attıktan sonra Yargı Bey bize Oracle iSupplier Portal’ın tercih edilmesi nedenlerini ve getirdiği avantajları gerçek yaşamdan örneklerle açıkladı.

Oracle iSupplier Portal ile diğer ERP Entegrasyonu – Yargı Çağlar


Teknoloji ve Sanat Bir Arada

Ve yüzümüzü teknolojiden sanata çevirdiğimiz an geldi. Sunumlara kısa bir ara verip Pera Müzesini gezmeye başladık. Müze hakkında detaylı bilgi edinirken muhteşem eserleri de yakından inceleme fırsatımız oldu.

İngiltere'ye gönderilen ilk daimi Osmanlı elçisi, Yusuf Agâh Efendi

İngiltere'ye gönderilen ilk daimi Osmanlı elçisi, Yusuf Agâh Efendi

8 Haziran 2005’te açılan Pera Müzesi, Suna ve İnan Kıraç Vakfı’nın nitelikli ve geniş ölçekli kültür-sanat hizmeti vermek amacıyla kurduğu bir özel müzedir.
2003-2005 döneminde restoratör mimar Sinan Genim’in hazırladığı proje çerçevesinde Tepebaşı’ndaki tarihi Bristol Oteli’nin cephesi korunarak çağdaş ve donanımlı bir müze olarak inşa edilen binasında faaliyet göstermektedir.
Kuruluşundan günümüze gerçekleştirdiği etkinliklerle Türkiye’nin en nitelikli, öncü ve sevilen müzelerinden biri haline gelen Pera Müzesi kentin bu çok canlı bölgesinde çağdaş bir müze-kültür merkezi olarak hizmet vermektedir.
Pera Müzesi, tüm sergilerini kitaplar, sözel etkinlikler ve çocuk eğitim programlarıyla da desteklemektedir.
Dönemsel programları ve etkinlikleriyle dikkat çeken Pera Film ise ziyaretçilere ve sinema meraklılarına, klasiklerden bağımsız filmlere, animasyon ve belgesellere uzanan, kimi zaman sergilere paralel kapsamlı gösterimler düzenlemektedir.

Sunumlara Kaldığımız Yerden Devam Ediyoruz

Keyifli Pera turunun ardından Burcu Karayazgan’ın “Oracle EBS ile UFRS Uygulamaları” konulu sunumunda Genel Muhasebe, Borçlar Muhasebesi, Alacaklar Muhasebesi, Hazine Yönetimi ve Varlık Yönetimi konularında yaptıkları çalışmalar hakkında detaylı bilgiler aldık.

Oracle EBS ile UFRS Uygulamaları – Burcu Karayazgan



Ardından Derya İçöz “Oracle EBS ile Entegre Bayi Otomasyon Sistemi” sunumu ile Karsan bayilerinin kullanımına sunulan “Bayi Otomasyon Sistemi” projesi hakkında bize bilgiler verdi. Projeyi Katalog, Araç Satış ve Satış Sonrası Hizmetler ana başlıkları altında inceledik.

Oracle EBS ile Entegre Bayi Otomasyon Sistemi – Derya İçöz



Sabahki programımızı Engin Hafızoğlu’nun “Oracle EBS Bakım Yönetimi Uygulamaları ve Başarı Hikayeleri” ile bitirdik. Engin Bey bakım yönetiminin önemine değindikten sonra sektörde karşımıza çıkabilecek bakım yöntemlerini bize anlattı.

Oracle EBS Bakım Yönetimi Uygulamaları ve Başarı Hikayeleri – Engin Hafızoğlu



Öğle arasından sonra ilk olarak Ömer Faruk Altuntaş ve Mustafa Yılmaz’ın beraber sundukları “Oracle WMS ile Akıllı Depo Yönetimi” sunumunu izledik. Neden WMS, WMS nasıl uygulanır, WMS’in fayda, zarar ve sonuçları nelerdir sorularını KARSAN’da uyguladıkları bir başarı hikayesi üzerinden cevapladılar.

Oracle WMS ile Akıllı Depo Yönetimi – Ömer Faruk Altuntaş ve Mustafa Yılmaz



Ardından Çağıl Gözen’in “MSCA Customization ve Alternatif WEB Uygulaması” sunumunu izledik. “Mobile Supply Chain Applications” mobil platformlar üzerinden depo ve üretim bölümlerine özel işlemler yapmaya olanak veriyor. Ayrıca MSCA’nın neder tercih edilmesi gerektiği ve anatajları hakkında da bilgi edindik.

MSCA Customization ve Alternatif WEB Uygulaması – Çağıl Gözen



Daha sonra Orhan Türkoğlu ve benim birlikte sunduğumuz “Formspider ile Oracle EBS Entegrasyonu” sunumu ile devam ettik. Bu sunumda EBS uygulamalarının Formspider uygulamaları ile nasıl genişletilebileceği hakkında bilgi verdik. Bir EBS uygulamasına kimlik doğrulama ile giriş yaptıktan sonra bir daha giriş yapmaya gerek olmadan, o anki EBS kullanıcısı bilgileri ile bir Formspider uygulaması çalıştırılabilir. Böylece EBS kullanıcısına ait kimlik doğrulama ve yetkilendirme bilgileri Forsmpider uygulamasında da kullanılmaya devam eder. Sunumun son bölümünde EBS uygulaması içinden çağrılan ve EBS datasını kullanan ve güncelleyen bir demo uygulaması gösterdik. Sunumun sonundaki soru/cevap bölümünde çok güzel sorular aldık. Bu da bize yapılan uygulamanın başarısını ve sektörde bu konuda bir ihtiyaç olduğunu gösterdi.

Formspider ile Oracle EBS Entegrasyonu – Orhan Türkoğlu ve Uğur Koçak



Günü Seçkin Candemir’in sunduğu “Oracle BI Publisher ile Raporlama” sunumu ile kapattık. Bu sunumla Oracle BI Publisher ile şablon tabanlı, hızlı, kolay ve esnek raporlar geliştirebileceğimizi öğrendik.

Oracle BI Publisher ile Raporlama – Seçkin Candemir



Sunumların hepsi birbirinden güzeldi. Soru / Cevap bölümlerine katılım ortalamanın çok üzerindeydi. Bu da sunumların ne kadar başarılı olduğunu gösteriyor zaten. Emeği geçen ve katılan herkese teşekkürler.

Kapanış

Bu güzel etkinlik Ümit Varol’un kapanış konuşmasıyla sona erdi.

Kapanış – Ümit Varol





Uğur Koçak
Gerger

ORA-04030 and dbms_xslProcessor.valueOf

While reading values from XML nodes for a bulk operation, we encountered the “ORA-04030: out of process memory when trying to allocate…” error raised by dbms_xslProcessor.valueOf procedure.

When I first searched the web, I found out that small PGA size or kernel parameters not large enough to allow enough RAM was the cause of the problem. Then I tried to tune the database and operating system parameters. However down that path madness lied. Soon enough I’ve found myself playing with parameters that are better left alone.

Then I tried XMLType API’s instead of the XMLDom API’s and the result was successful. Memory and SWAP usage significantly decreased.

How to read xml node values with XMLType

My XML to read looks like:

<PANELDTLS>
  <PANELDTL>
    <ENABLED_YN>Y</ENABLED_YN>
    <INSERT_YN>N</INSERT_YN>
    <LABEL_TX>ID</LABEL_TX>
  </PANELDTL>
  <PANELDTL>
    <ENABLED_YN>Y</ENABLED_YN>
    <INSERT_YN>N</INSERT_YN>
    <LABEL_TX>Description</LABEL_TX>
  </PANELDTL>
  <PANELDTL>
    <ENABLED_YN>Y</ENABLED_YN>
    <INSERT_YN>N</INSERT_YN>
    <LABEL_TX>Name</LABEL_TX>
  </PANELDTL>
  .
  .
  .
</PANELDTLS>

and I want an output like:

ENABLED_YN INSERT_YN LABEL_TX
---------- --------- -----------
Y          N         ID
Y          N         Name
Y          N         Description

Here is the query to read text node:

select dbms_xmlgen.convert(
         extract(column_value,'/PANELDTL/ENABLED_YN/text()').getStringVal(),
         1 /*means decrypt escape characters*/ ) enabled_yn,
       dbms_xmlgen.convert(
         extract(column_value, '/PANELDTL/INSERT_YN/text()').getStringVal(),
         1) insert_yn,
       dbms_xmlgen.convert(
         extract(column_value, '/PANELDTL/LABEL_TX/text()').getStringVal(),
         1) label_tx
from table( XMLSequence( xmltype(
'<PANELDTLS>
  <PANELDTL>
    <ENABLED_YN>Y</ENABLED_YN>
    <INSERT_YN>N</INSERT_YN>
    <LABEL_TX>ID</LABEL_TX>
  </PANELDTL>
  <PANELDTL>
    <ENABLED_YN>Y</ENABLED_YN>
    <INSERT_YN>N</INSERT_YN>
    <LABEL_TX>Description</LABEL_TX>
  </PANELDTL>
  <PANELDTL>
    <ENABLED_YN>Y</ENABLED_YN>
    <INSERT_YN>N</INSERT_YN>
    <LABEL_TX>Name</LABEL_TX>
  </PANELDTL>
</PANELDTLS>').extract('/PANELDTLS/PANELDTL')))

Uğur Koçak

The 100th Confirmed Installation

When we made Formspider Installer available in February, we counted how many people are actually downloading it. After a while a thought came to our minds. PL/SQL developers from all over the world were downloading Formspider. But were they installing it? We had built a notification system to the installer that alerted us when an installation attempt failed (with user’s permission of course). However, we had no mechanism to know how many of the installation attempts succeeded. We updated the installer in May to count the successful installations.

Formspider Installer opens up a thank you web page when the installation completes and we count how many times we render the thank you page. This page serves to a much more important purpose too. We’ve felt like the end of the installation did not really reflect our sentiments about how happy we are that you are giving Formspider a shot. Our thank you page shows how we really feel about it.

Formspider surged passed 100 installations in just five weeks. This is amazing. Thanks to Formspider, we have met many people from all around the world. We exchanged ideas, received invaluable feedback and hopefully we were able to help them as well.

On behalf of the team, I would like to sincerely thank everyone who is giving Formspider a shot. We love to hear what people do with Formspider. Please don’t be a stranger. Let us know what you do. Send us an email, ask a question or get involved in social networks. We are here to help.

Let’s meet at Oracle Open World

This year, Formspider team applied to present at the Oracle OpenWorld via Oracle Mix. We submitted the presentation “Forms Modernization: The PL/SQL Way”.

We believe Oracle Forms modernization is an important topic for many Oracle customers. We would like to share our experience and knowledge in how organizations can protect their Forms and PL/SQL investment. If you are interested in seeing this presentation at Oracle OpenWorld please vote for it on the Oracle Suggest-A-Session page.

Admittedly, the process to vote is a little tedious. If you don’t have an Oracle account, you have to sign up and then vote for at least three presentations in order for your vote to be valid. However, we promise the presentation will be totally worth your effort. :-)

Vote for Forms Modernization: The PL/SQL Way now.

Free PL/SQL and Web 2.0 Training

Formspider, our Web 2.0 framework for PL/SQL developers, is moving ahead full speed. In four months and with just a $5/day Google AdSense budget, Formspider surpassed 500 downloads and 500 online users. We all would like to thank you from the bottom of our hearts.

We are determined to help PL/SQL developers build amazing web applications. We believe Formspider is the best way to achieve this goal. To prove this, we are offering free Formspider training to anyone who is interested.

So how does this actually work? If you are located in Istanbul, Turkey just contact us to schedule the training.

If you are not located in Istanbul, we can come to your office anywhere in the world and provide a five day Formspider training completely free of charge. The training may be for one developer or hundred. All we ask from you is to pay for travel, lodging and a reasonable €100 Per Diem for the daily expenses of the trainer. The five day training itself is completely free.

Contact us now, let us show you how Formspider can help you build platform independent beautiful web applications with just PL/SQL.

Javascript vs. JavaFX

We built the XML Editor for the Formspider IDE in Java, because the original Formspider IDE was a Java Application. When we were preparing the Formspider Online IDE for the Web, we also had to move the XML Editor to the Web. In one of the brilliant moments of my career I told the team “Hey, we have a working editor in Java. Why don’t we convert it to JavaFX and be done with it?” This should be simple right? Right…After months of work, we finally got the editor working in JavaFX. The fact that we converted from Java to JavaFX, did not help as much as we hoped it would.

We went live with the Formspider Online IDE and started observing user behavior. Something was not right. People were signing up but not really doing anything. A quick investigation revealed that we were having problems with the XML Editor. It was failing for more than 50% of our users. Some people didn’t have Java on their machines, some had the open SDK that did not support JavaFX and some had problems we could not figure out.

Formspider IDE was not a joyride for the lucky few who was able to run the editor either. On average, a user had to wait about two minutes before the IDE was ready for input. The 1.5 MB jar was downloaded quickly enough but it took ages for the computer to install the jar and getting it ready to run. The security alert that kept popping up was also very annoying from the user’s perspective.The state we were in with the Online IDE was clearly unacceptable.

JavaScript came to the rescue. We were actually smart enough to sponsor a coding contest for a JavaScript editor while we were working on the JavaFX one. The team of Bilal Gültekin and Bahattin Tozyılmaz were the winners. In the picture below you see Bilal receiving their bounty, a teddy bear filled with $2600 dollars. We are also looking forward to host both Bilal and Bahattin as our interns this summer.

The Award Ceramony

After the contest was over, Öskan took over the code base for the XML Editor in JavaScript and prepared it for production use. After several weeks of work, the editor was ready for beta testing. However, the problem was so severe that even a partially working editor written in JavaScript was better than a thoroughly tested editor written in JavaFX. So we skipped the beta pretty quickly. We were already annoying pretty much every user, how much worse could we really get?

After a few quick iterations, we were incredibly happy with the results. Now our new XML Editor written entirely in JavaScript loads instantly and runs for our every user. Most importantly, our users started to engage with the Online IDE. I see them creating panels, text fields and windows everyday.

If you used the Formspider Online IDE before and you did not have a pleasant experience at all, I apologize and kindly invite you to give it another try. If this is going to be your first time with the Online IDE, nevermind… It all works just fine.

Caching Dynamically Generated Scripts

If static JavaScript or CSS files are served from the application server, we take it for granted that they are going to be cached by the browsers. However, dynamically generated content (Javascript and CSS in particular) could also be cached as if it is static and sent from the server only when it is changed. Nevertheless, application servers provide no support for this at all. So, the responsibility rests on the shoulders of the server-side code which generates dynamic content.

I looked all over the Internet but was unable to find a solution, so I wrote my own code. It’s written for a Java Servlet but the same logic can be applied to other languages too. The servlet below sends a piece of JavaScript to the client that it builds dynamically and adds the necessary headers to the response so that the browser can cache it.

Here’s the code that gets the job done:

public class TestServlet extends HttpServlet {
    private static final String CONTENT_TYPE = "application/x-javascript";

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    public void doGet(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException, IOException {

        Calendar c1 = Calendar.getInstance();
        c1.clear();
        c1.set(2011,2,22,13,12);
        long lastModifiedDate = c1.getTimeInMillis();

        response.setContentType(CONTENT_TYPE);
        response.addDateHeader("Last-Modified",lastModifiedDate);

        PrintWriter out = response.getWriter();

        long lastFetchedDate = request.getDateHeader("If-Modified-Since");
        boolean notModified = false;
        if (lastFetchedDate>-1){
            if (lastModifiedDate<=lastFetchedDate){
                response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                notModified = true;
            }
        }
        if (!notModified){
            System.out.println("test");
            out.println("var test = {};");
            out.println("test['a']='b';");
            out.println("alert(test['a']);");
        }

    }

    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
} 

To keep the example simple, I used a static date for the last modified date.

Here is how you can include this servlet in an html document as a javascript file:

<html>
    <head>
    <script type="text/javascript" src="http://localhost/test/testservlet"></script>
    </head>
    <body>
    </body>
</html>

When you run this from an application server, the first time you access the page you will see the message “test” in application server console, meaning that the servlet did the necessary work and generated the JavaScript code. The next time you access the page, the JavaScript will already be cached by the browser. Therefore, even the alert still pops up when the page is accessed, you will not the see message “test” in the server console. Since the dynamically created JavaScript is already cached in the browser and the headers were set up correctly, the server did not bother to generate the code all over again and responded much faster just like it would if the JavaScript was actually in a static file. 

M. Serdar Biçer

Aloha ICSSP 2011

We are thrilled to announce that our team member M. Serdar Biçer will present his paper “Defect Prediction Using Social Network Analysis on Issue Repositories” at the International Conference on Software and Systems Process, ICSSP 2011. His work generated great interest from the committee of reviewers and was one of the 18 papers accepted to the conference world wide. We congratulate him for his amazing success. Serdar, enjoy your trip to Hawaii!

Google Maps Api v3 Location Search with jQuery Autocomplete Plugin

When I needed Google Maps style auto complete in my application, I looked into a lot of JavaScript libraries but I couldn’t find a useful solution. Since I’m new to JQuery, at first I couldn’t realize how it simple all this was.

With JQuery auto complete plug-in we can pull data from local or remote sources. In this example , I used google.maps.Geocoder as the remote data source.

For those who are not familiar with the term, geocoding is the process of converting addresses like (“1600 Amphitheatre Parkway, Mountain View, CA”) into geographic coordinates (latitude and longitude values).

There are two different geocode requests in this example:

1. I used first geocoding request to convert user address into latitude and longitude values,
2. The second request is the Reverse Geocoding, to convert search results into human readable format.

Reverse Geocoding often returns more than one result. I think it is best to fetch all these results and serve all of them to the user instead of showing only one result.

After getting search results for a given keyword, the map’s viewport is adjusted to the selected search result using map.fitBounds(bounds).

Let’s examine the script;

First initialize the map with basic options;

var mapOptions = {
  zoom : 10,
  mapTypeId: google.maps.MapTypeId.ROADMAP,
  center: new google.maps.LatLng(41.06000,28.98700)
};

var map = new google.maps.Map(document.getElementById("map"),mapOptions);



Then create a google Geocoder object;

var geocoder = new google.maps.Geocoder();

Bind the auto complete event to the search input box,

$(function() { $("#searchbox").autocomplete({ source: function(request, response) {

In source event I created a callback function that process the geocoder results;

geocoder.geocode( {'address': request.term }, function(results, status) { if (status == google.maps.GeocoderStatus.OK) {



My first geocoder request takes address as a parameter, and the callback functions processes the returning result object if geocoder status is OK. Then using the returning location which usually has one string, I prepare a Google Maps LatLng object to get a list of search results with reverse geocoding;

var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
var latlng = new google.maps.LatLng(lat, lng);



This is the second and the last request to google geocoder with latlng;

geocoder.geocode({'latLng': latlng}, function(results1, status1) {

This request also have a callback function that generates label, value and bounds

if (status1 == google.maps.GeocoderStatus.OK) {
if (results1[1]) {
             response($.map(results1, function(loc) {
        return {
         label: loc.formatted_address,
         value: loc.formatted_address,
         bounds: loc.geometry.bounds
}
               }));
          }
    }
 });

Finally, when the user selects an option from search results, to navigate the map to that place, I wrote the following code in the auto complete select event;

select: function(event,ui){
var bounds = ui.item.bounds;
  map.fitBounds(bounds);
 }

Here is the full demonstration of my auto complete example;


<!DOCTYPE PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> 
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script> 
  <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
  <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>  
 </head>
 <body>
  <h1>Google Maps Autocomplete Search Sample</h1>
  <div align="left">
   <input type="text" value="" id="searchbox" style=" width:800px;height:30px; font-size:15px;">
  </div>
  <div align="left" id="map" style="width:800px; height: 600px; margin-top: 10px;">
   
  </div>
  
 </body>
</html>
<script type="text/javascript">
 $(document).ready(function(){

  var mapOptions = {
       zoom: 10,
       mapTypeId: google.maps.MapTypeId.ROADMAP,
       center: new google.maps.LatLng(41.06000,28.98700)
     };

  var map = new google.maps.Map(document.getElementById("map"),mapOptions);

  var geocoder = new google.maps.Geocoder();  

     $(function() {
         $("#searchbox").autocomplete({
         
           source: function(request, response) {

          if (geocoder == null){
           geocoder = new google.maps.Geocoder();
          }
             geocoder.geocode( {'address': request.term }, function(results, status) {
               if (status == google.maps.GeocoderStatus.OK) {

                  var searchLoc = results[0].geometry.location;
               var lat = results[0].geometry.location.lat();
                  var lng = results[0].geometry.location.lng();
                  var latlng = new google.maps.LatLng(lat, lng);
                  var bounds = results[0].geometry.bounds;

                  geocoder.geocode({'latLng': latlng}, function(results1, status1) {
                      if (status1 == google.maps.GeocoderStatus.OK) {
                        if (results1[1]) {
                         response($.map(results1, function(loc) {
                        return {
                            label  : loc.formatted_address,
                            value  : loc.formatted_address,
                            bounds   : loc.geometry.bounds
                          }
                        }));
                        }
                      }
                    });
            }
              });
           },
           select: function(event,ui){
      var pos = ui.item.position;
      var lct = ui.item.locType;
      var bounds = ui.item.bounds;

      if (bounds){
       map.fitBounds(bounds);
      }
           }
         });
     });   
 });
</script>

Aziz Ünsal ( @azizunsall )

Formspider Available for Local Installation

We just made Formspider available for downloading and installing locally. This was important as there was quite a bit of interest in the local installation. The team tested the hell out of the installer but please, please, pretty please let us know if you run into any issues. Giving feedback is incredibly easy. If the installer fails, it will ask your permission to send us the installation log. It collects no personal information and asks for an optional email address to get back to you when the problem is fixed.

The Installer currently supports Windows only. We are going to support other platforms but in the meantime, if you need Formspider installed to a different OS, contact us at contact@theformpider.com. We’d be happy to guide you through it.