Wednesday, 11 November 2020

1Z0-817 exam review

I took and passed the "1z0-817 Upgrade OCP Java 6, 7 & 8 to Java SE 11 Developer" exam this week. I previously held the OCP (Oracle Certified Professional) Java 8 (Note: Oracle renamed the OCA (Oracle Certified Associate) and OCP to Programmer I and Programmer II respectively). In this post are some of my thoughts and recommendations.

Revision

The exam topics are purposely vague. This is so Oracle can tweak the exam and test you on broader concepts.

1Z0-817 is specifically an upgrade exam from previous OCP versions to Programmer II in Java 11. Documentation and guides are more abundant for the full Programmer I and II exams (1Z0-815 and 1Z0-816) as there is a higher demand.

These two aspects make studying for 1Z0-817 more challenging. I found and used the following resources:

Oracle University: If you have the funds then the Java University subscription is a great option. Oracle added hundreds of hours of new videos this summer as part of their site and content revamp. You can pick and choose the videos relevant to the course. They also have X2 speed for twice as fast learning! You can also get access to a virtual machine (VM) to work through code examples though I personally found some of the code to be messy and overdeveloped for what I needed - stick to the videos.

java.boot.by: This is an excellent (and free) resource from Mikalai Zaikin who also hosts guides on many many other exams. His well researched descriptions and code examples are a great addition to any study plans. Additionally you can purchase questions with detailed answers from Mikalai for a very low fee.

OCP Oracle Certified Professional Java SE 11 Developer Complete Study Guide: Exam 1Z0-815, Exam 1Z0-816, and Exam 1Z0-817: As you can tell from the lengthy name this book claims to cover all three Java exams and it does it very well. Scott Selikoff and Jeanne Boyarsky's writing style is very conversational, making even the more complicated subjects simple via their more human step by step guidance. Buying the book also gives you access to 500 flashcards (meh) and over 800 exam questions via the Wiley site. These questions are much more difficult than the actual exam, with longer code examples and more choices. I read this book with the Kindle App which has a great note taking feature via highlights which I found invaluable when cramming on exam eve and exam morning.

How long you need to prepare depends on how dedicated you are. The Java Uni videos can be sped up and the book could be blitzed a chapter or two a day. My only recommendation is have more than one source for revision for a deeper understanding on any area and to ensure nothing is missed.

Taking the exam

This was the first exam I've taken at home. You need to make sure you personal computer can run the test software (PearsonVue). On exam day you will need to take photos of your workspace from all angles, plus yourself and a form of identity. Your web cam will be on for the duration of the exam but you soon forget it as you focus on the questions. Make sure no one interupts or enters the room to avoid it being thrown out. They also disallow you from reading the questions outloud. If you want to make notes or write anything down the software includes a whiteboard.

Exam difficulty

The pass mark is 61% so you need at most 49 correct from the 80 questions. With 180 minutes there is no chance you will run out of time. I passed the exam with 89% with well over an hour to spare.

I read through the resources cited above (much of it multiple times) so I was very prepared. Many questions regarding var, the new interface methods (i.e. default, static and private), how to write functional interfaces (Single Abstract Methods - SAM) and lambdas are based on rules. If you know the rules then you can eliminate wrong answers really really fast. Questions regarding the interfaces in java.util.function and the modular service provider pattern will take longer to analyse. You need to know the functional interfaces SAMs - particularly what parameters they take and what they return. You need to know the service provider pattern well so you can identify the module from minor clues. Again, if you do the preparation you'll be fine. Watch out for questions that look out of place such as a question on Threads. These are often subtly hiding a more relevant issue with the code such as a lambda issue or var misuse.


Finally, I took a lot of notes and created a lot of example code. It is available on my GitHub site.

Thursday, 21 November 2019

Compiling JAXB and JAX-WS classes with Maven in Java 11

Due to the deprecation of EE modules from SE, migrating projects to Java 11 can be somewhat trickier when you rely on Maven to compile your JAXB or JAX-WS classes. See https://jaxenter.com/jdk-11-java-ee-modules-140674.html for more information.

Here's how I got round the issues:

Dependencies


These were either the latest at time of writing, or the version that happened to work. Always check Maven Repository before throwing in dependencies - there may be a better version out there.

<javax.activation.version>1.1.1</javax.activation.version>
<jaxb-api.version>2.3.1</jaxb-api.version>
<jaxb-runtime.version>2.3.2</jaxb-runtime.version>
<jaxb2.maven.version>2.5.0</jaxb2.maven.version>
<jaxws.tools.version>2.3.2</jaxws.tools.version>

<dependency>
<groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>${javax.activation.version}</version>
</dependency>
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>${jaxb-api.version}</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>${jaxb-runtime.version}</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-tools</artifactId>
    <version>${jaxws.tools.version}</version>
    <scope>compile</scope>
</dependency>

JAXB


Our legacy application was using the following dependencies from org.jvnet.jaxb2 to generate the classes based on the xsds/xjc:

<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.12.2</version>

<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>0.6.4</version>

I won't go into detail as to how we configured those as it's not relevant here. Importantly, even by upgrading the versions, at time of writing, these simply do not work in Java 11! Here's the working solution which uses an xjc file to create the files. If you don't have one, they are easily created. There are many xjc guides out there.

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>${jaxb2.maven.version}</version>
    <executions>
        <execution>
            <id>mystuff</id>
            <goals>
                <goal>xjc</goal>
            </goals>
            <configuration>
                <sources>
                    <source>src/main/resources/xsd/</source>
                </sources>
                <packageName>my.package.name</packageName>
            </configuration>
        </execution>
    </executions>
</plugin>

JAX-WS


This is a bit different because we need the endpoints as well as the JAXB objects. Essentially we need to call wsimport differently than we would have using the fairly straightforward jaxws-maven-plugin.

<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.4.1</version>

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>${maven.exec.version}</version>
    <executions>
        <execution>
            <id>mkdir</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>exec</goal>
            </goals>
            <configuration>
                <executable>mkdir</executable>
                <arguments>
                    <argument>-pv</argument>
                    <argument>target/generated-sources/wsimport</argument>
                </arguments>
            </configuration>
        </execution>
        <execution>
            <id>mystuff</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>exec</goal>
            </goals>
            <configuration>
                <executable>java</executable>
                <arguments>
                    <argument>-classpath</argument>
                    <classpath/>
                    <argument>com.sun.tools.ws.WsImport</argument>
                    <argument>-extension</argument>
                    <argument>-Xnocompile</argument>
                    <argument>-wsdllocation</argument>
                    <argument>/xsd/file.wsdl</argument>
                    <argument>-s</argument>
                    <argument>target/generated-sources/wsimport</argument>
                    <argument>src/main/resources/xsd/file.wsdl</argument>
                </arguments>
            </configuration>
        </execution>
    </executions>
</plugin>

This plugin literally creates a directory and then calls wsimport from the com.sun.tools.ws.WsImport library.

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>${maven.build.helper.version}</version>
    <executions>
        <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>${project.build.directory}/generated-sources/wsimport/</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

For the code to be picked up use build-helper-maven-plugin as you normally would.

Friday, 14 September 2018

Factorials and Trailing Zeros


Here’s a seemingly impossible and odd query that I’ve been asked in a technical interview:

Question: “How many trailing zeros are there in 126! (factorial)”

At the time I was left stumped and made sure to find out the solution later - so here it is! It turns out there’s a simple solution that works for all numbers.

Answer: 
Firstly, as a quick reminder, a factorial is the product of an integer and the integers below it. For 126! it is: 126 * 125 * 124 * … 3 * 2 * 1
Which can be shown as: n * (n – 1) * (n – 1) * …

Now the solution. The simplest way has three steps, i.e. for number n:
  1. Divide the number n by 5 and write down the quotient. Ignore remainders (if any).
  2. Then divide the quotient by 5 again and again till you get a quotient less than 5.
  3. Add up all the resultant quotients to get the number of zeros in n!
Therefore, for 126! We get to the answer via:

126 / 5 = 25 (Actually 25.2 but we ignore the fraction. Note that 125 / 5 gives us the whole number of 5 – this will be useful in a moment)
25 / 5 = 5
5 / 5 = 1
25 + 5 + 1 = 31 zeros in 126!

This pattern can be shown as:


[ ] indicates only whole numbers; neglect any fractional part in the division process. This pattern may make more sense when we note that 52 is 25 and 53 is 125. The formula technically goes on till infinity but fractions are considered as 0 so do not affect the final result.

For 126! This resulted in [25] + [5] + [1] = 31.

Why does this work? Well, here’s an explanation: We know that a number gets a zero at the end of it if the number has 10 as a factor, e.g. 10 is a factor of 20, 150, and 99990. Also, 5 * 2 = 10, so we need to account for all the products of 5 and 2. However, every other factor is even, so there are far more factors of 2 than 5 - As such, we have to count the number of factors divisible by 5. To phrase it differently, there are many more numbers that are multiples of 2 (2, 4, 6, 8, 10, 12, 14, ...) than are multiples of 5 (5, 10, 15, ...). If we were to take all the numbers with 5 as a factor, we'll have way more than enough even numbers to pair with them to get factors of 10 (and another trailing zero on the factorial). Finally, we need to consider numbers which are factors of 5 and count them again, e.g. 25 (which is 5 * 5 or 52), 125 (5 * 5 * 5 or 53), 625 (5 * 5 * 5 * 5 or 54) etc.

To conclude, here is 126! in full (feel free to count the trailing zeros):

23721732428800468856771473051394170805702085973808045661837377170052497697783313457227249544076486314839447086187187275319400401837013955325179315652376928996065123321190898603130880000000000000000000000000000000

The approximate value is: 2.37217324288E+211



Sunday, 2 September 2018

Cleaner code - Comments

I truly believe that if the code is written well enough, comments should not be required at all. Not all comments are bad. They can be useful, i.e. they add additional details, information, caveats or provide example inputs (e.g. good/bad inputs for complex regex). Sadly, most of the time comments are put in with little thought, added automatically and are not kept up to date. It has become a bug-bear of mine and this nonsense has to stop! The following are the types of comments that bug me the most!

Bad comments
Comments should be informative, explain the intent or clarify what the code is doing. Sadly this is not always the case. Please be on guard to remove these variances of bad commenting:
Journal comments
We don't need to document when code was created, last updated or by whom. That's what versioning systems are for.
* Changes (from 11-Oct-2001)
* --------------------------
* 11-Oct-2001 : Re-organised the class and moved it to new package
*               com.jrefinery.date (DG);
* 05-Nov-2001 : Added a getDescription() method, and eliminated NotableDate
*               class (DG);
* 12-Nov-2001 : IBD requires setDescription() method, now that NotableDate
*               class is gone (DG);  Changed getPreviousDayOfWeek(),
*               getFollowingDayOfWeek() and getNearestDayOfWeek() to correct
*               bugs (DG);
Attributions and Bylines
/* Added by Rick */
Thanks Rick. Remove anything like this.
Noise / Redundant comments
Sometimes you see comments that are nothing but noise. They restate the obvious and provide no new information.
/**
  * Returns the day of the month.
  *
  * @return the day of the month.
  */
 public int getDayOfMonth() {
   return dayOfMonth;
}
Consider what purpose does the comment serve. If it’s not more informative than the code, remove.
Misleading comments
These are possibly the worst kind as they may state a fact about the code that may have been true once but is now false. Too often the comments get separated from the code they describe and become orphaned blurbs of ever-decreasing accuracy.
JavaDocs in Nonpublic code
Javadocs are useful for public APIs. Generating Javadoc pages for the classes and functions inside a system is not generally useful, and the extra formality of the Javadoc comments amounts to little more than a distraction. Comments like this just clutter up the code, propagate lies, and lend to general confusion and disorganization.

Friday, 24 August 2018

Print the content of a JavaScript object

I was working on an Eclipse plugin based on a 3rd party API. One feature of their API I used allowed me to display a HTML page in a window. Sadly, within the applications frame, the page is impossible to debug with modern browser tools (e.g. FireBug in FireFox or DevTools in Chrome). I needed a different way to debug the JavaScript Objects I had on the page. Here is the useful solution which ending up helping me:

function printObject(o) {
  var out = '';
  for (var p in o) {
    out += p + ': ' + o[p] + '\n';
  }
  alert(out);
}

// test:
var myObject = {'something': 1, 'other thing': 2};
printObject(myObject);

Here we can access all the elements of an object using a foreach loop. The printObject function alert()s the object showing all properties and respective values.

Wednesday, 19 June 2013

Oracle Serive Bus: Get file name from proxy service

The following is how to get the file name of a file that is being processed by a proxy service in OSB.

1. We can get the URI via the $inbound context variable with the following XPath:
$inbound/ctx:transport/ctx:request/tp:headers/file:fileName

This results in:
<file:fileName
xmlns:file="http://www.bea.com/wli/sb/transports/file">
c:\temp\input\2635978486281_
test.xml</file:fileName>

2. To get the filename only, use the tokenize function (which returns the characters after the last "\\":
tokenize($inbound/ctx:transport/ctx:request/tp:headers/file:fileName, "\\")[last()]

Tuesday, 18 June 2013

Auto increment primary key with Oracle Databases

Suppose you have a database and you want each entry to be identified by a unique number. This can be achieved easily in MySQL by specifying "auto_increment" for the column, but Oracle requires a little bit of extra work to get this done.

One way to do it is by creating two database objects, a sequence and a trigger:

1. As a simple example, imagine we have a table called "tbl_test" with two columns, "test_id" and "test_data".
create table tbl_test (test_id number, test_data varchar2(145)); 

 2. Now, we create a sequence for the test_id column. Note that the numbering starts with 1 and is incremented by 1.
create sequence seq_test 
start with 1 
increment by 1 
nomaxvalue; 

3. Next we create the trigger that will automatically insert the next number from the sequence into the test_id column.
create trigger tgr_test 
before insert on tbl_test 
for each row 
begin 
select seq_test.nextval into :new.test_id from dual; 
end;
/