JDev and IE11 Patches are finally available for all ‘current’ versions

Aside

[UPDATE 2014-03-07] added correct patch number for JDev 11.1.2.4.0
————————————————————————————————-

Since February 25th 2014 the missing patch for JDev 12.1.2.0.0 to make ADF application work with IE11 has arrived. In OTN forum thread https://community.oracle.com/thread/2624119 you find the details of the delay.
The patch for 12.1.2.0.0 has Id 18091042
The patches for the other versions are mentioned in doc ID 1599898.1. The document itself is a bit outdated as the patch for JDev 12.1.2 is missing in the doc.
Here is the summary of the available patches:

    JDeveloper/ADF 11.1.1.6.0
    patch 18277457 – MERGE REQUEST ON TOP OF 11.1.1.6.0 FOR BUGS 17236592 18176711
    patch 17236592 – IE11 SUPPORT: ADF APPS DON’T LOAD WITH IE11 Superseded by patch 18277457
    JDeveloper/ADF 11.1.1.7.0
    patch 18277370 – MERGE REQUEST ON TOP OF 11.1.1.7.0 FOR BUGS 18071063 18176711
    patch 18071063 – MERGE REQUEST ON TOP OF 11.1.1.7.0 FOR BUGS 17236592 17672146 17723555 17723794 Superceded by patch 18277370
    patch 17236592 – IE11 SUPPORT: ADF APPS DON’T LOAD WITH IE11 Superceded by patch 18071063
    JDeveloper/ADF 11.1.2.3.0
    patch 18436342 – MERGE REQUEST ON TOP OF 11.1.2.3.0 FOR BUGS 17236592 17672146 17723555 17723794
    JDeveloper/ADF 11.1.2.4.0
    Patch 18277436: MERGE REQUEST ON TOP OF 11.1.2.4.0 FOR BUGS 18070879 18176711
    JDeveloper/ADF 12.1.2.0.0
    patch 18091042 – MERGE REQUEST ON TOP OF 12.1.2.0.0 FOR BUGS 17236592 17663878 17672146 17723555

JDeveloper 11.1.1.6.0: Self Closing Popup

Based on Frank’s (Frank Nimphius) article How to auto-dismiss af:popup dialogs and the sample 105, a user on OTN JDev & ADF forum tried to get this running on JDeveloper 11.1.1.6.0. Franks sample was built using JDeveloper 11.1.2.3.0 and can’t be run without changes in JDeveloper 11.1.1.6.0.
However, it’s easily possible to build a sample using 11.1.1.6.0 showing how to use the af:poll to close a popup using an af:noteWindow or an af:dialog inside the popup. The technique is described in Frank’s article, so I spare repeating it here.
Let’s look at the running application

Running Sample

Running Sample

Clicking on the link “Show Popup NW” or the button “Popup NW” shows the location of the department in a note window

Location in Note Window

Location in Note Window

Clicking on the link “Show Popup DW” or the button “Popup DW” shows the location of the department in a dialog window (modal)

Location in Dialog

Location in Dialog

You can download the sample, which is using the HR DB schema, from ADF EMG Samples Project

UPDATE 2013-03-25:
as it turned out there is a problem with the af:poll component and the timeout setting. This timeout setting should cancel the poll component after the given period of time (which should work in 11.1.2.3). This was one key feature in Frank’s original article. Using 11.1.1.6.0 it turned out, that hte af:poll remains active even after the timeout period should have canceled any further events to the poll listener.
I implemented a fix for this behavior. The popup uses a fetch listener which sets the interval (5000 ms in the sample) and the poll listener cancel the poll by setting the interval to -1 after hiding the popup.
The code is written in a generic way to allow handling of different popups. Please download the new sample from ADF EMG Samples Project

JDeveloper 11.1.1.6.0: Escape QBE Operators in Filterable Tables

You may not have noticed that some words like ‘and’ and ‘or’ do have a special meaning if you use them in a filterable af:table. If a column of a db table contains some text which you like to filter via the Query by Example (QBE) feature of the af:table, you’ll notice that you can’t filter for  ‘and’ and ‘or’. These words are used as SQL operands for character columns,  like  ‘>’ or ‘<‘. There is no property to escape these words do that they are treated as normal words. For a full list of QBE operands check the Table 27-2 Query-by-Example Search Criteria Operators.

In this post we learn how to implement such an escape mechanism. The sample work space, which used the HR DB schema, can be down loaded using the link provided at the end of the post.

The solution for the problem is implemented on the vo the table is based on. Surprisingly no change is needed in the view controller. We only need to overwrite one method on the ViewObjectImpl which is used to generate the where clause part out of the filter criteria.

Before we go into the details let’s look at the running application, the problem, and it’s solution.

Running Test Application

Running Test Application

To show the problem without the need to change to much in the HR db we use the FirstName and the LastName column of the employees table. Here we change one or more entries do that they contain the word ‘and’ and ‘or’. In the image the changed lines are EmployeeId 202 and 203.

Filter for 'Pat and John'

Filter for ‘Pat and John’

As you see in the image above you get no row if you enter e.g. ‘Pat and John’ into the filter column of the first name. The reason is that the QBE feature build two where clause parts out of the one filter value as down in the output below.

FINE: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: Employees.FIRST_NAME value: Pat%
INFO: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: Employees.FIRST_NAME value: Pat%
FINE: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: Employees.FIRST_NAME value: John%
INFO: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: Employees.FIRST_NAME value: John%
FINE: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: FirstName value: Pat%
INFO: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: FirstName value: Pat%
FINE: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: FirstName value: John%
INFO: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: FirstName value: John%

As mentioned before this is a feature and not a bug. However, the are use cases where we need to filter for the words which are treated as operands.
We use a trick to escape the operands. We surround the operands by ‘_’. Then they are not treated as special words any more but as normal text.

Filter for 'Pat_and_ John'

Filter for ‘Pat_and_ John’

To make it work we have to remove the ‘_’ in the ViewObject before the query is executed. The output from the method now looks like

 
FINE: 17.02.2013 16:07:22 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 11 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: Employees.FIRST_NAME value: Pat _and_ John
INFO: 17.02.2013 16:07:22 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 11 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: Employees.FIRST_NAME value: Pat and John
FINE: 17.02.2013 16:07:22 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 11 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: FirstName value: Pat _and_ John
INFO: 17.02.2013 16:07:22 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 11 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: FirstName value: Pat and John

For this we overwrite the ‘public String getCriteriaItemClause(ViewCriteriaItem vci)’ method in the ViewObjectImpl.

 
    /**
     * Build the where clause for the criteria item 
     * @param vci
     * @return null if we use hte default where clause, the where clause part if we want to change the default.
     */
    @Override
    public String getCriteriaItemClause(ViewCriteriaItem vci) {
        if (vci != null) {
            AttributeDef attrDef = vci.getAttributeDef();
            String attrName = attrDef.getName();
            // for string attributes check for the '_xxx_' sequence and remove the '_' around hte operator
            if ("java.lang.String".equals(attrDef.getJavaType().getName()) && vci.getValue() != null) {
                String colName = vci.getViewCriteria().isCriteriaForQuery() ? vci.getColumnNameForQuery() : attrName;
                String operator = vci.getOperator();
                String filterVal = (String)vci.getValue();
                _logger.fine("Before matching - Column: " + colName + " value: " + filterVal);
                int i = filterVal.indexOf("_");
                while (i > -1) {
                    int k = -1;
                    String subFilter = null;

                    k = filterVal.indexOf("_", i + 1);
                    if (k > -1) {
                        filterVal = filterVal.replaceFirst("_", "");
                        filterVal = filterVal.replaceFirst("_", "");
                    }
                    i = k;
                }

                _logger.info("Column: " + colName + " value: " + filterVal);
                // handling for STARTSWITH operator
                if (JboCompOper.OPER_STARTS_WITH.equals(operator)) {
                    int columnsValue = vci.getUpperColumnsValue();
                    // check if hte parameters are uppercase
                    String sql = "(%s like '%s%%')";
                    if (columnsValue != -1)
                        sql = "(UPPER(%s) like UPPER('%s%%'))";
                    String clause = String.format(sql, colName, filterVal);
                    return clause;
                }
                // handle other operators here
            }
        }
        return super.getCriteriaItemClause(vci);
    }

As the method is called for every criteria item we have to check if the current criteria is of type string as only string criteria react on the operands.
Then we need to create the where clause part for the criteria our self. The method implements this only for the ‘startswith’ operand!
If you need this for other operators too, you have to add the code to build the where clause at the commented point.

The workspace can be loaded from ADF EMG Samples Project. The sample uses the HR db schema and was developed using JDeveloper 11.1.1.6.0

JDeveloper 11.1.1.6.0 Use Selection in LOV to Navigate to Detail

This post shows how a selection in a list of value (LOV) can be used to navigate to another page to show detailed information about the selected item in the LOV. The sample uses the HR db schema, the work space can be loaded using the link provided at the end of the post.

Use Case
Using a af:selectOneChoice showing the department names of the departments table we want to select on department. Then by clicking a button we want to navigate to a different page which shows the details of the selected department.

Let’s start with a look at the finished application:

Running Application

Running Application

After selecting a department from the af:selectOneChoice we see the index of the selected department.

Select Department

Select Department

This is shown in the outputText below the LOV. Selection ‘Human Resources’ selects the index 3 in the LOV.

Navigate to Detail Page

Navigate to Detail Page

And finally the detail Page where we see the correct department id for ‘Human Resources’ of 40.

Detail Page

Detail Page

Implementation
To implement this use case we define two view objects (VO). One which we use for the LOV of department names (DepartmentLOVView) and one which we use to show the detail on a form for the detail page (DepartmentView1).

Data Model

Data Model

In the UI we define a bounded task flow (lov-select-detail-btf.xml) which is build using fragments. This task flow is put on a page (Start.jspx) as region.

lov-select-detail-btf

lov-select-detail-btf

Before we begin to setup the LOV we need a place to store the selected value from the LOV. For this we create a pageDef file for the DepSelect.jsff by right clicking on the page and selecting ‘Go to Page Definition’ from the menu. As there is no pageDef file one is created for us. We define a variable DepId inside the variable section of the ‘Exceutables’ section. Then we add an attributeValue ‘DepId’ in the bindings section.

Define Variable DepId inside the Executables Section

Define Variable DepId inside the Executables Section

Variable DepId

Variable DepId

Add attributeValue Binding

Add attributeValue Binding

Select DepId from variabels

Select DepId from variabels

To setup the LOV drag the DepartmentId from the DepaermentLOVView from the Data Controls section onto the DepSelecte.jsff fragment. Change the values in the dialog to match the image below:

Edit List Binding for DepartmentId

Edit List Binding for DepartmentId

In the property editor for the selectOneChoice set the label property to ‘Depaertment’ and the value property to ‘#{bindings.DepId1.inputValue}’ which is the attribute we defined in the variables section. Set the autoSubmit property to true so that selected values are posted into the variable once the value changes. The final selectOneChoise code is

        <af:selectOneChoice label="Department" id="soc1" required="#{bindings.DepartmentId.hints.mandatory}" value="#{bindings.DepId1.inputValue}"
                            autoSubmit="true" valuePassThru="true">
          <f:selectItems value="#{bindings.DepartmentId.items}" id="si1"/>
        </af:selectOneChoice>

To show the selected item we add an outputText which shows the “#{bindings.DepId1.inputValue}”, which is the place the value is stored after selecting a department in the LOV. Notice that we don’t see the DepartmentId (the PK of the VO), but the index of the selected department in the list binding. As we don’t use a value driven LOV we have to map the index back to the row key ourselves. One more reason to stick to model driven LOV whenever possible. In this use case we don’t use a model driven LOV by intent. This is to show how to map the index back to the row key of the list.

The missing element is a button we use to navigate to the next page, the detail page, showing the departments detail as a form (read only). To get this button, open the data controls section and then open the DepartmentsLOVView and open the ‘Operations’ node. Select the ‘setCurrentRowWithKeyValue’ operation and drag it onto the fragment. Drop it as operation->button. This will add the operation into the pageDef for the fragment. The image below shows the final pageDef:

Final pageDef

Final pageDef

The missing part is the mapping of the selected index to the needed key of the department. For this we select the button, go to the properties of the button. In the action property we select ‘Edit’ from the drop down list (small arrow) on the right side of the property. In the Dialog we create a new bean ‘DepSelectBean’ in the package ‘de.hahn.blog.lovselectdetail.view.beans’. In the method part we choose ‘new’ to create a new method ‘showSelectedDep’. Finally we change over to the source tab of the fragment and delete the ‘#{bindings.setCurrentRowWithKeyValue.execute}’ from the actionListener property. The reason for this is that we execute the method from the bean after we got the real DepartmentId from the LOV. The magic is done in the action method ‘showSelectedDep()’ in the bean.

    public String showSelectedDep() {
        BindingContext lBindingContext = BindingContext.getCurrent();
        BindingContainer bindings = lBindingContext.getCurrentBindingsEntry();
        // get the list binding for the department lov
        JUCtrlListBinding list = (JUCtrlListBinding)bindings.get("DepartmentId");

        // get the selected index from the list which is stored in the DepId1 attribute
        AttributeBinding attr = (AttributeBinding)bindings.getControlBinding("DepId1");
        Integer selid = (Integer)attr.getInputValue();

        // load the listdata
        Object row = list.getDisplayData();
        // get the selected row from the list
        Row lFromList = (Row)list.getValueFromList(selid);
        // from the row we get the PK the DepartmentId
        Object lAttribute = lFromList.getAttribute("DepartmentId");
        Number newVal = (Number)lAttribute;
        _logger.info("Information: selected Department = " + newVal);
        // get the MethodAction for setCurrentRowWithKeyValue
        OperationBinding method = bindings.getOperationBinding("setCurrentRowWithKeyValue");
        // set hte needed parameter as the department id
        method.getParamsMap().put("rowKey", newVal);
        method.execute();
        // after execution check for errors
        List errors = method.getErrors();
        if (!errors.isEmpty()) {
            Exception ex = (Exception)errors.get(0);

            FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(), "");
            FacesContext.getCurrentInstance().addMessage(null, msg);
            // keep on page in case of an error
            return null;
        }

        // navigate to the next page
        return "show";
    }

This concludes the implementation. The workspace can be loaded from ADF EMG Samples Project. The sample uses the HR db schema and was developed using JDeveloper 11.1.1.6.0

JDeveloper 11.1.1.6.0: af:inputText with self made Look-Up not using LOV

In this blog entry shows how to setup an af:inputText with a look-up which gets its data from a db table for easy reference. This sounds like an af:inputListOfValues you might say. The difference is that an af:inputListOfValues validates the input against the data present in the DB. In case you want to allow the user to chose values available, but also allow adding values which are currently not present, you can’t use af:inputListOfValues.

After you drop a VO from the data control which has an attribute setup an attribute as InputListOfValue you get the following code:

                      <af:inputListOfValues id="emailId" popupTitle="Search and Select: #{bindings.Email.hints.label}" value="#{bindings.Email.inputValue}"
                                            label="#{bindings.Email.hints.label}" model="#{bindings.Email.listOfValuesModel}"
                                            required="#{bindings.Email.hints.mandatory}" columns="#{bindings.Email.hints.displayWidth}"
                                            shortDesc="#{bindings.Email.hints.tooltip}">
                        <f:validator binding="#{bindings.Email.validator}"/>
                      </af:inputListOfValues>

Now when we run the sample (which is build using the HR schema and JDev 11.1.1.6.0, source code available using the link provided at the end of the blog) we see the form like:

Running Application

Running Application


You can click on the magnifying glass to search for an existing value for the EMail attribute.

EMail Look Up

EMail Look Up

However, if we enter a value into the inputText which is not part of the LOV, we get an error

Error when Value isn't Part of the LOV

Error when Value isn’t Part of the LOV

One way to get around this is to delete the validator from the af:inputListOfValues. However, this means that no validations take place on this field. The idea of this post is to build the look-up part of the af:inputListOfValues our self and add it to an af:inputText. The look and feel remains the same:

Application with Self-made Look-UP

Application with Self-made Look-UP

As you see there is no difference on the first look. However, clicking the magnifying glass we get a slightly different look-up

Self-made Look-Up

Self-made Look-Up

Now we can enter any value into the EMail field without getting an error

EMail with 'new' Value

EMail with ‘new’ Value

How is this implemented?
In the model project we have two VOs: one fro the form (EmployeesView) and one for the EMail look-up (EmployeesEmailView). This second VO has a view criteria which we later use to build the look-up in the popup. A third VO in the model project (TestEmpView) is used to show the normal behavior of the EMail attribute with a LOV attached to it.

In the view controller project we have one start page (Page1) which hosts a panelTabbed for the different solutions. The self-made look-up is done in the bounded task-flow input-text-lookup-btf, which is dropped as region into the first tab. The region (input-text-lookup-btf.xml) is build by dragging the EmployeesView from the data control onto the fragment (test1.jsff) as ‘ADF Form’. To get the look & feel of the af:inputListOfValue we have add an icon behind the af:inputText. To make this possible we use an af:panelLabelAndMessage which shows the label for the EMail attribute. Inside this we place an af:inputText in simple format (otherwise the label would show up twice) and finally the icon for the look-up.

          <af:panelLabelAndMessage label="#{bindings.Email.hints.label}" id="plam1">
            <af:inputText value="#{bindings.Email.inputValue}" label="#{bindings.Email.hints.label}" required="#{bindings.Email.hints.mandatory}"
                          columns="#{bindings.Email.hints.displayWidth}" maximumLength="#{bindings.Email.hints.precision}"
                          shortDesc="#{bindings.Email.hints.tooltip}" id="it2" simple="true">
              <f:validator binding="#{bindings.Email.validator}"/>
            </af:inputText>
            <af:commandImageLink id="cil1" icon="/images/icon_Pruefen.gif" immediate="true" blocking="true">
              <af:showPopupBehavior popupId="p1" triggerType="action"/>
            </af:commandImageLink>
          </af:panelLabelAndMessage> 

The generated af:inputText for the EMail attribute we simply delete. As you see the validator is still there but doesn’t show an error when we enter a value which is not part of the LOV from the popup. The popup used for the look-up, is a normal popup with a dialog as layout component. The dialog shows an af:query component generated by dragging the view criteria from the EmployeeEmailView from data control.

The missing part is how the value selected in the look-up is set into the EMail attribute on the form. This is done in the dialog listener which controls the dialog outcome:

    public void dialogListener(DialogEvent dialogEvent) {
        if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.ok)) {
            // get the binding container
            BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
            // get an ADF attributevalue from the ADF page definitions
            AttributeBinding attr = (AttributeBinding)bindings.getControlBinding("EmailPopup");
            Object inputValue = attr.getInputValue();
            // set the value into the other attribute
            attr = (AttributeBinding)bindings.getControlBinding("Email");
            attr.setInputValue(inputValue);
        }
    } 

The second tab (Test) hosts the normal use case using a af:inputListOfValue on the EMail attribute. This is just for reference.

The source for the sample can be loaded from ADF EMG Sample Repository. The sample is build on the HR db schema using JDeveloper 11.1.1.6.0.

JDeveloper 11gR1 Bug in Tuning Node of ViewObject

Today I came across a bug in the tuning node of ViewObjects in JDeveloper 11gR1 (meaning all 11.1.1.x versions). For a prove of concept I played with the tuning options available for ViewObjectes in JDeveloper. The following image shows the the default tuning node of a ViewObject (it doesn’t matter if it’s based on an EntiyObject or not):

Default Tuning Node

Default Tuning Node

As I tested some options I eventually switched to the ‘Only up to row number’ radio button which enables the input field for the number of rows:

Tuning for '...up to row number'

Tuning for ‘…up to row number’

Nothing special there. Now if you delete the number (default is 10)

Delete Number from Field

Delete Number from Field

and ‘tab’ out of the input field, or click on any other field, you get an error dialog telling you that ‘(null) is not a valid fetch size value’.

Error Dialog

Error Dialog

OK, this is correct, but if you hit the OK button or the ‘x’ to close the dialog to put the number back in the dialog stays open, you can’t close it. You don’t get a chance to put the number back into the field. A first I had to kill JDeveloper through the task manager (I did that a couple of times ;)) until I found the following workaround:
            hit the Esc key
you may need to do this multiple times, but the dialog closes eventually and the last number is back in the input field.

This bug is fixed in the current JDeveloper 11gR2 (11.1.2.3.0) version!

JDeveloper 11.1.1.6.0: The Git Experience (Part 2)

End of November Oracle released a new JDeveloper version 11.1.1.6.0 Build 6229 (What’s new 11.1.1.6.0) which introduces Git support as one of the new features.
Part 1 showed how to setup and use git integration in JDeveloper
In part 2 of the series I show how branching and merging are done using the git integration in JDeveloper.

Let’s start with a picture of the current git repository:

Repository at Start

Repository at Start

Here is the first missing part in JDeveloper’s git integration. There is no visual representation of the whole repository available as shown in the image above. To get such a representation we need to install a third party tool (msysGit in my case, or Tortoise Git which can run in parallel on a Win7 machine). JDeveloper only allows you to see the history of one file via the ‘Version History’ menu. The images of the repository we’ll see in this blog are done with msysGit.

As we see there is only one branch named ‘Master’ and we see a straight line of dots, each representing a commit to the ‘Master’ branch. We start by adding a new branch to the repository named ‘AddCalcuatorClass’. The name of the branch can be almost anything, as long as it doesn’t contain spaces. We choose the name of a branch so that it reminds us later why we created the branch, or what it’s used for. As the name of the branch indicates we add a class to the project which implements a simple calculator.

Create New Branch

Create New Branch

Name the new branch ‘AddCalcuatorClass’

Name Branch

Name Branch

The ‘Application Navigator’ did not change, but the new branch is visible in the ‘Version Navigator’ in JDevelpoer

Version Navigator

Version Navigator

the same from the view of msysGit:

msysGit Repository after adding new Branch

msysGit Repository after adding new Branch

We need to play close attention to the different views and what they tell us. In JDeveloper we still see ‘[master]’ behind the project name. This tells us that we are still working on the ‘master’ branch and not the new created branch ‘AddCalculatorClass’. The msysGit image shows the same as the ‘master’ branch is printed in bold (which it does for the current branch).
To switch to the new branch we need to checkout the branch.

Checkout Branch

Checkout Branch

then click the ‘Select Branch’ button in the dialog to get to the available branches and select the ‘AddCalculatorClass’ and click ‘OK’, finally close the dialog by clicking ‘OK’ again.

Select Branch

Select Branch

After that we are working on the ‘AddCalculatorClass’ branch, only we don’t see it right away. We need to refresh the project (e.g. clicking the refresh button) to see the ‘[AddCalculatorClass]’ right to the project name.

Now working on 'AddCalaculatorClass' Branch

Now working on ‘AddCalaculatorClass’ Branch

Again the msysGit image:

msysGit: new active Branch

msysGit: new active Branch

Now we add a new class ‘Calculator’ to the project. For this we add the new class from the ‘Candidate’ tab and then commit the new file by committing it

Add new Class to Project and Repository

Add new Class to Project and Repository

Add new File

Add new File

Commit

Commit

Commit dialog

Commit dialog

Repository after adding new File

Repository after adding new File

Now we add an other method in the calculator class which should multiply to parameters and return the result. After that we commit the change and the repository looks like:

Repository after Change of Calculator Class

Repository after Change of Calculator Class

Let’s assume that we have to fix a bug in the main development path, which is ‘master’. We have to switch back to the ‘master’ branch. This is done by checking out the ‘master’ branch again. The procedure is the same we already saw before. The result in JDeveloper looks like:

Back on Branch 'master'

Back on Branch ‘master’

msysGit: Back to 'master'

msysGit: Back to ‘master’

As we see the new class ‘Calculator’ is not part of the project as it was not added in the ‘master’ branch. Back to the ‘master’ branch we add another class ‘Stack.java’ and add some lined to the existing class. After committing the changes, in multiple commit cycles to get a better visibility of the different branches, the repository look like:

Repository after change to 'master'

Repository after change to ‘master’

Let’s switch back to the ‘AddCaclulatorClass’ branch to finish the work on this class by adding two more methods to subtract and divide to parameters. After this work is done the repository look like:

Repository after more work don in 'AddCalculatorClass' Branch

Repository after more work don in ‘AddCalculatorClass’ Branch

A requirement is that we need the changes done in the ‘master’ branch now need in our current branch ‘AddCalculatorClass’. For this we need to merge the branch ‘master’ to the current branch ‘AddCalculatorClass’. This is easily archived by opening the ‘Version Navigator’, open the node of the project and then the open the ‘Branches’, ‘Local’node. Here we see the currently available branches ‘master’ and ‘AddCalculatorClass’. The same can be archived by right clicking the Project and select ‘Versioning->Merge…’.

Merge 'master' Branch

Merge ‘master’ Branch

Merge

Merge

After Merge

After Merge

Don’t forget to refresh the project to see the added class. The resulting repository now looks like

Repository after Merge

Repository after Merge

with all changes made to the branch ‘master’ including the new class Stack. We could have done the merge the other way around. Then we had to checkout branch ‘master’ and then merge branch ‘AddCalculatorClass’. This would give us a repository looking like:

Merge 'AddCalculatorClas' to 'master'

Merge ‘AddCalculatorClas’ to ‘master’

The difference at this moment is, that the changes are visible in the ‘master’ branch and which branch is active after the merge. We can create another branch from every other tag or branch currently present in the repository. Let’s make a new branch ‘DoCalcDifferent’ from the ‘master’ branch. Remember that we are currently in branch ‘AddCalculatorClass’. Still we are able to create the new branch. We can also create a branch based onany other branch like ‘AddCalculatorClass’ which we call ‘AddCalc2’. A look at the repository after all this:

Branch Festival

Branch Festival

We see it’s easy to create new branches, switch between them to do some work, merge the different branches without problems. Make yourself familiar with the technique and how to use it. This is especially true after some wild changes to different branches. We may end up with a confusing repository like

Complex Repository after some changes

Complex Repository after some changes

where it’s not obvious which change created which node in the repository. It may take a while, but in the end it’s much easier then it looks and it’s more productive then SVN or CVS.

Learning to use git the integration into JDeveloper is a good start. However, we need some of the other git commands (e.g. cherry pick) or representations (gitk to view the whole repository) integrated into JDeveloper to make it really a great tool integration.

I have planned a third part for this series, but can’t really tell when it is going to happen. This 3rd part covers remote git repositories which add a new dimension to the git picture. Right now I don’t have a remote git repository available. I’m looking into this issue in the next couple of days/weeks and hopefully get one installed and running.

JDeveloper 11.1.1.6.0: The Git Experience (Part 1)

End of November Oracle released a new JDeveloper version 11.1.1.6.0 Build 6229 (What’s new 11.1.1.6.0) which introduces Git support as one of the new features.

After a short break in my busy schedule I tried out the new Git support and decided to write a multi part blog series about it. First I thought about writing it all up in one post, but the plenty available options would make this more like a book ;). So in this first part I run through the basics of Git support in JDeveloper, showing how to version an application using Git (locally), make changes to the project and show some parts which need some improvement from Oracle. The next part drills into branching and merging of projects and remote Git repositories.

Lets start with the obvious, a look at the available documentation. You find the documentation in the ‘Developing in Teams’ section of the JDeveloper internal documentation which is available via the ‘Help’ menu. You can search for ‘git’ using the ‘Help’ menu to get there fast. Looking at the first chapter it looks like Git has not added to all available topics. The ‘About the Available Versioning Systems’ only shows SVN, Concurrent Version System (CVS), Perforce, Serena Dimensions, ClearCase and Team System. However I assume that this will be fixed in an upcoming version of JDeveloper. There are more thinks which need to be reviewed in my opinion. I point them out whenever I talk about the specific topic.
A new chapter ‘Using Git with JDeveloper’ has been added which covers the basics of working with Git. My first impression is that the doc is written from the point of view of the Team extensions for JDeveloper because I couldn’t find the ‘Team’ menu as I don’t have a Team server available on my laptop. However, most options are reachable through right clicks, which then reveals the ‘Team’ menu, or at least parts of it. I encourage you to at least scan this documentation. If you never heard of Git you should search the Web for a introduction to Git first.

Leaving the documentation, lets start to play with Git. A short overview over the configuration option of Git:

GIT Options Page 1

GIT Options Page 1

This first page gives you the option to define some default text which the you can use when committing changes to the reposritory. Once you add a template they are shown in the dialog. like in the image below. I didn’t find out if you can add some tags to the templates which expand later to text like ‘author’. In my sample the text is not very intelligent, but it’s only to show the feature. The ‘/’ you see are line breaks which are added in the template.

GIT Options Page 2

GIT Options Page 2

GIT Options Page 3

GIT Options Page 3

GIT Options Page 4

GIT Options Page 4

As you see there isn’t much to configure in the global options. All other configurations are done on application level which we start looking into right now. We start with a test case, an generic Java application, which consists of just one Java class with a main function at the beginning.

Test Java class

Test Java class

As with SVN we start with ‘Versioning’ the application which we reach via a right click on the application work space, or the ‘Application’ menu, then use the ‘Version…’ menu.

'Version Application...'

‘Version Application…’

now we see Git as possible version control system

Hello Git

Hello Git

Now we follow the wizard

Git Import Wizard Page 1

Git Import Wizard Page 1

Git Import Wizard Page 2

Git Import Wizard Page 2

Git Import Wizard Page 3

Git Import Wizard Page 3

Git Import Wizard Page 4

Git Import Wizard Page 4

That’s it, easy enough. Now we see that the application is under source code control

Application after import

Application after import

and we find the first difference from the SVN view. We see that the project uses the ‘master’ version which is equal to the SVN ‘trunk’ version. Opening the tree in the ‘Version Control’ panel, we see the branches node and below it the local branch where we see the ‘master’ version.

OK, next we start to make some changes. First lets add a public method to the sole Java class. Right after this, save the change and open the ‘Pending Changes’ panel to see if the change is visible there.

First Change

First Change

Next we need to commit the change to the local repository. For this we have some image buttons:

Image Buttons to work with changes

Image Buttons to work with changes

the green plus sign is used to add files to the ‘staged index’. The ‘staged index’ holds all files which are later committed in one transaction. I call this a ‘commit set’. The button next one opens the commit dialog where you add a comment to the commit set. If you click the commit button right of the green plus sign you see the commit dialog, together with the changed file, but committing will tell you that there is nothing to commit from the ‘staged index’ or the ‘commit set’. That’s a difference to the SVN work flow. Using Git, changed files are first staged in an index, or a commit set. Only after this you can commit all files in the index or set together in one transaction.

Clicking the green plus sign opens a dialog which lets you add changes files. However, when you check the help for this dialog you get a kind of confusing help which tell you that you use this dialog if you add new files to the repository. This is not the case, so lets ignore this and add the changes file.

Add File Dialog and Help

Add File Dialog and Help

Once the file is added to the ‘commit set’ or ‘staged index’ you’ll notice, that the green plus sign gets gray, still the file is visible in the pending changes panel. Only after clicking the ‘commit’ button, right of the green plus button, adding a comment, or selecting one from the predefined templates, and closing the dialog with the OK button, the panels gets cleared. At this point the change is committed in the local repository.
To visualize this open the ‘Version History’ of the Java class:

Get Version Histroy

Get Version Histroy

and we’ll see all versions which we can filter using the filter select one choice at top of the panel.

Version Histroy

Version Histroy

Lets check the differences between the two versions:

Difference between versions

Difference between versions

This all looks like the we know it from SVN.

Finally, to conclude this first part lets check if we can work with an external Git application too. For this test I use msysgit and GitGui which comes together with the installation. The image below shows the change before the last commit

GitGui

GitGui

After some commits with msysgit we again look at the version history of the Java class

Version Histroy after msysgit commit

Version Histroy after msysgit commit

Thankfully, the two different applications (JDeveloper and msysgit) are working well together. Up to now I have not found anything which make working with the different apps break the whole version control system. That is a big step forward!

That’s it for the first part. Stay tuned for the next part where I show how to clone a repository from a remote Git server and how to work with branches.