Reklamlar

Jsf 2.0 ile Custom Component OlustrumaJsf 2.0 ile Custom Component Olustruma

Jsf 2.0 ile Custom Component OlustrumaJsf 2.0 ile Custom Component Olustruma

Blogdaki ilk yazimdan herkese Merhaba...

Makalemizde Jsf 2.0 ile custom component`lerin nasil olusturuldugu orneklerle beraber uygulamali olarak paylasmaya calisacam. Jsf `in 2.0`dan onceki surumlerinde de custom component olusturabiliyorduk ancak JSF2 ve facelets ile birlikte bu konu cok daha rahat bi sekilde hazirlanabiliyor. Bi sonraki yazimda, jsf2 ile gelen ozelliklerinden ve jsf2 ile eski surumlerin karsilastirilmasindan bahsedecem.

Simdi konumuza donersek, custom componentleri hangi durumlarda olusturuz, neden bole biseye ihtiyac duyariz derseniz, jsf`nin kendi componentlerinin yeterli olmadigi durumlarda, uygulamalarimiz icin kendi componentlerimizi olustururuz mesala bi ornek vermek gerekirse, h:datatable componentinde h:selectOneRadio componenti kullandigimizda cogumuz karsilasmisizdir, birden fazla satir secilebiliyor, ama radio butonlarin ozellikleri grub halinde calismalari ve o grub icinde yanliz birtane secilebilir olmalaridir. Ancak jsf componentinde birden fazla satir secebiliyoruz ve buda bizim hic istemedigimiz bir sonuc ortaya koyuyor, iste tam burada custom componentler yardimimiza kosuyor, ve biz kendi radio buton componentimizi istedigimiz sekilde olusturabiliyoruz. Bu sorunu 3.parti framevorklar kullanarak cozebiliyoruz ancak, onlarda sayfaya fazla bisekilde javascript-ajax atiyorlar. Bizim kendi olusturdugumuzu componentde ise hic bisekilde javascritpte yada ajax`a ihtiyacimiz olmayacak, Konuyu uzatmadan isterseniz hemen, nasil kendi componentlerimizi olusturabiliriz onan bakalim.

Ben uygulamarimda,

 NetBeans 6.8 - glassfishv3 - j2ee 6 - jsf 2.0 ve facelets kullandim.

Simdi componentimizi olusturmaya baslayalim.

Bize gerekli olan classlar, SingleRowSelect, SingleRowSelectRenderer, RadioGroup, RadioGroupRenderer,

Simdi bu classlar ne isimize yarayacak,

SingleRowSelect classi bizim componentimizin propertylerinin olacagi class, bi nevi hangi attributelerinin olacagini burada gosteriyoruz, biz burada butun attributeleri tek tek olusturmakdansa var olanin uzerine bize gereken attributeleri ekleyelim, bunun icinde yanliz groupId attributemiz olsa bizim icin yeterli olacak. Classin icersi asagidaki gibi..

 

package net.aslan.faces.radiobutton;

import javax.faces.component.FacesComponent;

 

@FacesComponent(value = SingleRowSelect.COMPONENT_TYPE)
public class SingleRowSelect extends javax.faces.component.UIInput {

    public static final String COMPONENT_FAMILY = "net.aslan.faces.component";
    public static final String COMPONENT_TYPE = "net.aslan.faces.component.radiobutton.SingleRowSelect";
    public static final String RENDERER_TYPE = "net.aslan.faces.component.radiobutton.SingleRowSelectRenderer";

    public SingleRowSelect() {
        super();
        setRendererType(RENDERER_TYPE);
    }

    @Override
    public String getFamily() {
        return COMPONENT_FAMILY;
    }

    public void setGroupId(String groupId) {
        getStateHelper().put("groupId", groupId);
    }

    public String getGroupId() {
        return (String) getStateHelper().get("groupId");
    }
}

 

Yukarida dikkat edecek olursak, classimizi UInput`dan extends ettik, cunku ayni seyleri tekrardan yazmakdansa bize gerekli olani var olani kullanarak onun uzerine eklemek daha rahat ve kolay olacaktir. UInput classinin icerisini incelemek bize cok fayada saglayacaktir.

Simdi yukaridaki classdaki kodlarin neler yaptigindan biraz bahsedecek olursak,

@FacesComponent, bu ozellikle jsf2 ile birlikte gelen annotationlar ile classin neyapacaginin neturden bi class olduguna karar veriyoruz,

ve classimizi component olarak gosteriyoruz, value` degeri ise componentin bir butun olarak calisacagindan Component_Family belirtiyoruz,

 public static final String COMPONENT_FAMILY = "net.aslan.faces.component";
public static final String COMPONENT_TYPE = "net.aslan.faces.component.radiobutton.SingleRowSelect";

 

kodlarimiz UInput classinin icindede var oldugunda biz bu propertyleri ovveride ediyoruz ve kendi component type`mizi ve family`ini gosteriyoruz, biz ovveride etmeseydik kendisi tanyacakti ama biz ona izin vermiyoruz (UIInput classinin icini incelemenizi tavsiye ederim.)

 

 public SingleRowSelect() {
        super();
        setRendererType(RENDERER_TYPE);
    }

 

burada ise yapilandiricimizda renderer olacagi classimi set ediyoruz, eger biz set etmesek kendi renderer classini kullanacaktir.

ve son olarak

  public void setGroupId(String groupId) {
        getStateHelper().put("groupId", groupId);
    }

    public String getGroupId() {
        return (String) getStateHelper().get("groupId");
    }

 

bizim icin gerekli olan attribute`i olusturuyoruz ve stateHelper ekliyoruz, stateHelper Map seklinde calisiyor, setGroupId`de map`a ekliyoruz ve istegimiz zaman getGroupId`de oldugu gibi cagirabiliyoru, StateHelper`i ilerki makalelerde UIInput incelerken gorecegiz.

 

Bundan sonra bizim icin gerekli olan ve en onemli kisimlardan birisi renderer clasimizi olusturmak. Yani componentimizin nasil davranacagini bu class yardimiyla belirtecegiz..

 

import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;

@FacesRenderer(componentFamily = SingleRowSelect.COMPONENT_FAMILY, rendererType = SingleRowSelect.RENDERER_TYPE)
public class SingleRowSelectRenderer extends javax.faces.render.Renderer {

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        SingleRowSelect radio = (SingleRowSelect) component;
        String clientId = component.getClientId();
        String groupId = radio.getGroupId();
        Object selectedItems = null;
        RadioButtonGroup group = null;

        if (groupId != null) {
            group = (RadioButtonGroup) findComponent(radio, groupId);
            if (group != null) {
                selectedItems = group.getValue();
            } else {
            }
        }

        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("input", component);
        writer.writeAttribute("type", "radio", null);
        writer.writeAttribute("id", clientId, null);

        if (group != null) {
            writer.writeAttribute("name", group.getClientId(), null);
        } else {
            writer.writeAttribute("name", clientId, null);
        }
        writer.writeAttribute("value", radio.getValue(), "value");

        if (selectedItems != null) {
            System.out.println("type is:" + radio.getValue().getClass().getName() + " / value:" + radio.getValue());
        }
        writer.endElement("input");
    }

    private UIComponent findComponent(UIComponent comp, String componentId) {
        UIComponent parent = comp;
        UIComponent found = null;
        int i = 1;
        while (parent != null) {
            found = parent.findComponent(componentId);
            if (found != null) {
                return found;
            }
            parent = parent.getParent();
        }
        return null;
    }
}

yukaridaki kod blogumuzu inceleyecek olursak,

@FacesRenderer ile classimizn renderer ozellikde davranacagini belirtiyoruz ve componentFamily ve rendererType`ni gosteriyoruz, ve classimizi Renderer`den extend ediyoruz, bize gerekli olan kisimlari ovveride edip gerekli degisiklikleri yaptiyoruz.

@Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {

Renderer classinin encodeEnd metodunu ovveride ettik cunku bizim icin componentimizin en son nasil davranacagini burada belirttik, metodu icinde kullandiklarimiza gelince.

SingleRowSelect radio = (SingleRowSelect) component

-burada componentimizi daha once olusturdugumuz SingleRowSelect custom component`i tipinde olusturduk. Burada kullandigimiz clientId componentimizin clientId`sini aldik, groupId ile`de bizim olusturdugumuz attribute`in degerin aldik. RadioGroup birazdan bizim olusturacagimiz class, bu classida component gibi olusturduk, cunku radiobutonlarimizdaki degerleri grub halinde kullanip radio butondaki degeri Object turunde almak icin.

ResponseWriter writer = context.getResponseWriter();
        writer.startElement("input", component);

 budan sonraki kisimlarda ise componentimizi hangi propetylerinin oldugunu degerlerin nasil alinacagini gosteriyoruz, bu bolumleri derinlemesi baska bi makalede paylasacagiz.

Ve RadioGroup ve RadioGroupRenderer clasinin yaziyoruz, bu bolumlerin uzerine fazla deyinmeden gececem, makaleyi cok fazla uzatmamak icin, sorusu olan arkadaslara formda yardimci olmaya calisirim.

 

=============

package net.aslan.faces.radiobutton;

 

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.render.FacesRenderer;

 

@FacesRenderer(componentFamily = RadioButtonGroup.COMPONENT_FAMILY, rendererType = RadioButtonGroup.RENDERER_TYPE)
public class RadioButtonGroupRenderer extends javax.faces.render.Renderer {

    public RadioButtonGroupRenderer() {
        super();       
    }

    @Override
    public void decode(FacesContext context, UIComponent component) {
      
        RadioButtonGroup group = (RadioButtonGroup) component;
        String clientId = group.getClientId(context);
        Object[] submittedValue = context.getExternalContext().getRequestParameterValuesMap().get(clientId);
        group.setSubmittedValue(submittedValue);
    }
}

====================

package net.aslan.faces.radiobutton;

 

import javax.faces.component.FacesComponent;
import javax.faces.component.UIInput;

 

@FacesComponent(value = RadioButtonGroup.COMPONENT_TYPE)
public class RadioButtonGroup extends UIInput {

    public static final String COMPONENT_FAMILY = "net.aslan.faces.component";
    public static final String COMPONENT_TYPE = "net.aslan.faces.component.radiobutton.RadioButtonGroup";
    public static final String RENDERER_TYPE = "net.aslan.faces.component.checkbox.RadioButtonGroupRenderer";

    public RadioButtonGroup() {
        super();
        setRendererType(RENDERER_TYPE);     
    }

    @Override
    public String getFamily() {
        return COMPONENT_FAMILY;
    }
}

 

Bizim icin gerekli olanlar classlar bukadar, bunda sonra yapmamiz gereken, componentimiz icin bi taglib olusturmak ve xml`de gostermek, daha sonrada kullanmak :).

 

Bunda sonra yapacaklarimiz cok kolay, oncelikle taglib`imizi olusturalim.

 

net-aslan-taglib.xml

 


 

sonra web.xml icerisinde gosterelim..

 

 

 

hepsi bukadar, simdide facelets page`imde kullanmaya basliyalim.

 

DataBean.java

 

import accr.beans.Person;
import accr.beans.PersonRemote;
import java.io.Serializable;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

 

@ManagedBean
@SessionScoped

public class DataBean implements Serializable {

    @EJB
    PersonRemote pr;
    private Person selectedPerson;
    Object selectedItem[];

    public List getPersons() {
        return pr.findAll();
    }

    public String actionEdit() {
        String id = (String) selectedItem[0];
        selectedPerson = pr.getPerson(new Long(id));
        System.out.println("Per : " + selectedPerson.getName());
        return "edit";
    }

    public Object[] getSelectedItem() {
        return selectedItem;
    }

    public void setSelectedItem(Object[] selectedItem) {
        System.out.println("Set edildi -----=== ");
        this.selectedItem = selectedItem;
    }

    public Person getSelectedPerson() {
        return selectedPerson;
    }

    public void setSelectedPerson(Person selectedPerson) {
        this.selectedPerson = selectedPerson;
    }
}

 

i

edit.xhtml       
        

   


       

   

 

Sonuc olarak..

 

index.xhtml 


 

 

edit.xhtml

 


uygulamanin tamamini, proje halinde dosyalar bolunde bulubilirsiniz.

Yorum ve dusuncelerinizi bekliyorum, Faydali olmasi dilegiyle.

Bir sonraki makaledeki, Jsf 2.0 ile gelen yeniliklerden bahsedecegim..

Degiserek gelismenin dilegilyle...

 

Ertugrul Aslan

R.I.S.K Company

Baku / Azerbaycan

 

Tartışma

Yorumlariminizi ve dusuncelerinizi bekliyorum, eksikligim, gozumden kacan yerler olduysa ve duzeltmeme yardim ederseniz cok sevinirim.
Ertugrul hocam emeginize saglik .. cok guzel ve ayrintili dokuman Tesekkurler
Ertgrul hocam gercektende jsf-2 de custom component ile ilgili turkce kaynak yoktu diger kaynaklarda bukadar acik net sekilde yazmamis emegine saglik makalelerinizin devami dilegi ile Hayirli gunler
Anlatım için teşekkürler.Resimler gözükmüyor.Resimler de çıkarsa çok iyi olacak.Emeğinize sağlık.



ya da
CAPTCHA Images