Tuesday, 6 December 2016

Customize jquery datepicker and its integration in ADF

ADF has a component <af: inputDate>, which is used to insert a date to the java.util.Date object. When you click on the calendar thumbnail, following popup calendar appears (styled).
The mechanism is simple, but it has one major drawback - the popup is opening up to 1 second which is quite long for end users.

I decided to change the component and use jquery datepicker, which opens instantly. In addition, it has an additional advantage: it has easy editor for customizing the calendar. On page:
https://jqueryui.com/themeroller/ we can generate template and save its jquery + CSS + images package. The structure is as follows:
We can use generated  packet in the ADF application . To do this, move the folder to the application:

I replace a component <af: inputDate> to <af: inputText> adding clisentListener and convertDateTime:


<!--<af:inputDate value="#{pageFlowScope.mb1.startDateFrom}"
    >
 <af:clientAttribute name="preventNoteWindow" value="true"/>
 <af:convertDateTime pattern="dd-MM-yyyy"/>
</af:inputDate>-->
<af:inputText value="#{pageFlowScope.mb1.startDateFrom}" autoSubmit="true"  id="it10" >
 <af:clientListener method="ksed.pickdate" type="mouseOver" />
 <af:convertDateTime pattern="dd-MM-yyyy"/>
</af:inputText>


Of course, we must add jquery and css files for configuration. PortalBundle file (the path must be compatible with the imported project):


global.resources.js.jQuery.path=/js/jquery-1.11.1.min.js
global.resources.js.jQueryui.path=/js/datepicker/jquery-ui.js
global.resources.js.jQuery.css.path=/js/datepicker/jquery-ui.css

Add to the view:


  <af:resource type="javascript" source="${portalBundle['global.resources.js.jQuery.path']}"/> 
  <af:resource type="css" source="${portalBundle['global.resources.js.jQuery.css.path']}"/>
 <af:resource type="javascript" source="${portalBundle['global.resources.js.jQueryui.path']}"/>

And now you can use the datepicker in the functions js:


ksed.pickdate = function(ev){     
    try {
            var id = ev.getSource().getClientId();
            jQuery('input[name="'+id+'"]').datepicker({
            dateFormat: "dd-mm-yy",
            monthNames : [ "Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień" ],
            firstDay: 1,
            dayNamesMin: ['N', 'PN', 'WT', 'ŚR', 'CZ', 'PT', 'SO']
        });
                
    }
    catch(err) {
        tpl.log(err);
    } 
     
};

If all goes well, after that when you click in the box, calendar should appear :



Monday, 5 December 2016

SSL in Integrated Weblogic with Jdeveloper

I had some problems with the setting SSL Weblogic integrated with Jdeveloper on localhost. To enable SSL I had to:
Log on to the administration console and enable SSL for Weblogic. Click Environment -> Servers -> DefaultServer (or another server name). Set to 'SSL Listen Port Enabled "and set the port for SSL (eg. 7002):


Then in JDeveloper go to the "Applications Servers", right click on the "IntegratedWeblogicServer" properties and in the tab "Configuration" set the same port number in the SSL port and mark the checkbox "Always use SSL."
But when you restart your WebLogic and you type "https://localhost:7002/console will you could see:


When I run the server with parameters: -Dweblogic.Stdout Debug Enabled = true -Dssl.debug = true -Djavax.net.debug = ssl
in logs appears:


<2016-12-05 17:02:49 CET> <Debug> <SecuritySSL> <BEA-000000> <write ALERT, offset = 0, length = 2> 
<2016-12-05 17:02:49 CET> <Debug> <SecuritySSL> <BEA-000000> <HANDSHAKEMESSAGE: ClientHello> 
<2016-12-05 17:02:49 CET> <Debug> <SecuritySSL> <BEA-000000> <close(): 29237695> 
<2016-12-05 17:02:49 CET> <Debug> <SecuritySSL> <BEA-000000> <close(): 29237695> 
<2016-12-05 17:02:49 CET> <Debug> <SecuritySSL> <BEA-000000> <SSLIOContextTable.removeContext(ctx): 3075174> 
<2016-12-05 17:02:49 CET> <Debug> <SecuritySSL> <BEA-000000> <NEW ALERT with Severity: FATAL, Type: 40
java.lang.Exception: New alert stack
 at com.certicom.tls.record.alert.Alert.<init>(Unknown Source)
 at com.certicom.tls.record.handshake.HandshakeHandler.handleHandshakeMessages(Unknown Source)
 at com.certicom.tls.record.MessageInterpreter.interpretContent(Unknown Source)
 at com.certicom.tls.record.MessageInterpreter.decryptMessage(Unknown Source)
 at com.certicom.tls.record.ReadHandler.processRecord(Unknown Source)
 at com.certicom.tls.record.ReadHandler.readRecord(Unknown Source)
 at com.certicom.tls.record.ReadHandler.readUntilHandshakeComplete(Unknown Source)
 at com.certicom.tls.interfaceimpl.TLSConnectionImpl.completeHandshake(Unknown Source)
 at javax.net.ssl.impl.SSLSocketImpl.startHandshake(Unknown Source)
 at weblogic.server.channels.DynamicSSLListenThread$1.run(DynamicSSLListenThread.java:130)
 at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
 at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)


What tells us, that ssl handshake does not work properly. To correct this, you must enter the console:
  Environment -> Servers -> DefaultServer (or another name). -> ssl -> advanced and select "use JSSE SSL"




 With restart the server and entering: https://localhost:7002/console console now should appear

Deleting highlighted position from


In the last week I had the task to delete selected items from the component <af: selectManyShuttle>, which are e-mail addresses of users:


In this case, I would like to have removed the addresses 3Email@gmail.com and 4Email@gmail.com. Of course, other values of the list must be unchanged.
I have not found any listeners for component <af: selectManyShuttle>, which I could use so I used a little workaround.


File scheduler.jspx:

1
2
3
4
5
6
7
8
9
<af:selectManyShuttle autoSubmit="true"  leadingHeader=" " trailingHeader=" "  id="sms2"  value="#{pageFlowScope.harmonogramManagementMB.selectedMailsList}">
 <f:selectItems value="#{pageFlowScope.harmonogramManagementMB.allMailsListSI}" id="shjki6a"/>
 <af:clientAttribute name="preventNoteWindow" value="true"/>
</af:selectManyShuttle>

<af:commandButton text="DELETE HIGHLIGHTES USERS" id="cb22" rendered="#{!pageFlowScope.
harmonogramManagementMB.addingMailRecipient}">
 <af:clientListener method=" ksed.deleteHighligtedUser" type="action"/>
 <af:serverListener type="deleteSelectedEmails" method="#{pageFlowScope.harmonogramManagementMB.deleteEmails}"/>
</af:commandButton>

The "DELETE highlightes USERS" calls the js function ksed.deleteHighligtedUser, which extracts a list of selected emails and calls serverListener that performs the method deleteEmails:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
ksed.deleteHighligtedUser = function(ev){
    try {
        var selectedEmails = jQuery('.af_selectManyShuttle_item.p_AFSelected '); 
        var emails = [];
       
        for(var i=0; i<selectedEmails.length; i++) {
            emails.push(selectedEmails[i].innerText);
        }
        AdfCustomEvent.queue(ev.getSource(), "deleteSelectedEmails", {"emails":emails}, true);

    }
    catch(err) {
        tpl.log(err);
    } 
}


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    public String deleteEmails(ClientEvent event) {
        List<String> emailsList =(List<String>)event.getParameters().get("emails");
        if(emailsList!=null && emailsList.size()>0){
        //DELETING EMAILS FROM DB
            onRemoveMailRecipientButton(emailsList);
        }
        return null;
    }

Of course, we also need to manually delete selected values:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
                Iterator<SelectItem> it = allMailsListSI.iterator();
                while(it.hasNext()){
                    SelectItem nextValue = it.next();
                    emails.contains(nextValue);
                }              
                Iterator<String> it1 = selectedMailsList.iterator();
                while(it1.hasNext()){
                    String nextValue = it1.next();
                    emails.contains(nextValue);
                }
                

But it is not everything. During the execution of these methods I encountered two problems. Firstly, after returning to the view displays some adf validation issue:





We can delete it after the creation ControllerClass for the view. In pageDefinition we add:

1
2
3
4
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
                 version="11.1.1.64.93" id="adminPanelPageDef"
          ControllerClass="pl.energa.portal.src.view.controllers.HarmonogramController"
                 Package="oracle.webcenter.portalapp.pages.adminPanel">

And the we create the Controller:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class HarmonogramController implements PagePhaseListener  {
    public HarmonogramController() {
        super();
    }

    public void afterPhase(PagePhaseEvent pagePhaseEvent) {
    }

    public void beforePhase(PagePhaseEvent pagePhaseEvent) {
        FacesContext ctx = FacesContext.getCurrentInstance();
        Iterator<FacesMessage> it = ctx.getMessages();
        if(it!=null){
            while(it.hasNext()){
                FacesMessage fm = it.next();
                LoggerHelper.logInfo(fm.getDetail());
                System.out.println(fm.getDetail());
                if("Enter a value that matches this pattern: {2}".equalsIgnoreCase(fm.getDetail())){
                    it.remove();
                }
            }
        }
    }
}

Of course, when changing localization will change the name of the statement, so hardcodding here is not recommended.
 The second problem is that, if removed element is not the last element in the list of selected items.
the next element of the left window jumps to a selection on the right which is wrong. To correct this, we can set a flag in method deleteEmails, which prevents in setter set bad values:


1
2
3
4
5
6
7
    public void setSelectedMailsList(List<String> selectedMailsList) {
        if(deleteUser){
            deleteUser = false;
            return;
        }
        this.selectedMailsList = selectedMailsList;
    }