Table of contents
Working copies - it is almost my most wanted APEX feature.
It's finally available in Oracle APEX 23.2 - you can download it here.
What would I like more than this? An ability to export the APEX application into YAML format(this part is doable), merge it in the GIT repository, and import a final version of the APEX app (still in YAML) into my database. But this is the future. How close? I don't know.
What are "APEX working copies"?
According to Oracle's documentation, it allows you to create a copy of an application, make changes in that copy, and then merge those changes back into the main application. Similarly, you can merge changes from the Main application into the Working Copy. During export, you can view a comparison (or diff) of the Working Copy and the Main application and then select which changes to merge.
What could a typical developer expect from Working Copies?
What are my expectations:
I don't need to have a separate APEX development (DEV) environment for each developer (there still will be people who could argue and ask: "What about the database?" but it's not a topic for this blog :) ).
I always forget to lock pages I work on (or unlock them once finished) so I won't have to remember about it anymore. I don't need to lock pages anymore (but I should).
I will be able to review developer's changes in their working copies and decide what should be merged into the main application.
My use case:
I'm using my workspace at apex.oracle.com
My main application (MA) is "Sample Reporting MAIN APP" 15014
I will create two working copies for DEVELOPER_1 and DEVELOPER_2.
Create a "Working Copy"
Go to the main application APP Builder (as a DEVELOPER_1)
Two nice icons indicate you are in a "Main application" right now.
Pick "Create Working Copy"
Pick a name and click "Create Working Copy".
Repeat the above steps as DEVELOPER_2.
There is also an option to create a copy or switch to existing copies directly from the new context menu:
I also have an enhanced view showing the number of working copies (report or icons view).
"Working copies" column was there by default, and the "Working Copy Info" was chosen by me from Actions -> Columns.
I hoped that this nice GIT branch icon would grow with the number of copies, but it always shows two branches :)
Choose a "Working Copy" to work on.
To pick one of the created copies, go to the main application app builder and select one from the right side.
What I'm missing in this feature? An option to prevent other developers from using a working copy I created. Just make my copy exclusively available for me.
No matter who I am logged in (DEVELOPER_1 or DEVELOPER_2), I can see (and work on) all created working copies.
What does a "Working Copy" look like inside?
The working copy name is shown on the right of the main app name.
My application copy (created as DEVELOPER_1) received an ID 70529, and for DEVELOPER_2 ID is 61613.
Also, the branch icon colour changed to brown (grey for the Main app).
That's good because it will be hard to change something in the main app by mistake.
What else is there?
There is a new menu dedicated to Working Copies. Some of the options are also repeated on the right side of the page for faster access.
Let's look at a view of the apex builder for a specific page I want to edit.
There is the same context menu as on the main apex builder page with a branch icon indicating that we are in "Working Copy" mode.
Making changes in two Working Copies by two developers
Changes made by DEVELOPER_1 in a working copy "Sample Reporting DEVELOPER_1."
- A new column was added to a query in Classic Report on page 3.
- Changed the Interactive Grid title on page 17
- I also changed the Automatic Time Zone to YES (unfortunately, merging Application Attributes is not supported - read further about it)
- I created a new page 16.
- With an empty Static Content region.
Now, DEVELOPER_1 is going for a coffee break (changes are not merged to the main application yet), and DEVELOPER_2 will be making changes in his own copy :)
Changes made by DEVELOPER_2 in a working copy "Sample Reporting DEVELOPER_2."
- A new page with an interactive report was added.
Notice the page number assigned automatically - it's also 16. The exact number was assigned to the new page created previously by DEVELOPER_1 ( but DEVELOPER_2 doesn't know it yet).
- DEVELOPER_2 also created a new list of values.
- And new column was added to the report on page 3 (DEVELOPER_1 modified the same query in his working copy, but of course, DEVELOPER_2 doesn't know about it)
Compare changes from Working Copies with the Main Application
Working Copy "Sample Reporting DEVELOPER_1" changes vs. Main App.
After finishing work, DEVELOPER_1 can review and merge his changes into the main app.
What's interesting is that DEVELOPER_1 is also allowed to use a working copy created by DEVELOPER_2 and do whatever he wants with that copy.
But first, we should compare changes made in the working copy with the main app (there are two places to do that).
Quick shortcut/tip - you can skip comparing changes and go directly to "Merge into Main" and compare your changes there.
What happens next:
It seems like APEX is exporting the Main Application somewhere to YAML format.
The same thing is happening with working copy.
And the result is below.
It looks nice, but why can't I sort by the "Status" column? :)
I also got a warning saying that some of my changes can not be merged into the main app (not supported changes yet). So, is everything gonna be merged or not? It would be nice to have exact information.
DEVELOPER_1's expected changes are:
Changed Classic Report Query on Page 3, which looks good in the "View Differences" window.
Changed the IG title on page 17 - it's also good-looking.
Changed Automatic Time Zone to YES in Globalization Attributes - oops! There's no such change listed anywhere. It's an Application Properties component that is not supported, but why can't it be listed with the status "NOT SUPPORTED TO MERGE"?
Added new page 16, with empty Static Content region - all changes seem to be there.
Working Copy "Sample Reporting DEVELOPER_2" changes vs. Main App.
Now, let's review the changes made by DEVELOPER_2.
DEVELOPER_2's expected changes are:
Added new page 16 with Interactive Report.
One LOV in shared components was created.
Changed Classic Report Query on Page 3.
All changes seem to be there.
But I still have this warning that I might have some modifications that cannot be merged. I think all the above changes are supported.
Merge changes from Working Copies to the Main Application
Merge from Working Copy "Sample Reporting DEVELOPER_1" into the Main App.
DEVELOPER_1 is ready to merge his changes into the MAIN APP.
Here comes the export again.
And the result is below.
I have a list of my changes. I can choose what I want to merge and still see my "Differences view" by clicking the "DIFF" icon (actually, it does the same as the "Compare changes" option)
But I can still see a warning saying that some of my modifications might not be changed.
Which ones? Why are they listed here? I don't know - there's an area for improvement for APEX Team :)
Probably, it's about my change in Globalization Attributes, which is not even listed here.
I will choose all and click NEXT. My next screen is below.
There are two extra features:
Backup target app first
Delete the working copy after merge.
Deleting a working copy can always wait, but that's so nice from the APEX Team that backing up a Main App is a default option. We always do backups and remember about it, do we? :)
I'm leaving it with default values and clicking "Confirm Merge".
It took about 5 seconds and automatically moved me to my Main App view with a fantastic message: "Your changes have been successfully merged!".
I was supposed to have some changes not merged due to unsupported types, but they were all merged. Do they?
It also looks like a backup was created.
Let's have a look at recently edited components in my Main APP:
Looks good. All were merged, and my Main App is now improved with new features/changes from the working copy of DEVELOPER_1.
Merge from Working Copy "Sample Reporting DEVELOPER_2" into the Main App.
Now, DEVELOPER_2 is ready to merge his changes into the main APP.
DEVELOPER_2 can easily review changes and differences and decide what should be merged into the Main App.
In the example below, a developer can see that PAGE 16 is listed as "Changed" instead of "Added" because DEVELOPER_1 merged his new page with the same number into the Main App.
Components with "Missing" status mean that they do not exist in DEVELOPER_2's working copy but exist only in the Main App.
That screen will allow you to resolve conflicts and choose what to merge or exclude easily.
In that example, I will choose everything possible.
Merge was a small car crash (no blood). But it was intended :)
Let's take a look into the Main App now. I had some conflicts, and because I decided to merge everything from the DEVELOPER_2 working copy, the final result is shown below.
Page 3 with a classic report.
"Developer_1_New_column" was lost. It would still be there if I refreshed my working copy before merging. But the behaviour of this feature was as expected.
Page 16 (created by both developers).
A version of this page (created by DEVELOPER_1, with only static content inside) was removed and replaced with the version created by DEVELOPER_2 (with Interactive Report).
You are probably wondering how it is possible that Main App shows "DEVELOPER_1_NEW_PAGE" while DEVELOPER_2's changes overwrote it.
Because breadcrumbs are separate components and were created by both developers during page creation.
And because both breadcrumbs have the attribute "Page -> 16", then APEX renders the first one matching, which is "DEVELOPER_1_NEW_PAGE"
Always refresh Working Copies with the Main Application.
I think it could be a good practice for developers to always refresh the working copy with the Main App before merging working copy changes to the Main App.
It would allow developers to get all changes made in the Main App since creating their working copy. In that case, DEVELOPER_2 could pull all changes made by DEVELOPER_1 into the main app since DEVELOPER_2 created his working copy.
It would minimize conflicts and reduce unnecessary work that may have already been implemented into the main application. It would also help avoid merge issues that occurred while merging the DEVELOPER_2 working copy into the Main App.
Refreshing looks the same way as merging into the Main App. The difference is that you merge changes from the Main App into your working copy.
Tips, Unsupported Component Types and Limitations (by Oracle)
Here are some pieces of information from Oracle that will show up when you click on the "More information" button while comparing changes/merging working copies.
Full documentation is here.
Overall, I think it's an outstanding feature that works very well - and remember that it's only in pre-production release. I hope it keeps getting better.
What I really like:
The "Working Copy" feature is like GIT inside APEX. I like versioning and controlling deployments, so I love this feature :)
Big Respect to the APEX Team that you assume people do not take backups by default. You're absolutely right! That's why this checkbox marked by default during merging is almost a life-changer :)
If I uncheck this checkbox :)
What am I missing in it's features right now:
A way to lock working copies and make them visible/editable only for selected users/creators of it.
Ordering/filtering by "Status" at the list of changes to merge/compare.
A feature that will prevent some developers from working on the Main App and allow them to work/edit only their working copies. It would allow DevOps guys (more privileged) to review changes and decide what should be merged into the Main App.
Instead of/in addition to this message, I prefer an exact list of changes I've made that can not be merged into my Main Application. Now, I need to guess and search in documentation.
It would be nice to have an indicator in my working copy telling me: "Hey, someone changed something in the main application. How about refreshing your copy?"
What are your thoughts? Have you tried it already?