Tuesday, December 31, 2013

javaFX redirect page and passing object to controller

i am building a java desktop application using javaFX 2.2 with FXML to create the user interface, following this (http://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm) tutorial.

i use jdk7u45, the jfxrt.jar is located in $JAVA_HOME/jre/lib/jfxrt.jar.
note: if u're facing an exception
 Exception in thread "main" java.lang.NoClassDefFoundError: javafx/application/Application   
when running the app, the jar is not loaded in the classpath, an alternative solution is to copy the jfxrt.jar to $JAVA_HOME/jre/lib/ext/ folder.

back to topic, the tutorial above give us an example to create a page using FXML and bind it's components and action listener method to a java controller class. and the follow-through question is: how to redirect page and passing object between controller class in javaFX?

this is not a tutorial, just want to share how i do page redirect in javaFX and passing object between controller classes.

first of all, it's the structure. it's kind of like this:


stage(window) - scene - page.
the stage is instantiate by javafx's Application, act as the application window. i figure scene as a wrapper of a page. and a page is the user interface we create using fxml and the controller.

from that structure, to enable redirection, we should save the instance of the stage somewhere that can be retrieved by each page, and there should be a controller manager which manage the page rendering.

so, architecturally, i separate the page controller manager (the one that controls the content of the main window, loads and renders the page of a scene) from the pages, including the main page.

here's the controller manager, i named it CommonController:
 public abstract class CommonController implements Initializable {  
   public final Logger LOGGER = Logger.getLogger(this.getClass().getName());  
   private static final String UI_BASE_LOCATION = "/pages/";  
   private static final String FXML_PREFIX = ".fxml";  
   private RestClient restClient = new RestClient();  
   public static void setSceneContentStartup(Stage stage) throws IOException{  
     Context.getInstance().setCurrentStage(stage);  
     setSceneContent("login");  
   }  
   public static Parent setSceneContent(String pageName) throws IOException {  
     Stage currentStage = Context.getInstance().getCurrentStage();  
     Scene scene = currentStage.getScene();  
     Parent page = (Parent) FXMLLoader.load(CommonController.class.getResource(UI_BASE_LOCATION + pageName + FXML_PREFIX));  
     if (scene == null) {  
       scene = new Scene(page);  
       currentStage.setScene(scene);  
       currentStage.setTitle("Sample JavaFX Application");  
       currentStage.setWidth(800);  
       currentStage.setHeight(600);  
     } else {  
       currentStage.getScene().setRoot(page);  
     }  
     currentStage.centerOnScreen();  
     currentStage.sizeToScene();  
     currentStage.show();  
     return page;  
   }  
   public RestClient getRestClient(){  
     return restClient;  
   }  
 }  

this is an abstract class, so it couldnt be instantiated and it implements Initializable so every controller class that extends this class will have to implement the initialize method.

this class holds the .fxml file folder location, and the setSceneContent receive a string as input argument which is the filename of the page's .fxml file and load the file, put it in a scene, and assign the scene to the stage showing. this method loads and renders the page.

we see that the scene that contained to page we want is attached to the stage. so we need to retrieve the current showing stage. for that case, i make a static holder for the stage, and this holder can be use also for holding some objects that want to be passed between controller, i name it as Context:
 public class Context {  
   private static Context instance;  
   public static Context getInstance(){  
     return instance == null ? new Context() : instance;  
   }  
   private static Map<String, Object> contextObjects = new HashMap<String, Object>();  
   private static Stage currentStage;  
   public Map<String, Object> getContextObjects(){  
     return contextObjects;  
   }  
   public Object getContextObject(String key){  
     return contextObjects.get(key);  
   }  
   public Object removeContextObject(String key){  
     return contextObjects.remove(key);  
   }  
   public void addContextObject(String key, Object value){  
     contextObjects.put(key, value);  
   }  
   public void clearContextObjects(){  
     contextObjects.clear();  
   }  
   public Stage getCurrentStage() {  
     return currentStage;  
   }  
   public void setCurrentStage(Stage stage) {  
     currentStage = stage;  
   }  
 }  

here's the main page:
 public class MainPage extends Application {  
   public static void main(String[] args) {  
     Application.launch(args);  
   }  
   @Override  
   public void start(Stage stage){  
     try {  
       CommonController.setSceneContentStartup(stage);  
     } catch (IOException ex) {  
       Logger.getLogger(MainPage.class.getName()).log(Level.SEVERE, null, ex);  
     }  
   }  
 }  

the MainPage called the CommonController.setSceneContentStartup and passed the stage as the argument. and that method stored the stage to Context
 Context.getInstance().setCurrentStage(stage);  
and call the redirect/rendering method
 setSceneContent("login");  
which asks to load and render page login.fxml.

and so, the login.fxml is rendered and showed in the stage. what about the redirection?

let's see the login page:
 <GridPane fx:controller="org.mazb.samplejavafx.controller.LoginController"  
      xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">  
   ...  
   <HBox spacing="10" alignment="bottom_right"  
      GridPane.columnIndex="1" GridPane.rowIndex="4">  
     <Button text="Sign In"    
         onAction="#handleSubmitButtonAction"/>  
   </HBox>  
   ...  
 </GridPane>  

and login controller:
 public class LoginController extends CommonController {  
   @FXML  
   private Text actiontarget;  
   @FXML  
   private TextField usernameField;  
   @FXML  
   private PasswordField passwordField;  
   @Override  
   public void initialize(URL url, ResourceBundle rb) {  
     LOGGER.log(Level.INFO, "initialize not implemented yet.");  
   }  
   @FXML  
   protected void handleSubmitButtonAction(ActionEvent event) {  
     String username = usernameField.getText();  
     String pass = passwordField.getText();  
     User user = new User(username, pass);  
     user = (User) getRestClient().postFormData(user, CommonConstant.RestOperationPath.VALIDATE_USER);  
     if(user==null){  
       actiontarget.setText("forbidden");  
     }else{  
       try {  
         Context.getInstance().addContextObject("loggedInUser", user);  
         setSceneContent("home");  
       } catch (IOException ex) {  
         LOGGER.log(Level.SEVERE, null, ex);  
       }  
     }  
   }  
 }  

when button is clicked, it will trigger the invocation of method handleSubmitButtonAction.

in my case, the process then will invoke a site via rest, and check the result. if the result is not null, then it will ask to redirect to page home.fxml and passes the object result.

the object to be passed is placed in static HashMap ContextObjects and can be retrieved anytime. the CommonController will then get the current stage from the Context, and load home.fxml and then render it.

and then the home.fxml is rendered:
 <GridPane fx:controller="org.mazb.samplejavafx.controller.HomeController"  
      xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">  
   ...  
   <Text fx:id="welcomeText" id="welcome-text"  
      GridPane.columnIndex="0" GridPane.rowIndex="0"  
      GridPane.columnSpan="2"/>  
 </GridPane>  

and the method initialize in HomeController will be invoked:
 public class HomeController extends CommonController {  
   private User user;  
   @FXML  
   private Text welcomeText;  
   @Override  
   public void initialize(URL url, ResourceBundle rb) {  
     user = (User) Context.getInstance().getContextObject("loggedInUser");  
     welcomeText.setText("Welcome, "+user.getRealName());  
   }  
 }  

in the method, we retrieved the passed ContextObject (instance of User) and assign its property realName to the welcomeText.

the page is succesfully redirected, the object is successfully passed. i think, until this time, this is the most suitable architecture for page redirection and object passing in javaFX.

sample source code is available at https://github.com/mazbergaz/sample_javafx

Monday, December 16, 2013

How To Act on Tasks That Require a Password on Oracle BPM

Pada blog kali ini , saya akan membagikan cara untuk membubuhi password yang wajib di isi terlebih dahulu sebelum melanjukan suatu user task. Cara ini bertujuan untuk keamanan suatu proses yang tidak semua orang bisa lakukan.

Sudah tahu bukan cara untuk membuat usertask yang dilengkapi human task seperti yang sudah saya paparkan pada blog sebelumnya? Kalau belum bisa di lihat di sini

Mari kita mulai ...
  1. Buat beberapa user task, pada kali ini saya akan membuat 5 user task, kemudian klik kanan pada user task yang akan di tambahkan sistem keamanan password.

  2. Setelah terbuka window human task, pilih tab Access, kemudian menuju menu Signature policy yang default nya none, kemudian ubah menjadi configure policy


  3. Setelah memilih configure policy, pilih password required, kemudian pilih ok.

  4. Deploy aplikasi anda, lalu masuk ke webcenter portal/bpm workspace, dan jalankan aplikasi anda.
  5. Isi field - field yang tersedia, kemudian langsung pilih submit. Kita akan lihat apakah bisa langsung tereksekusi atau tidak ^__^


  6. Ternyata untuk mengeksekusi pilihan, kita perlu memasukkan password id kita, setelah anda memasukkan passwordnya, kemudian pilih ok dan anda bisa langsung mengeksekusi submit seperti biasa lagi ^__^
Sekian blog singkat saya, semoga bermanfaat !

How To Act on Tasks That Require a Comment on Oracle BPM

Pada blog kali ini , saya akan membagikan cara untuk membubuhi komentar yang wajib dahulu sebelum melanjukan suatu usertask, ini cukup bermanfaat untuk mengantisipasi "penggunaan asal approve"

Sudah tahu bukan cara untuk membuat usertask yang dilengkapi human task seperti yang sudah saya paparkan pada blog sebelumnya? Kalau belum bisa di lihat di sini

Mari kita mulai...
  1. Buat beberapa user task, pada kali ini saya akan membuat 5 user task, kemudian klik kanan pada user task yang akan di tambahkan wajib di isi komentar.

  2. Setelah terbuka window human task, pilih tab General, kemudian cari yg bernama Outcomes, lalu klik pada tanda magnifier/kaca pembesar.

  3. Setelah mengklik kaca pembesar, maka akan muncul Outcomes Dialog. Lalu klik pada bagian Outcomes Requiring Comment.

  4. Pilih pada pilihan mana yang diwajibkan untuk mengisi komentar, lalu pilih oke. Pada kali ini saya akan memilih pilihan Submit yang harus di isi komentar.

  5. Deploy aplikasi anda, lalu masuk ke webcenter portal/bpm workspace, dan jalankan aplikasi anda.
  6. Isi field - field yang tersedia, kemudian langsung pilih submit. Kita akan lihat apakah bisa langsung tereksekusi atau tidak ^__^



  7. Ternyata kita memang harus di wajibkan untuk mengisi komentar terlebih dahulu. Pada bagian Comment, kemudian Create Comment.
  8. Isi Komentar sesuai yang ingin anda sampaikan, pada kali ini saya akan mengisi dengan kata kata "Jangan Lupa Isi Comment ^__^"
  9. Setelah anda isi komentar, anda bisa langsung mengeksekusi submit seperti biasa lagi ^__^
Sekian blog saya, semoga bermanfaat !


Sunday, December 15, 2013

Migrating a WebLogic Domain from VirtualBox to Cloud


Beberapa minggu yang lalu kami butuh untuk menampilkan showcase WebCenter Portal ke salah satu klien kami. Pada waktu itu development server Nostratech (Bima) saat itu sedang proses maintenance, sehingga tidak dapat digunakan. Setelah mempertimbangkan faktor effort, waktu, biaya, dan bandwidth, akhirnya kami memutuskan untuk memanfaatkan cloud service seperti DigitalOcean untuk showcase tersebut. Prosedurnya yang dilakukan adalah dengan mempersiapkan deployment-nya di lingkungan VirtualBox, dan meng-upload deployment tersebut ke DigitalOcean. 

Sayangnya DigitalOcean tidak mendukung untuk konversi dari VirtualBox, sehingga WebLogic Domain yang di-deploy di VirtualBox harus se-portable mungkin agar dapat dipindah-pindahkan dengan mudah ke lingkungan yang lain tanpa harus melakukan banyak perubahan. Deployment yang saya lakukan di VirtualBox tidak akan didetilkan pada artikel ini karena sudah mengikuti dokumentasi Oracle dikombinasikan dengan konfigurasi Node Manager pada artikel saya sebelumnya.

Namun ada beberapa catatan yang penting agar proses migrasi dapat berjalan dengan mulus:
  1. OS yang digunakan adalah CentOS 5.8 (64-bit), karena OS tersebut adalah image OS yang disediakan oleh DigitalOcean dan OS yang paling dekat relasinya dengan Oracle Enterprise Linux 5.8 yang sudah disertifikasi oleh Oracle.
  2. Install paket RPM oracle-validated melalui Oracle Public Yum Server untuk mempermudah proses instalasi produk-produk Oracle.
  3. Instalasi Oracle Database server dan Oracle WebCenter Portal domain dilakukan pada instance VirtualBox yang berbeda.
  4. Install Oracle Database jangan menggunakan filesystem Oracle ASM, karena akan mempersulit proses migrasinya nanti.
  5. Selalu menggunakan FQDN dalam mereferensi hostname, seperti database host, WebLogic listen address, dan lain-lainnya. Berhubung nantinya akan di-deploy ke DigitalOcean, saya sudah menggunakan penamaan hostname menggunakan domain nostratech.com agar tidak perlu mengubah lagi. Praktik ini juga sangat saya sarankan di manapun, agar deployment yang kita lakukan dapat lebih portable.
  6. Pisahkan lokasi ORACLE_BASE antara Oracle Database (/u03/app/oracle) dengan Oracle WebCenter Portal (/u01/app/oracle).
  7. Sesuaikan rule firewall dengan level keamanan yang Anda inginkan, pada artikel ini tidak akan membahas mengenai rule firewall yang diperlukan.
  8. Pastikan bandwidth uplink yang memadai untuk proses upload DigitalOcean. :)

Proses Backup di VirtualBox


Setelah proses instalasi dan konfigurasi selesai, shutdown seluruh WebLogic Domain beserta proses Database instance-nya. Lakukan langkah-langkah berikut di instance Database:
  1. Catat semua hostname yang diperlukan.
  2. Backup ORACLE_BASE menggunakan user root.
    oracle@db-vbox:~ $ su -
    root@db-vbox:~ # cd /u03/app
    root@db-vbox:/u03/app # tar cvvzpf /home/oracle/MIGRATE/ORACLE_BASE.tar.gz oracle
    root@db-vbox:/u03/app # exit
  3. Backup ORACLE_INVENTORY.
    oracle@db-vbox:~ $ tar cvvzpf ~/MIGRATE/ORAINVENTORY.tar.gz oraIventory
  4. Backup ORADIAG.
    oracle@db-vbox:~ $ tar cvvzpf ~/MIGRATE/ORADIAG.tar.gz oradiag_oracle
  5. Backup oraInst.loc dan oratab.
    oracle@db-vbox:~ $ cp /etc/ora* ~/MIGRATE/

Sementara di instance WebLogic Domain, ikuti langkah-langkah berikut:
  1. Catat semua hostname yang diperlukan.
  2. Backup ORACLE_BASE.
    oracle@portal-vbox:~ $ cd /u01/app
    oracle@portal-vbox:/u01/app $ tar cvvzpf ~/MIGRATE/ORACLE_BASE.tar.gz oracle
    oracle@portal-vbox:/u01/app $ cd /u02/app
    oracle@portal-vbox:/u02/app $ tar cvvzpf ~/MIGRATE/ORACLE_BASE_PRIVATE.tar.gz oracle
  3. Backup ORAINVENTORY.
    oracle@portal-vbox:~ $ tar cvvzpf ~/MIGRATE/ORAINVENTORY.tar.gz oraInventory
  4. Backup ORADIAG.
    oracle@portal-vbox:~ $ tar cvvzpf ~/MIGRATE/ORADIAG.tar.gz oradiag_oracle
  5. Backup BEA_HOMES.
    oracle@portal-vbox:~ $ tar cvvzpf ~/MIGRATE/BEA_HOMES.tar.gz bea
  6. Backup oraInst.loc.
    oracle@portal-vbox:~ $ cp /etc/ora* ~/MIGRATE/

Upload backup tersebut ke masing-masing droplet di DigitalOcean. Kesabaran sangat dibutuhkan pada tahap ini, kemarin saya upload sekitar 4 jam baru selesai. :)

Proses Restore ke DigitalOcean


Selagi menunggu proses upload ke droplet, jangan lupa untuk menginstalasi paket RPM oracle-validated pada kedua droplet tersebut. Setelah proses upload selesai, lakukan langkah-langkah berikut untuk me-restore Database:
  1. Sesuaikan hostname dengan IP yang terkonfigurasi pada droplet.
  2. Restore ORACLE_BASE menggunakan user root.
    oracle@db-droplet:~ $ su -
    root@db-droplet:~ # mkdir -p /u03/app
    root@db-droplet:~ # chown -R oracle:oinstall /u03/app
    root@db-droplet:~ # cd /u03/app
    root@db-droplet:/u03/app # tar xvvzpf /home/oracle/MIGRATE/ORACLE_BASE.tar.gz
    root@db-droplet:/u03/app # exit
  3. Restore ORAINVENTORY.
    oracle@db-droplet:~ $ tar xvvzpf ~/MIGRATE/ORAINVENTORY.tar.gz
  4. Restore ORADIAG.
    oracle@db-droplet:~ $ tar xvvzpf ~/MIGRATE/ORADIAG.tar.gz
  5. Restore oraInst.loc dan oratab.
    oracle@db-droplet:~ $ su
    root@db-droplet:/home/oracle # cp ~/MIGRATE/ora* /etc/
    root@db-droplet:/home/oracle # exit
  6. Reinstall Oracle scripts.
    oracle@db-droplet:~ $ su -
    root@db-droplet:~ # /u03/app/oracle/product/11.2.0/dbhome_1/root.sh
    root@db-droplet:~ # exit
  7. Validasi instalasi dengan startup Database.
    oracle@db-droplet:~ $ . oraenv
    oracle@db-droplet:~ $ lsnrctl start
    oracle@db-droplet:~ $ sqlplus / as sysdba
    SQL> startup
    
Setelah Database sudah valid pada droplet, WebLogic Domain dapat di-restore dengan mengikuti langkah-langkah berikut:
  1. Sesuaikan hostname dengan IP yang terkonfigurasi pada droplet.
  2. Restore ORACLE_BASE.
    oracle@portal-droplet:~ $ su -
    root@portal-droplet:~ # mkdir -p /u01/app
    root@portal-droplet:~ # chown -R oracle:oinstall /u01/app
    root@portal-droplet:~ # mkdir -p /u02/app
    root@portal-droplet:~ # chown -R oracle:oinstall /u02/app
    root@portal-droplet:~ # exit
    oracle@portal-droplet:~ $ cd /u01/app
    oracle@portal-droplet:/u01/app $ tar xvvzpf ~/MIGRATE/ORACLE_BASE.tar.gz
    oracle@portal-droplet:~ $ cd /u02/app
    oracle@portal-droplet:/u02/app $ tar xvvzpf ~/MIGRATE/ORACLE_BASE_PRIVATE.tar.gz
  3. Restore ORAINVENTORY.
    oracle@portal-droplet:~ $ tar xvvzpf ~/MIGRATE/ORAINVENTORY.tar.gz
  4. Restore ORADIAG.
    oracle@portal-droplet:~ $ tar xvvzpf ~/MIGRATE/ORADIAG.tar.gz
  5. Restore BEA_HOMES.
    oracle@portal-droplet:~ $ tar xvvzpf ~/MIGRATE/BEA_HOMES.tar.gz
  6. Restore oraInst.loc menggunakan user root.
    oracle@portal-droplet:~ $ su -
    root@portal-droplet:~ # cp /home/oracle/MIGRATE/ora* /etc/
    root@portal-droplet:~ # exit
  7. Validasi deployment dengan startup WebLogic Domain.
    oracle@portal-droplet:~ $ cd /u02/app/oracle/admin/nodemanager
    oracle@portal-droplet:/u02/app/oracle/admin/nodemanager $ export JAVA_OPTIONS="-DDomainRegistrationEnabled=true"
    oracle@portal-droplet:/u02/app/oracle/admin/nodemanager $ java weblogic.WLST NodeManager.py
    oracle@portal-droplet:/u02/app/oracle/admin/nodemanager $ java weblogic.WLST AdminServer.py

Demikian langkah-langkah sederhana yang saya lakukan untuk berhasil memindahkan deployment WebLogic Domain beserta Database-nya dari lingkungan VirtualBox ke cloud service. Selamat mencoba!

BPM HumanTask - Reuse TaskFlow Form

Pada blog kali ini saya membagikan tips bagaimana me-reuse ui task form yang sama di bpm. Pertama - tama pastikan payload antara human task sama.

  1. Buka human task , pilih tab source
  2. Copy targetNamespace. 
  3. Lalu buka UI project, yang ada di dalam application source, buka hwtaskflow.xml

    <hwTaskFlow>
    <WorkflowName>HumanTask1</WorkflowName>
    <TaskDefinitionNamespace>http://xmlns.oracle.com/sample/HumanTask1</TaskDefinitionNamespace>
    <TaskFlowId>HumanTask1_TaskFlow</TaskFlowId>
    <TaskFlowFileName>WEB-INF/taskFlows/HumanTask1_TaskFlow.xml</TaskFlowFileName>
    </hwTaskFlow>
    
  4. Ganti <WorkflowName> dan <TaskDefinitionNamespace> value dengan humantask2 WorkflowName dan Namespace. 

    <hwTaskFlow>
    <WorkflowName>HumanTask1</WorkflowName>
    <TaskDefinitionNamespace>http://xmlns.oracle.com/sample/HumanTask1</TaskDefinitionNamespace>
    <TaskFlowId>HumanTask1_TaskFlow</TaskFlowId>
    <TaskFlowFileName>WEB-INF/taskFlows/HumanTask1_TaskFlow.xml</TaskFlowFileName>
    </hwTaskFlow>
    <hwTaskFlow>
    <WorkflowName>HumanTask2</WorkflowName>
    <TaskDefinitionNamespace>http://xmlns.oracle.com/sample/HumanTask2</TaskDefinitionNamespace>
    <TaskFlowId>HumanTask1_TaskFlow</TaskFlowId>
    <TaskFlowFileName>WEB-INF/taskFlows/HumanTask1_TaskFlow.xml</TaskFlowFileName>
    </hwTaskFlow>



Sekian blog dari saya. TerimaKasih........

Customize bahasa di webcenter spaces

Blog kali ini saya akan membahas bagaimana menambah/customize bahasa di webcenter spaces.

Sebelom memulai :
Overview :

Langkah 1 buka sample project dengan jdeveloper,buka project LanguageAdditions . Dapat dilihat gambar di bawah terdapat java resource bundle class yang bernama WebCenterResourceBundle_ca. Dengan kelas tersebut kalian bisa menambahkan bahasa baru "ca" tersebut merupakan id untuk sebuah bahasa (Catalan). Jika kalian ingin mengubah bahasa inggris tinggal mengganti "ca" menjadi "en".

Langkah 2 buka file supported-language dan tambahkan jika kalian menggunakan bahasa baru yg tidak di dukung webcenter spaces


Langkah 3 buka file config.properties. 

Langkah 4 klik clean-stage, lalu klik deploy-shared-lib

Langkah 5 untuk membuat bahasa barua tersedia di spaces application, tambah "Catalan" <language> tag untuk supported-languages.xml
  • buka Weblogic Scripting Tool (WLST) di WC_ORACLE_HOME/common/bin
  • gunakan command WLST exportMetadata untuk download supported-languages.xml dari MDS.   ExportMetadata(application='webcenter',server='WC_Spaces',toLocation='/tmp/myMDSfiles',docs='/oracle/webcenter/webcenterapp/metadata/supported-languages.xml') 
  • Lalu edit file dan tambahkan : <language name=" Catalan" id="ca" used="true" activeicon="nlse_a.gif" inactiveicon="nlse.gif" translated="true"/>
     
  • Dan langkah terakhir gunakan WLST command importMetadata.
     importMetadata(application='webcenter', server='WC_Spaces', fromLocation='/tmp/myMDSfiles',docs='/oracle/webcenter/webcenterapp/metadata/supported- languages.xml')


Langkah 6  - editing shared library list (weblogic.xml). Untuk lebih detail klik link ini.


Langkah Terkahir login ke Spaces Application ke menu administration -> ganti default language 


Klik disini untuk language pack spaces
Sekian blog singkat saya :D 







RESTful Service with Spring Roo

Sebelum, kami membahas cara membuat aplikasi CRUD (Create, Read, Update and Delete) sederhana berdasarkan Class Diagram berikut :









Dari aplikasi tersebut, kami akan menambahkan RESTful Service dengan JSON format sebagai nilai pengembaliannya.

Caranya begitu mudah, yaitu :

  1. Lakukan langkah 1 hingga 15 pada blog sebelumnya.
  2. Ketik json all pada bagian Roo Shell.
  3. Ketik web mvc json all pada bagian Roo Shell.
  4. Jalankan dengan maven parameter -e clean tomcat:run
Untuk testing bisa menggunakan Poster (add-on pada firefox atau google chrome browser). Untuk lebih detail, bisa kita lihat demonya disini.

Sekali lagi kita disajikan kemudahan pembuatan RESTful Service dengan menggunakan Spring Roo.

Enjoy.

Rapid Application Development with Spring Roo

Di dalam proses pembuatan software, sering kali kita mendengar RAD. RAD adalah Rapid Application Development, metodology pengembangan perangkat lunak yang menggunakan template prototyping. Dengan adanya template prototyping yang di buat oleh framework, akan mempercepat (Rapid) proses development. Dari itu semua, yang terpenting adalah mudah untuk di modifikasi yang disesuaikan dengan kebutuhan developer.

Banyak sekali framework RAD yang ada di pasaran. Salah satunya adalah Spring Roo. Spring Roo adalah salah satu web framework yang di buat dengan bahasa pemrograman java. Spring Roo dinaungi oleh Spring.

Kenapa harus Spring Roo, karena :
  1. Mempercepat produktifitas.
  2. Standart Java API.
  3. Mudah digunakankan.

Untuk lebih mengenal Spring Roo, mari kita membuat aplikasi sederhana berdasarkan Class Diagram berikut :









Dari Class Employee ini kita membuat CRUD Operation menggunakan Spring Roo.

Sebelumnya pastikan kita sudah menginstall Spring Roo. Jika belum terinstall lakukan langkah berikut :

  1. Download Spring Tool Suite (STS) disini
  2. Jalankan STS-nya
  3. Pilih Help - Marketplace
  4. Tulis Roo pada di bagian Find
  5. Klik Install untuk menambahkan add-on Spring Roo
  6. Klik confirm
  7. Pilih I accept untuk melanjutkan proses instalasi.
  8. Klik Finish dan tunggu hingga proses instalasi selesai









Selanjutkan kita akan membuat aplikasi dengan Spring Roo. Ikuti langkah-nya sebagai berikut :
  1. Buka STS aplikasi.
  2. Klik File - New
  3. Pada bagian Wizards, tulis roo lalu tekan Enter
  4. Project Name: Employee
  5. Top level package name: com.demo
  6. Klik tombol Next lalu klik tombol Finish
  7. Ketik jpa setup --database MYSQL --provider HIBERNATE pada bagian Roo Shell
  8. Untuk setting database, bisa kita lakukan di database.properties yang terletak di Employee/src/main/resources/META-INF/spring
  9. Ketik entity jpa --class ~.domain.Employee --testAutomatically pada bagian Roo Shell
  10. Ketik field string --fieldName firstName --notNull --sizeMax 20 pada bagian Roo Shell
  11. Ketik field string --fieldName lastName --notNull --sizeMax 20 pada bagian Roo Shell
  12. Ketik field string --fieldName email --notNull pada bagian Roo Shell
  13. Ketik field date --fieldName joinDate --type java.util.Date --dateFormat SHORT pada bagian Roo Shell
  14. Ketik web mvc setup pada bagian Roo Shell
  15. Ketik web mvc all --package ~.controller pada bagian Roo Shell
  16. Jalankan dengan maven dengan parameter -e clean tomcat:run
Layar Utama

Menambah Data Employee

Daftar dari semua data Employee

Lihat, begitu mudahnya kita membuat aplikasi CRUD (Cread, Read, Update and Delete) dengan menggunakan Spring Roo. Cukup dengan membuat :

  1. Domain/Model
  2. Controller

Sisanya di tangani oleh Spring Roo.

Itulah sekilas info tentang Spring Roo dan untuk blog kami selanjutkan masih dengan Spring Roo yang berkaitan dengan pembuatan RESTfull Service dari aplikasi diatas. 

Enjoy

ADF table multiple selection tanpa business component

Ada kalanya saat menggunakan ADF, kita mem-bind suatu table tidak melalui business component, misalnya data tersebut tidak berasal dari database, bisa jadi hasil dari suatu kalkulasi di engine tertentu dan resultnya berupa list, atau bisa juga data didapat dari invokasi service (soap/rest).

Melalui artikel ini saya ingin berbagi trik yang saya lakukan untuk melakukan multiple selection di adf table yang bindingnya tidak melalui business component, tetapi di-binding ke Object List yang ada di backing bean atau managed bean.

Kita tambahkan property boolean pada Object yang digunakan:
 public class AnObject{  
   private int id;  
   private String code;  
   private String description;  
   private boolean selected; // <- add this boolean property  
   //setter getter  
 }  

dan kita tambahkan checkbox di kolom table:
 <af:commandButton text="Print Selected" action="#{TestPageBacking.printSelected}"/>  
 <af:table var="row" rowBandingInterval="0"  
      value="#{TestPageBacking.listObject}"  
      styleClass="AFStretchWidth"  
      columnStretching="last">  
   <!-- add this checkbox column -->  
   <af:column sortable="false" headerText="" width="20">  
     <af:selectBooleanCheckbox value="#{row.selected}"/>  
   </af:column>  
   <af:column sortable="false" headerText="id" width="200">  
     <af:outputText value="#{row.id}"/>  
   </af:column>  
   <af:column sortable="false" headerText="code">  
     <af:outputText value="#{row.code}"/>  
   </af:column>  
   <af:column sortable="false" headerText="description">  
     <af:outputText value="#{row.description}"/>  
   </af:column>  
 </af:table>  

di backing bean (TestPageBacking), di method printSelected dibuat checker utk object yang selected:
 private List<AnObject> listObject;  
 public void printSelected(){  
  System.out.println("selected objects:");  
  for(int i=0; i<listObject.size();i++){  
   if(listObject.get(i).isSelected()){  
    AnObject ao = listObject.get(i);  
    System.out.println("- "+ao.getId()+", "+ao.getCode()+", "+ao.getDescription());  
   }  
  }  
 }  
 //setter getter listObject   

contoh tampilannya:

bila di-klik button Print Selected, maka akan terlihat di log:
 selected objects:  
 - 1, satu, object pertama  
 - 3, tiga, object ketiga  

Semoga berguna.

Simplified Node Manager Setup


Peran Node Manager terhadap WebLogic domain sangat penting. Beberapa fungsinya telah saya sampaikan juga pada artikel saya sebelumnya mengenai WebLogic Whole Server Migration. Setelah beberapa kali melakukan konfigurasi WebLogic domain secara lengkap dan terinspirasi dari 2 artikel dari Middleware Magic (di sini dan di sini), saya mengompilasi cara yang sederhana dan dinamis untuk mempersiapkan Node Manager. Dengan menjalankan prosedur berikut, kita dapat menjalankan proses AdminServer tanpa menggunakan perintah nohup. ;) Prosedurnya dapat dibagi menjadi 2 prosedur utama, yaitu persiapan Node Manager dan asosiasikan Node Manager dengan WebLogic Domain.


Persiapan Node Manager


Node Manager secara default letaknya menyatu dengan letak instalasi WebLogic. Untuk menyederhanakan administrasi dan operasional, kita akan memisahkan letak Node Manager home. Selain itu kita juga akan mempersiapkan file-file tambahan yang dibutuhkan Node Manager. Berikut adalah langkah-langkahnya:
  1. Buat Node Manager home (NODEMGR_HOME) baru di luar instalasi WebLogic (MW_HOME).
  2. Copy 2 Shell script setWLSEnv.sh dan startNodeManager.sh dari lokasi instalasi WebLogic  Server (MW_HOME/wlserver_10.3/server/bin) ke Node Manager home.
  3. Edit script startNodeManager.sh, sesuaikan variabel NODEMGR_HOME dengan lokasi Node Manager home yang baru pada langkah 1. Saya biasanya menggunakan lokasi /u02/app/oracle/admin/nodemanager sebagai NODEMGR_HOME.
    ...
    NODEMGR_HOME="/u02/app/oracle/admin/nodemanager"
    ...
    
  4. Buat file nodemanager.domains di dalam NODEMGR_HOME yang berisi  pasangan nama WebLogic domain dengan lokasi domain-nya di filesystem, contohnya seperti berikut ini:
    # DOMAIN_NAME=DOMAIN_HOME
    Access_Domain=/u01/app/oracle/admin/Access_Domain/aserver/Access_Domain
    
  5. Buat file nodemanager.properties di dalam NODEMGR_HOME yang berisi property-property yang diperlukan untuk menjalankan Node Manager. File property tersebut bisa juga di-copy dari lokasi default-nya jika sudah tersedia. Bagian terakhir dari file properties diberi tanda comment (#), kecuali jika kita perlu mengkonfigurasi fitur WebLogic Server Migration.
    # Minimal Node Manager properties
    DomainsFile=/u02/app/oracle/admin/nodemanager/nodemanager.domains
    LogLimit=0
    PropertiesVersion=10.3
    DomainsDirRemoteSharingEnabled=false
    javaHome=/u01/app/oracle/product/fmw/jrockit-jdk1.6.0
    AuthenticationEnabled=true
    NodeManagerHome=/u02/app/oracle/admin/nodemanager
    JavaHome=/u01/app/oracle/product/fmw/jrockit-jdk1.6.0/jre
    LogLevel=INFO
    DomainsFileEnabled=true
    StartScriptName=startWebLogic.sh
    ListenAddress=
    NativeVersionEnabled=true
    ListenPort=5556
    LogToStderr=true
    SecureListener=true
    LogCount=1
    DomainRegistrationEnabled=true
    StopScriptEnabled=false
    QuitEnabled=false
    LogAppend=true
    StateCheckInterval=500
    CrashRecoveryEnabled=false
    StartScriptEnabled=true
    LogFile=/u02/app/oracle/admin/nodemanager/nodemanager.log
    LogFormatter=weblogic.nodemanager.server.LogFormatter
    ListenBacklog=50
    
    # WebLogic Server Migration
    #Interface=eth0
    #NetMask=255.255.255.0
    #UseMACBroadcast=true
    
  6. Buat script Python NodeManager.py di dalam NODEMGR_HOME yang isinya adalah script WSLT untuk menjalankan proses Node Manager.
    # Start Node Manager
    startNodeManager()
    
  7. Buat script Python AdminServer.py di dalam NODEMGR_HOME yang isinya adalah script WLST untuk connect dengan proses Node Manager dan menjalankan proses WebLogic AdminServer.
    # Import necessary libraries
    from java.io import FileInputStream
    import java.lang
    import os
    import string
    
    # Load WebLogic Domain properties file
    propInputStream = FileInputStream("AdminServer.properties")
    configProps = Properties()
    configProps.load(propInputStream)
    
    # Connect to Node Manager
    userConfigFile = configProps.get("nm.config")
    userKeyFile = configProps.get("nm.key")
    host = configProps.get("nm.host")
    port = configProps.get("nm.port")
    nmType = configProps.get("nm.type")
    domainName = configProps.get("domain.name")
    domainDir = configProps.get("domain.dir")
    nmConnect(userConfigFile=userConfigFile, userKeyFile=userKeyFile, host=host, port=port, domainName=domainName, domainDir=domainDir, nmType=nmType)
    
    # Start WebLogic Server instance
    serverName = configProps.get("server.name")
    nmStart(serverName)
    
  8. Persiapkan file properties AdminServer.properties yang akan dibaca oleh script AdminServer.py untuk menjalankan AdminServer.
    # Node Manager connection info
    nm.config=/u02/app/oracle/admin/nodemanager/security/NodeManagerConfig.properties
    nm.key=/u02/app/oracle/admin/nodemanager/security/NodeManagerKey.secure
    nm.host=localhost
    nm.port=5556
    nm.type=ssl
    
    # WebLogic Domain info
    domain.name= Access_Domain
    domain.dir=/u01/app/oracle/admin/Access_Domain/aserver/Access_Domain
    
    # WebLogic instance name
    server.name=AdminServer
    
  9. Jalankan proses Node Manager dan pastikan tidak ada error yang terjadi di log output-nya.
    oracle@dev.nostratech.com:~ $ cd /u02/app/oracle/admin/nodemanager
    oracle@dev.nostratech.com:/u02/app/oracle/admin/nodemanager $ . ./setWLSEnvh.sh
    oracle@dev.nostratech.com:/u02/app/oracle/admin/nodemanager $ java weblogic.WLST NodeManager.py


Asosiasi Node Manager dengan WebLogic Domain


Ketika melakukan konfigurasi sebuah WebLogic Domain, Node Manager juga akan terkonfigurasi secara otomatis. Namun karena pada bagian sebelumnya konfigurasi Node Manager dipisahkan dari WebLogic Domain, maka kita harus mengkonfigurasi username dan password Node Manager untuk terhubung ke WebLogic Domain. Lakukan langkah-langkah berikut:
  1. Login ke Oracle WebLogic Administration Console.
  2. Pilih $NAMA_DOMAIN -> Security -> Advanced. Ubah Node Manager username dan password pada halaman tersebut. Simpan perubahan dengan memilih Save.
    Setup Node Manager Credential
  3. Login ke AdminServer melalui WLST, kemudian asosiasikan dengan Node Manager.
    wls:/offline> connect('weblogic', 'secret', 't3://accessadminvhn.nostratech.com:7001')
    wls:/Access_Domain/serverConfig> nmEnroll('/u01/app/oracle/admin/Access_Domain/aserver/Access_Domain')
  4. Buat sebuah Machine yang merupakan representasi dari Node Manager tersebut.
    Konfigurasi Machine OAMHOST1
  5. Test status Node Manager melalui WebLogic Administration Console dengan memilih Environment -> Machines -> $MACHINENAME -> Monitoring -> Node Manager Setup.
    Reachable Node Manager
  6. Generate Node Manager credential dalam bentuk yang terenkripsi melalui WLST, sesuaikan lokasi direktori dengan yang tertera pada file AdminServer.properties.
    wls:/offline> nmConnect('nodemanager', 'secret', 'localhost', '5556', 'Access_Domain', '/u01/app/oracle/admin/Access_Domain/aserver/Access_Domain', 'ssl')
    wls:/nm/Access_Domain> storeUserConfig('/u02/app/oracle/admin/nodemanager/security/NodeManagerConfig.properties', '/u02/app/oracle/admin/nodemanager/security/NodeManagerKey.secure', 'true')

Menjalankan AdminServer melalui Node Manager


Semua konfigurasi yang diperlukan sudah selesai, sekarang saatnya untuk menguji coba konfigurasi kita. Pastikan semua proses Java kita akhiri terlebih dahulu. Untuk menjalankan AdminServer, lakukan langkah berikut:
  1. Setup environment variable yang diperlukan.
    oracle@dev.nostratech.com:~ $ export JAVA_OPTIONS="-DDomainRegistrationEnabled=true"
  2. Jalankan Node Manager sebagai daemon.
    oracle@dev.nostratech.com:~ $ cd /u02/app/oracle/admin/nodemanager
    oracle@dev.nostratech.com:/u02/app/oracle/admin/nodemanager $ java weblogic.WLST NodeManager.py
  3. Jalankan AdminServer via Node Manager.
    oracle@dev.nostratech.com:/u02/app/oracle/admin/nodemanager $ java weblogic.WLST AdminServer.py

Biarkan perintah tersebut berjalan, dan jika tidak ada error seharusnya AdminServer sudah berjalan secara daemon. Sekian pembahasan untuk kali ini, jika ada isu dalam menjalankan langkah-langkah tersebut, silahkan tinggalkan komentar Anda.

Semoga bermanfaat! :)