The developer workflow always begins and ends with JIRA.
Everything about an issue is captured in JIRA, whether it is a Bug, Feature, Tweak, or Task. JIRA is the database of record for OpenJFX. Any Bug, Feature, Tweak, or Task will have all comments related to the issue recorded directly on the issue, or linked to from the issue. For example, if there is an openjfx-dev mailing list thread about the issue, the issue should contain a link to the mail archives.
The first step in the workflow is to search JIRA for your issue. You may use the JIRA search functionality, or you may ask developers on openjfx-dev if an issue you see is a known issue. You may be asked to file an issue. If you do, it is important to understand the difference between a Feature, a Tweak, and a Bug.
A Feature is a significant piece of new functionality which is expected to take more than two weeks to implement, document, and test. Because features represent a significant amount of work, a development team needs to prioritize and approve work on features. Whoever proposes to work on a feature is responsible to "fund" the development, documentation, and testing. For example, if Feature X is important to you, you can take responsibility to ensure that it is developed according to guidelines and feedback from the team, develop the documentation, and develop the tests. If you do so and the feature is in harmony with the rest of the platform (we're not adding a full blown email client!) then the feature has been "self funded" by the contributor, but will still be gratefully accepted by OpenJFX. On the other hand, if all you propose is to provide the implementation, then it will be up to somebody else to agree to fund the documentation and testing before the feature can be integrated.
Features do not necessarily mean new API, they may also mean significant implementation work such as a new rendering pipeline. A Feature is never a Bug.
A Tweak is a less significant amount of work. It is somewhat like a "little feature". Tweaks can be delivered after the Feature Freeze date, even if they implement new API, as long as the amount of work to deliver the completed tweak is less than two weeks. As with Features, if a contributor wants to supply a Tweak, it is best to ensure that testing and documentation is complete, otherwise the Tweak may not be accepted.
A Bug is a defect in the code. Something is not behaving as it should. Bugs can be fixed all the way to the Code Freeze date, although with stricter guidelines the closer the Code Freeze date approaches. Sometimes the line is blurry between a Bug and a Feature, so be gentle if you need to adjust somebodies Feature to turn it into a Bug or (worse!) if you have to turn a Bug into a Feature. Use judgement and Do the Right Thing.
As a contributor, you might be done with your involvement after filing the issue. If you are not interested or capable of spending the time to supply a patch as well, we thank you! Every little contribution makes a big difference and is gratefully received.
Otherwise, it is time now to tell the Issue owner that you are interested in providing a patch. Collaborate with the owner -- they may already have something in mind that could make your job easier, and smooth the process of accepting the contribution back. Make sure people know you are working on something so that effort is not duplicated. Be responsive if people approach you about the current state of the work.
You should also make sure that you have signed and submitted an Oracle Contributor Agreement and that it has been received and processed. A committer must ensure this has been filed for any non-trivial contribution and the submitter is on the signatories list.
One excellent way to collaborate is to fork the project on BitBucket. From here you can work transparently, making your changes readily available to anybody who would like to contribute. If you need to go away for a while, let the Issue owner know so that the owner isn't waiting around for a patch that is never going to come.
Once you have a patch developed, you have two options. If you are a committer, then you should use the code review process (TBD). If you are not a committer then the best approach is to attach a diff or patch to the JIRA issue if it is very small, or a Webrev to the issue if it is larger. Or you can issue a pull request from BitBucket and provide a link to the pull request in the JIRA. From this point, the issue owner needs to provide quick feedback in the JIRA issue, a code review, and acceptance of the submission when appropriate or clear guidance on why a submission was not accepted when appropriate.
The committer who owns the issue will then be responsible for taking the patch, applying it, running the tests, and pushing the fix to the repository. The comment on the change set should be of the form:
RT-12345: Short Description of the JIRA issue
Summary: Optionally provided to give more info on what is being done
Submitted-By: Contributor email who submitted it
The Summary is optional, and Submitted-By should only be used when the contribution came from somebody who is not a committer on the project.
The final step is to update the JIRA. The JIRA issue should be marked "Resolved" (not "Closed") and a comment should be added with a reference to which changeset(s) were involved. This is most helpful when it is a link to the Mercurial HTTP website for OpenJFX so that a simple click will lead to the patch.
Mercurial is a very powerful source control system. If you have not used Mercurial before, it is highly recommended that you download and read the free Mercurial HG RedBook. This will give you a working knowledge of how to use Mercurial from the command line, which is very useful for those cases that you run into from time to time where whatever Mercurial UI you might use day-to-day fails you.
Since cloning a fresh repository is fairly expensive, and since developers are often faced with working on several issues concurrently (perhaps one is in code review while you work on another), each developer must decide how to manage multiple concurrent patches. The most dangerous method is to have a single repository with multiple fixes in it concurrently, because the possibility of introducing a bad patch is quite high.
Because true branches in Mercurial are a permanent part of the record and pushed to all parent repositories, we never use branches in Mercurial. Rather, we either use locally cloned repos, manually managed patches, or Mercurial Queues.
Having multiple local repos is relatively straightforward. First, you clone from whatever the parent repo is you want, for example:
hg clone http://hg.openjdk.java.net/openjfx/8u-dev/rt /path/to/my/local/integRepo
Then you clone from your local integration repo, once for each local "branch" you want to maintain. Because Mercurial will use hard links, this should be fairly quick in most cases.
hg clone /path/to/my/local/integRepo rt-1234 hg clone /path/to/my/local/integRepo rt-5678
Basically at this point you manage your own integrations with the graphics repo. Theoretically straightforward, but a lot of busy work!
Another common approach is to use manually managed patches. The way this typical works is that you clone from your repo (such as graphics) and work in that cloned repo. You then do some work. When it is time to switch to another issue that needs to be fixed, you save off the current changes as a patch, revert the changes, and start work on the second issue. When you want to switch back to the first issue, you save off the diff for the second issue, revert all changes, and import the first diff again.
hg clone http://hg.openjdk.java.net/openjfx/8u-dev/rt cd rt vi SomeFile.txt hg diff > rt-1234.patch hg revert --all --no-backup vi SomeOtherFile.txt hg diff > rt-5678.patch hg revert --all -no-backup hg import --no-commit rt-1234.patch
This is by no means foolproof and is a fair amount of work! Wouldn't it be great if there were some tools to automate this work? Well, that is exactly what Mercurial Queues are. Conceptually MQ is one big queue of patches that get applied to your workspace. You can push new changes on, and pop changes off. The above example would be implemented like this in MQ:
hg clone http://hg.openjdk.java.net/openjfx/8u-dev/rt cd rt hg qnew rt-1234 vi SomeFile.txt hg qrefresh hg qnew rt-5678 vi SomeOtherFile.txt hg qpop
SourceTree and TortoiseHg
Instead of using the command line (or perhaps, in addition to) you can also use various visual tools. Atlassian produces one for Mac (and now for Windows) called SourceTree. It has a very simple and intuitive user interface and performs most every task you need when it comes to managing a mercurial repository. You can clone directly within the tool, or open an existing locally cloned Mercurial repository. From within SourceTree you can view the entire history, search through the history, view outstanding changes, commit, push, pull, and perform all the other operations necessary for working with your repo.
Another highly used visual tool for Mercurial on Windows is TortoiseHg. It is very similar visually and in function to SourceTree. For this reason we will focus only on SourceTree in this section, as much of this information also applies to TortoiseHg, or is near enough that you can figure out the rest.
The main window gives a quick view at a glance of the current state of affairs. The branch view shows the history of changes and merges that exist in the repo. You can easily see who has pushed what changsets. If you select a changeset within this view, the details of the changeset are shown below it, listing all the files, and the individual hunks that changed. For the current uncommitted changes, you can revert any hunk (not just an entire file!), and for committed changes you can reverse any hunk (or file), making it easy to back out some changes.
SourceTree also gives you a method for dealing with multiple concurrent changes (the problem we defined in <<Using Mercurial>> above). It is similar to the manual patch style, but using visual tools instead of managing it by hand.
First, we have a very simple project with a single file, Foo.txt. Our repo has a single change set where Foo.txt was created and its single line "First Foo".
We then modify the Foo.txt file. You can see that we've modified the first line to say "Second Foo".
We've now been interrupted and need to switch to another issue. First we select the "Shelve" toolbar button and name our shelved change set
The repo has now been reset to its normal state, and I am free to start working on my second issue, RT-5678. I then am interrupted again and have to switch back to rt-1234 in order to commit the work (perhaps a pending code review has now finished). So, as before, I shelve my changes.
Now I select the shelved rt-1234 and choose to unshelve it.
Mercurial with NetBeans
Mercurial with IntelliJ IDEA
Mercurial with Eclipse
OpenJFX is a project with committers and contributors from all over the globe. We all live in vastly different timezones and speak very different native languages, and yet all collaborate together on a single code base and a single project. It is sometimes easy for misunderstandings to arise, and sometimes difficult to effectively communicate ideas in a time-sensitive manner. Over many years the software development community has identified a few things that make communicating and collaborating on software easier. We have tried to gather the best practices and bring them all together.
The openjfx-dev mailing list is the main source for free-form communication among all members of the team. The mailing list archives are publicly available. After subscribing to openjfx-dev, you are able to post textual content and easily follow along in all the various issues that are discussed on the list. openjfx-dev is intended as a list for discussing the development of OpenJFX. Every API change request is first created as a JIRA issue, and then a formal request made to openjfx-dev. This is so that everybody can see when a new API is being proposed, and can chime in (primarily on the JIRA issue) with feedback about that API design.
openjfx-dev is also the place to raise architectural issues or questions, or to get help when things aren't building or when some new idea needs to be discussed. It should be a place of respect and moderation in dialog. We're all on the same team, working together to build the best project we can.
Although much dialog occurs on openjfx-dev, the most work and the most data resides in JIRA. Each issue in JIRA contains (or should contain) all of the information pertaining to that issue, such that anybody who reads over the issue can understand the problem, the proposed solutions, the chosen solution (and why it was chosen), the nature and flow of the code review, and when and where the fix went in (or why a fix did not go in) and/or links to that information. JIRA will tell you when an issue is scheduled for work, or if it is unscheduled, or if it is unassigned or to whom it is assigned. Generally individuals are encouraged to vote for issues they feel are important, and to watch any issue that they are interested in and want to participate on.
Most teams also setup JIRA Dashboards for monitoring the progress of a particular release. Some are also using JIRA tags on issues to indicate which "sprint" an issue is assigned to. These dashboards can be searched out by each user of JIRA and added to their home page.
By using JIRA effectively, and by using JIRA dashboards, it is possible for anybody to follow along with development of those issues they are most interested in, and to track the progress of the release and what work is going on now. We attempt to make sure that JIRA is the database of record, meaning that the most accurate up-to-date information is always kept in JIRA.
It is important to understand some unique challenges that come with building for the JDK. All Java developers have experience in building applications which rely on a specific JDK, but very few have attempted to build code for the JDK itself. Welcome to an elite band . As you know, when the JVM starts up, it locates classes on a class path. By default, all JDK classes are first on the class path, before any application code. Normally this is not a problem, because application code is not redefining java.lang.String, for example. However when building JDK code, that is exactly what you are doing. In the case of JavaFX, your version of javafx.scene.Node needs to take precedence over the version of javafx.scene.Node provided by the JDK. Further, since you need a version of the JDK available to build against, you have to deal with the problem of having two versions of most classes on your class path – those provided by the JDK you are building with and those you are providing yourself.
Over the years JDK engineers have developed various techniques for dealing with this problem. The issue manifests itself at two times: when you attempt to build, and when you attempt to run code. For now this document will cover the build part of the problem only. The good news is that the OpenJFX Gradle build handles this for you.
The main contributions of JavaFX to the JDK are the jfxrt.jar file and several native libraries. jfxrt.jar is located on the extension class path. This path comes before application code but after code on the boot class path. Because of this, the jfxrt.jar file is located in JDK_HOME/jre/lib/ext/ (ext here stands for 'extension'). Java allows developers to override the location of the ext directory by means of the -Djava.ext.dirs= command line argument. Setting the value of this argument to empty (i.e.: a dangling = sign with nothing after it) effectively clears the ext path. This means that the jfxrt.jar file shipped with the JDK won't be included on the class path by default.
This is how the OpenJFX Gradle build works. Whenever anything needs to be compiled (whether compiling java sources, or running javadoc) we always set the -Djava.ext.dirs flag to be empty. This way the code we're building isn't confused by the presence of another nearly identical set of classes on the ext class path (that is, our locally built jfxrt.jar and associated files take precedence over what is supplied by the JDK).
During the week many changes go into the repositories. Some of these changes may require that you rebuild all of the native libraries. Some libraries like Media and Web are not normally built and are harder to build on some platforms because they require more libraries to be installed. Other changes reference new API or use language features in the latest JDK.
Each week we produce a published "promoted" build of the JDK which includes the week's worth of changes to JavaFX. Generally speaking, you should always use the same corresponding version of the JDK. For example, on Mar 22 2013 we published b82 of the JDK. When building from OpenJFX master for the following week, use b82. If you always keep up to date, then you will get the latest binaries and OpenJFX will always compile.
If you have additional build issues, let us know on the openjfx-dev mailing list.