tag:blogger.com,1999:blog-25617039154462815532024-03-28T22:35:53.704-07:00Matt Greencroft's BlogMatt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-2561703915446281553.post-44555467469964897552017-07-04T05:44:00.003-07:002017-07-04T05:44:54.267-07:00Java Advanced Tools - Errata for Thread Safety<div class="MsoNormal">
In Chapter 20 of the <a href="https://www.virtualpairprogrammers.com/training-courses/Java-Advanced-Topics-training.html" target="_blank">Java Advanced Topics</a> course (the video
on Synchronization and Thread Safety), at about 20 mins 15 seconds, I explain
that you tend to use the synchronized keyword with the smallest possible code
block. I demonstrate this with the following code:<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkIhgvRKMbIOrPX9Rn_rm0YqoflEox-gttSrnXlctSPoA3AelhEctSN-JO-8yX4NYEVck6lICw_6bQYWDOAGW8ThaEqGWoBG1ytVqeusLe1kfi1c91SmoYAtjGdKR9dw5tDzl2W-QseMA/s1600/jat-thread-screen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="519" data-original-width="811" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkIhgvRKMbIOrPX9Rn_rm0YqoflEox-gttSrnXlctSPoA3AelhEctSN-JO-8yX4NYEVck6lICw_6bQYWDOAGW8ThaEqGWoBG1ytVqeusLe1kfi1c91SmoYAtjGdKR9dw5tDzl2W-QseMA/s400/jat-thread-screen.png" width="400" /></a></div>
<span id="goog_1539939516"></span><span id="goog_1539939517"></span><br />
<div class="MsoNormal">
Unfortunately, for the example we have been looking at, this
wouldn’t be thread safe! It would be possible, if a thread was interrupted
after the synchronized block, but before the return statement, for 2 threads to
be given the same number.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
Thank you to one of our customers who pointed this out today
– the synchronized keyword needs to be around the minimum part of the code that
should not be interrupted. In this example it would need to be the entire
method. <o:p></o:p></div>
</div>
Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com4tag:blogger.com,1999:blog-2561703915446281553.post-9122655110661995962017-06-21T03:06:00.000-07:002017-06-21T03:06:02.569-07:00Java 9 – custom Runtimes… would you actually use them?<div class="MsoNormal">
Last month I posted about the issues
affecting the Jigsaw (modular Java) features within Java 9. As we approach the
release of Java 9 (which we currently expect to be at the end of July, but who
knows if it will be delayed again?), this time I thought I should talk about one
of the other features of Java 9, creating your own custom Java Runtime
Environments.</div>
<div class="MsoNormal">
<span lang="EN-US"><br />
The idea is that the Java Runtime Environment (JRE) has been split into a
number of modules in Java 9 (see the last blog post for details about what we
mean by modules). So when you build your own applications, the users who will
run them don’t necessarily need the entire JRE, but could use a cut-down version.
I’ll talk in a paragraph or so about why
you might want to do this.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US">The process to create a cut down version,
containing only the parts of the JRE that are needed for your application looks
quite straightforward (I saw a demo of this at the recent London Java User
Group hackday) but two points did stick …<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoListParagraphCxSpFirst" style="mso-list: l0 level1 lfo1; text-indent: -18.0pt;">
<!--[if !supportLists]--><span lang="EN-US">1.<span style="font-size: 7pt; font-stretch: normal; font-variant-numeric: normal; line-height: normal;">
</span></span><!--[endif]--><span lang="EN-US">The process to create a
cut-down version of the JRE uses the JRE installed on the computer being used
to create the new version. So for example if you’re using a Mac, then you can
create a cut-down JRE for the Mac, but if you’re application is going to
potentially be run on a Windows or Linux machine, that’s not going to work.
You’ll need to use a Windows or Linux machine to create compatible cut-down
runtimes for those environments too.<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpLast" style="mso-list: l0 level1 lfo1; text-indent: -18.0pt;">
<!--[if !supportLists]--><span lang="EN-US">2.<span style="font-size: 7pt; font-stretch: normal; font-variant-numeric: normal; line-height: normal;">
</span></span><!--[endif]--><span lang="EN-US">Once you have created the new
runtime, there’s no easy way to distribute it – what you are effectively
creating is a folder with lots of sub-folders and files in… but you’ll need to
provide all of these to your users with some instructions on what to do with
them (such as creating the environment variables). The system (at least for
now) doesn’t create a nice user-friendly installer for your cut-down JRE.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US">In practice this almost certainly means
that you won’t be creating cut-down JREs for applications which you plan to
sell to the general public… you’re more likely to do it only where you are deploying
to hardware that you have control of. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US">That probably makes sense, as for most
users there is no obvious need for a cut-down JRE – the main benefits of a reduced
JRE would be lower storage requirements (where disk space is limited) and
possibly reduced memory requirements (e.g. in an embedded device where RAM is
limited). If you’re creating an application to run on an embedded device, and
so you know the specific hardware, and operating system that needs to be
targeted, and that this won’t be generally accessible by the public, then this
could be something you will benefit from. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US">Given the ever lowering cost of storage and
RAM, you might wonder if this is really going to be a sizeable need, although
even in server environments there could be a genuine use case. If you’re creating
microservices, that are going to run in a cloud platform such as Amazon’s AWS,
making them as “lightweight” as possible, so that you can get reasonable
performance from the cheaper, lower spec EC2 instances, might deliver some
considerable cost savings. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US">Another issue which may crop up from this
is what happens when the Java runtime needs updating with security patches etc.
Will the developer need to continually create new versions of their runtime for
distribution? If so then systems with a reliance on developers to provide a
patch for a security issue in a JRE sounds like a real potential for disaster!<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US">Initially my reaction to all this was that
this will be another feature of Java which very few people will want or use,
but I’m now wondering if this actually presents an opportunity for a service to
come along and make this useful…. <o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-US">I suspect in due course we’ll see a
“centralized custom JRE service”. Developers can register their applications
and tell the centralized service which modules within the JRE their application
needs. The centralized service can then create custom installers of the
cut-down JRE for various platforms, and the developer can tell their customers
to click on a personal link to download and install that JRE.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US">Then when security patches are released,
whereas Oracle’s standard Java calls home to Oracle to find out about updates,
the custom JREs could call home to the centralized service and get their
updates from there.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<span lang="EN-US">I’m sure I’m not the first person to think
of this, so I won’t claim copyright (or royalties if you have a go at
implementing the idea) but it does feel like something like this would make the
idea of custom JREs actually useable… maybe something for an enterprising
startup to consider in due course?<o:p></o:p></span></div>
Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com0tag:blogger.com,1999:blog-2561703915446281553.post-19864209061516480732017-05-11T09:25:00.000-07:002017-05-11T09:25:00.081-07:00The latest on Java 9... will it be delayed, features removed, or released with problems? <div class="MsoNormal">
<span style="font-size: 12pt;">In case you’ve not been following the progress of the next
release of Java SE,</span><span style="font-size: 12pt;"> </span><span style="font-size: 12pt;">Java 9, we thought
we should let you know what the current status is (or at least our current
understanding of it!).</span></div>
<div class="MsoNormal">
<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
As you might expect, the next version of Java will have some
changes in it from the earlier versions. By far the biggest, is the
introduction of Jigsaw, an API for building modular applications. Some have
described this as a bigger change for Java than when generics were introduced
back in Java 5.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If you’re not familiar with modular applications, then in
simple terms the idea is that you can split larger applications into smaller
parts (modules). Each module can depend on / use other modules, but they’re
built as separate projects, and compiled into separate Jar files. There are
quite a few potential benefits to this approach, but perhaps the most useful is
that if you need to change a single module, you can do that without needing to
amend or recompile any of the other modules. There's more to it than this, but that's a very simple high level overview.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If this sounds familiar (you may be thinking about
microservices) well it’s another way of solving the same problem that
microservices solves, at least in terms of building smaller, more manageable
applications rather than monoliths.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Actually if you have a need for modular Java right now, then
you don’t need to wait for Jigsaw – the OSGi framework (<a href="https://www.osgi.org/">https://www.osgi.org/</a>) provides this today,
and although I've never used it personally, everyone I have met who has say it works well.
Unfortunately Jigsaw isn’t compatible with OSGi… I guess there are some
politics involved as to why they didn’t adopt OSGi as the standard!<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
So that’s the background… what’s the current status?<o:p></o:p></div>
<div class="MsoNormal">
<br />
Well Jigsaw is having some problems. I have tried using it myself, with the
current beta release of the Java 9 JDK. I thought it might be an interesting and useful exercise to take an internal Spring Boot based application that we use at Virtual Pair Programmers, and upgrade it to make it modular.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Unfortunately I ran into some problems doing this,
including:</div>
<div class="MsoNormal">
</div>
<ul>
<li>Maven doesn’t work with Jigsaw right now. So if
you want to build a set of modular Spring Boot applications, for example, well
it’s possible in theory but highly frustrating in practice…. it involves writing a number of shell scripts and delving into the file system to work out where all the maven dependency jars have been put, so that you can reference them in your compilation scripts.</li>
<li>Eclipse doesn’t really cope well with Modular
projects right now. It can be used to edit them (although you’ll do some frustrating manual
moving around of the file structure to get it to work) but you can’t currently
create a modular Jar / War file from Eclipse. Again you'll end up writing shell scripts to do these. We understand that other IDEs
have similar issues.</li>
</ul>
<br />
<div class="MsoListParagraphCxSpLast" style="mso-list: l0 level1 lfo1; text-indent: -18.0pt;">
<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
This means that today, Jigsaw is really not ready for
use.<span style="mso-spacerun: yes;"> </span>We recently attended the London
Java User Group’s hackday to get an introduction to Java 9, and certainly left
there with a feeling that the modular approach is going to take some getting
used to… and without full integration with familiar build tools and IDEs, it
won’t get widely adopted. <o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
It seems that more widely within the Java community our view
that Jigsaw isn’t ready is shared… and not just for the reasons we have come across. Currently 13
of the 23 organisations that have a vote on the Java Committee have voted no to
Jigsaw being ready to release (<a href="https://jcp.org/en/jsr/results?id=5959">https://jcp.org/en/jsr/results?id=5959</a>).
<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<!--[if gte mso 9]><xml>
<o:DocumentProperties>
<o:Revision>0</o:Revision>
<o:TotalTime>0</o:TotalTime>
<o:Pages>1</o:Pages>
<o:Words>483</o:Words>
<o:Characters>2758</o:Characters>
<o:Company>Multihost Ltd</o:Company>
<o:Lines>22</o:Lines>
<o:Paragraphs>6</o:Paragraphs>
<o:CharactersWithSpaces>3235</o:CharactersWithSpaces>
<o:Version>14.0</o:Version>
</o:DocumentProperties>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]-->
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>JA</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
<w:UseFELayout/>
</w:Compatibility>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="276">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]-->
<style>
<!--
/* Font Definitions */
@font-face
{font-family:"Courier New";
panose-1:2 7 3 9 2 2 5 2 4 4;
mso-font-charset:0;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:-536859905 -1073711037 9 0 511 0;}
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;
mso-font-charset:2;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:0 268435456 0 0 -2147483648 0;}
@font-face
{font-family:"MS 明朝";
mso-font-charset:78;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:1 134676480 16 0 131072 0;}
@font-face
{font-family:"MS 明朝";
mso-font-charset:78;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:1 134676480 16 0 131072 0;}
@font-face
{font-family:Cambria;
panose-1:2 4 5 3 5 4 6 3 2 4;
mso-font-charset:0;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:-536870145 1073743103 0 0 415 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:Cambria;
mso-ascii-font-family:Cambria;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"MS 明朝";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Cambria;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
mso-themecolor:hyperlink;
text-decoration:underline;
text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-noshow:yes;
mso-style-priority:99;
color:purple;
mso-themecolor:followedhyperlink;
text-decoration:underline;
text-underline:single;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{mso-style-priority:34;
mso-style-unhide:no;
mso-style-qformat:yes;
margin-top:0cm;
margin-right:0cm;
margin-bottom:0cm;
margin-left:36.0pt;
margin-bottom:.0001pt;
mso-add-space:auto;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:Cambria;
mso-ascii-font-family:Cambria;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"MS 明朝";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Cambria;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst
{mso-style-priority:34;
mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-type:export-only;
margin-top:0cm;
margin-right:0cm;
margin-bottom:0cm;
margin-left:36.0pt;
margin-bottom:.0001pt;
mso-add-space:auto;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:Cambria;
mso-ascii-font-family:Cambria;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"MS 明朝";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Cambria;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle
{mso-style-priority:34;
mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-type:export-only;
margin-top:0cm;
margin-right:0cm;
margin-bottom:0cm;
margin-left:36.0pt;
margin-bottom:.0001pt;
mso-add-space:auto;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:Cambria;
mso-ascii-font-family:Cambria;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"MS 明朝";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Cambria;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast
{mso-style-priority:34;
mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-type:export-only;
margin-top:0cm;
margin-right:0cm;
margin-bottom:0cm;
margin-left:36.0pt;
margin-bottom:.0001pt;
mso-add-space:auto;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:Cambria;
mso-ascii-font-family:Cambria;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"MS 明朝";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Cambria;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
font-family:Cambria;
mso-ascii-font-family:Cambria;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"MS 明朝";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Cambria;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
@page WordSection1
{size:595.0pt 842.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:35.4pt;
mso-footer-margin:35.4pt;
mso-paper-source:0;}
div.WordSection1
{page:WordSection1;}
/* List Definitions */
@list l0
{mso-list-id:507522835;
mso-list-type:hybrid;
mso-list-template-ids:1860324762 67698689 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l0:level1
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;
font-family:Symbol;}
@list l0:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;
font-family:"Courier New";
mso-bidi-font-family:"Times New Roman";}
@list l0:level3
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;
font-family:Wingdings;}
@list l0:level4
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;
font-family:Symbol;}
@list l0:level5
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;
font-family:"Courier New";
mso-bidi-font-family:"Times New Roman";}
@list l0:level6
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;
font-family:Wingdings;}
@list l0:level7
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;
font-family:Symbol;}
@list l0:level8
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;
font-family:"Courier New";
mso-bidi-font-family:"Times New Roman";}
@list l0:level9
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;
font-family:Wingdings;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
</style>
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:Cambria;
mso-ascii-font-family:Cambria;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Cambria;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<!--StartFragment-->
<!--EndFragment--><br />
<div class="MsoNormal">
Currently Java 9 is scheduled for release on July 27 2017.
Whether it gets delayed, it gets released without Jigsaw, or the Jigsaw issues
get sufficiently fixed in time, we’ll have to wait to see!</div>
Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com0tag:blogger.com,1999:blog-2561703915446281553.post-71547729847169678832017-05-08T09:01:00.000-07:002017-05-11T09:02:07.303-07:00Installing Groovy - which version to go for?Since we released the Groovy course, there have been some changes to the hosting of the Groovy distribution files. The newer versions of Groovy are completely compatible with the course, so you're fine to use any, but you'll need to download them from:<br />
<br />
http://groovy-lang.org/download.html<br />
<br />
Please note that for Windows users, the latest version may not have a windows installer available. To get started quickly you may wish to check a prior version with a Windows installer. At the time of creating this blog post, 2.4.11 is the latest stable version of Groovy, but if you want the Windows installer you'll need to get 2.4.10.<br />
<br />
We also mention in this course that at the time of recording we were planning a course on Grails. We held off for the release of Grails 3, we knew that each version of Grails tends to break something in earlier versions / is not always backwards compatible. Unfortunately the Grails project has lost popularity in recent years (mainly due to political reasons I believe) and so a course on Grails has not been a viable option.<br />
<br />
However for fans of the Groovy language, it's perfectly possible to create Spring Boot applications in Groovy - and indeed this is effectively where Grails was heading anyway. So Combining Groovy and our Spring MVC / Spring Boot courses will allow you to build production quality web applications in Groovy... and that's our recommended way forward!Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com1tag:blogger.com,1999:blog-2561703915446281553.post-37022991028671001712017-05-07T18:01:00.000-07:002017-05-11T08:54:06.880-07:00Errata for Hadoop course - Installing Java with UbuntuIn chapter 4 of the Hadoop course we set up a new Virtual Machine, running Linux. This step is not needed if you're already using Linux or a Mac to run the course, but is needed for Windows users.<br />
<br />
In the course we install the Java JDK version 7. However this is no longer available from the repositories, and you'll now need to use Java version 8. We've tested the course with this version of Java and are not aware of any issues.<br />
<br />
To install Java version 8 issue the following command:<br />
<br />
sudo apt-get install openjdk-8-jre-headless<br />
<br />
instead of<br />
<br />
sudo apt-get install openjdk-7-jreMatt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com3tag:blogger.com,1999:blog-2561703915446281553.post-27242613810610530952017-04-27T13:36:00.000-07:002017-05-11T08:46:56.671-07:00Errata - Java EE Module 1, Chapter 6We've recently been made aware of a small issue which affects chapter 6 (the CDI chapter) of Java EE with Wildfly, Module 1. You might experience this issue if you're using some versions of Java 8 to create your project - we're aware it is a problem in Java 8.60 and above.<br />
<br />
In the video we talk about the different ways to tell JavaEE which implementation of a particular interface should be injected at runtime, when multiple implementations exist in your project. We first demonstrate the @Default and @Alternative annotations, then we look at specifying the required implementation in beans.xml, and finally we discuss qualifiers, which allow us to specify a different implementation in one specific area of our code.<br />
<br />
In the video, we end up with all 3 methods in our project in use at the same time, and this worked fine at the time of recording. However we have found that when you then add in your own custom annotations (such as @ProductionDao - the example we use in the video) the deployment might fail. It appears that there is a bug in Java 8 which means that you can't use custom annotations together with beans.xml.<br />
<br />
So you are fine to use @Default and custom annotations together, but not beans.xml and custom annotations. As most users will agree that using @Default and @Alternative are much easier than editing the xml file, this probably won't cause much difficulty in practice, but if you are getting a message that the build has failed, this will be why. If you're following along with the chapter, simply remove beans.xml from your project, and you will be able to continue with no further issues.Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com8tag:blogger.com,1999:blog-2561703915446281553.post-78625992122427663472017-03-05T09:04:00.000-08:002017-05-11T09:05:38.713-07:00Why I have never attempted to teach JavaScript...<span style="background-color: white; color: #1d2129; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px;">It must be time for the "which is the best programming language" debate again... Here's an interesting article that claims "Jobs-wise, you’d be hard-pressed to find a better language than Java as your primary programming language" - that does seem to reflect the reality we see... actually the comments are even more fascinating than the article! </span><br />
<br style="background-color: white; color: #1d2129; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px;" /><a href="http://www.theregister.co.uk/2017/03/03/pizza_roaches_and_java/" rel="nofollow noopener" style="background-color: white; color: #365899; cursor: pointer; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; text-decoration-line: none;" target="_blank">http://www.theregister.co.uk/…/03/03/pizza_roaches_and_java/</a>Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com0tag:blogger.com,1999:blog-2561703915446281553.post-69119977712543953282016-10-17T09:07:00.000-07:002017-05-11T09:08:45.789-07:00Unsatisfied Dependencies in Spring Boot 1.4?My colleague, Richard Chesterwood has just posted on his blog about a problem with Spring Boot 1.4... if you're getting an issue with unsatisfied dependencies, check it out:<br />
<br />
<a href="https://richardchesterwood.blogspot.co.uk/2016/10/spring-boot-crashing-due-to-unsatisfied.html">https://richardchesterwood.blogspot.co.uk/2016/10/spring-boot-crashing-due-to-unsatisfied.html</a>Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com1tag:blogger.com,1999:blog-2561703915446281553.post-9626444889578992992016-08-23T02:00:00.000-07:002017-05-11T09:10:35.526-07:00Tomcat problems with Java 8<div style="background-color: white; color: #1d2129; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; margin-bottom: 6px;">
If you're doing any of our courses that use Tomcat, be aware that the latest update to Java 8 (1.8.0_91) seems to have broken JSP compilations for all versions of Tomcat up to and including 8. We're not sure why this is happening, but as a quick fix either use Java 1.8.0_77 or earlier, OR use Tomcat 9 which is confirmed to fully support Java 8.</div>
<div style="background-color: white; color: #1d2129; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; margin-bottom: 6px; margin-top: 6px;">
(Note that Tomcat 9 is still in Alpha, so doing this carries some risk - the safest choice is to use an earlier Java).</div>
<div style="background-color: white; color: #1d2129; display: inline; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; margin-top: 6px;">
Thanks to all those who have reported this, and you can also follow a Stackoverflow post at <a href="http://stackoverflow.com/questions/36956912/spring-mvc-unable-to-compile-class-for-jsp" rel="nofollow noopener" style="color: #365899; cursor: pointer; font-family: inherit; text-decoration-line: none;" target="_blank">http://stackoverflow.com/…/spring-mvc-unable-to-compile-cla…</a></div>
Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com0tag:blogger.com,1999:blog-2561703915446281553.post-88392101533875084392015-03-26T05:51:00.000-07:002015-03-26T05:51:13.143-07:00Java Advanced Course now live!Today's an exciting day - we've just put the <a href="https://www.virtualpairprogrammers.com/training-courses/Java-Advanced-Topics-training.html" target="_blank">Java : Advanced Topics course</a> live on the Virtual Pair Programmers' website.<br />
<br />
I'm really pleased with this course - I think it is going to be really helpful to lots of Java developers - it covers topics which you don't tend to learn about in most Java courses as they are that bit more advanced, but are vital for really good Java developers to know about<br />
<br />For example, we go into depth on how the LinkedHashMap actually works, what can go wrong when you're writing multi-threaded apps, and how to avoid it, and even how to load-test your application so that you can be sure it won't run out of memory when you put it onto the production server!<br />
<br />
I hope you enjoy it!Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com29tag:blogger.com,1999:blog-2561703915446281553.post-52035284376987175742015-02-09T02:04:00.003-08:002015-02-09T02:04:54.936-08:00An update on Hadoop VersionsOur popular <a href="https://www.virtualpairprogrammers.com/training-courses/Hadoop-for-Java-Developers-training.html" target="_blank">Hadoop for Java Developers</a> course was recorded using version 2.4.0 of Hadoop. Since the course was released there have been some further releases of Hadoop, with the current version being 2.6.0.<br />
<br />
There are no differences in the content that we cover on the course between the two versions of Hadoop, so the course is completely valid if you wish to use 2.6.0 or 2.4.0. In this blog post, however, I want to point out a reason to stick with version 2.4.0, and a couple of pointers that you should be aware of if you are going to use 2.6.0. I'll also mention the process to upgrade from 2.4.0 to 2.6.0.<br />
<br />
<b>Which Version of Hadoop should I use?</b><br />
<br />
If you're starting to develop with Hadoop today then you might just want to download the latest version from the Hadoop website (2.6.0) and there is only really one reason that I can think of not to do this... and that is that Amazon's Elastic Map Reduce (EMR) service, which can be used to run Hadoop jobs "in the cloud" is not yet compliant with versions of Hadoop newer than 2.4.0.<br />
<br />
Although the code that you'll write on the course is identical in both versions of Hadoop, if you compile your code with the 2.6.0 jar files you'll not be able to run it on EMR. For this reason we suggest you consider sticking with 2.4.0, at least while learning Hadoop, so that you can experience EMR (we cover how to set up and run an EMR job on the course). If you plan to use Hadoop on EMR in a production scenario then you must stick to 2.4.0 until Amazon update the EMR service to work with newer versions.<br />
<br />
You can download a copy of version 2.4.0 from <a href="https://archive.apache.org/dist/hadoop/core/hadoop-2.4.0/" target="_blank">this link</a>.<br />
<br />
<br />
<b>If I am going to use 2.6.0, what do I need to know?</b><br />
<br />
The only things to be aware of if you wish to study the course with version 2.6.0 of Hadoop are:<br />
<br />
(1) Your standard installation path will be opt/hadoop-2.6.0/ instead of /opt/hadoop-2.4.0/ so you'll want to change the references to that in the following two script files that are provided with the course:<br />
startHadoopPseudo<br />
startHadoopStandalone<br />
<br />
(2) When you install hadoop, you'll edit either .bashrc or .profile - make sure you also put the reference to the correct folder name in here also. Also, you'll be creating symbolic links to the Hadoop configurations - again make sure you use the correct folder names when you set these up.<br />
<br />
<br />
<b>What happens if I want to upgrade from 2.4.0 to 2.6.0?</b><br />
<br />
If you have been running with 2.4.0 and wish to upgrade to 2.6.0, you just need to do the following:<br />
<br />
(1) Download and unpack the 2.6.0 files from the Hadoop website - place these in /opt/hadoop-2.6.0/<br />
(2) Create the configuration folders under /opt/hadoop-2.6.0/etc as you did for Hadoop 2.4.0 (you can actually copy the configuration folders from your 2.4.0 installation as they'll be valid for 2.6.0)<br />
(3) edit your .bashrc (linux) or .bash_profile (Mac) to change the location of the Hadoop files in the HADOOP_PREFIX and PATH variables from 2.4.0 to 2.6.0<br />
(4) Close your terminal window and open a new one to ensure that the updated environment variables and path varaible are loaded.<br />
(5) run the script resetHDFS - you must be in the Scripts directory to run this script - this will reformat the HDFS file system and will create the symbolic links needed to use the Pseudo configuration. After running this script, enter the JPS command and check that you have the various daemons running (namenode, datanode etc)<br />
(6) Your code, compiled with 2.4.0 will work in 2.6.0 - if you wish to recompile with 2.6.0, remove all the Hadoop jar files from the build path, and then re-add them from the folders under /opt/hadoop/2.6.0/share/hadoopMatt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com2tag:blogger.com,1999:blog-2561703915446281553.post-80350189783616651202014-12-01T09:55:00.001-08:002014-12-01T09:55:43.034-08:00Java 8 Time - choosing the right objectIn the last blog post, we looked at the java.time library’s Instant and Duration objects in Java 8. In this second post, we’ll get an overview of some of the other objects within the java.time libraries.<br />
<br />
The Instant object is defined in the JavaDocs as “An instantaneous point on the time-line.” There are other objects, related to the Instant, that might also be useful to us – in particular LocalDateTime, LocalDate and LocalTime and ZonedDateTime.<br />
<br />
I’ll ignore LocalDate and LocalTime for the moment, and consider LocalDateTime, ZonedDateTime and Instant... all three of these appear to be quite similar, so it’s worth understanding how each differs.<br />
<h3>
What's the time?</h3>
A good starting place is to instantiate each object type with it’s now() method, to get the current time, and to print these out to the console to see what the print formats look like.. the code to do this is shown here, with the output below:<br />
<br />
<pre class="brush:java">Instant instNow = Instant.now();
LocalDateTime ldtNow = LocalDateTime.now();
ZonedDateTime zdtNow = ZonedDateTime.now();
System.out.println(instNow);
System.out.println(ldtNow);
System.out.println(zdtNow);</pre>
<br />
<span style="font-family: Courier New, Courier, monospace;"><span style="color: blue;">2014-12-01T15:18:31.094Z<br />
2014-12-01T15:18:31.109<br />
2014-12-01T15:18:31.152Z[Europe/London]<br />
</span></span><br />
<br />
Ignoring the nano second differences, the formats are interesting. The first, the Instant tells us that this code was ran at 3.18pm on 1st December 2014. The letter z at the end stands for Zulu time, which is also known as GMT (Grenwich Mean Time) or UTC (which stands for Coordinated Universal Time… I don’t know why it’s not abbreviated to CUT – I’ll leave you go to go searching on Wikipedia if you want to know more about this!) So the first item, the Instant, is 3.18pm on 1st December 2014 UTC.<br />
<br />
The second result is the local date time – that’s a representation of my current time, which is 3.18pm on 1st December 2014, that's what my computer clock and calendar say. And the third item is the zoned date time, where we can again see that it’s 3.18pm on 1st December 2014, London time. <br />
<br />
This all looks very neat because I’m in the UK, where the timezone is GMT (at least in Winter)… what would have happened if I was somewhere else in the world?<br />
<br />
Well here’s what a person in Abu Dhabi who tried the same exercise would find...<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><span style="color: blue;">2014-12-01T15:18:31.094Z<br />
2014-12-01T19:18:31.109<br />
2014-12-01T19:18:31.152+04:00[Asia/Muscat]<br />
<br />
</span></span><br />
So now we can see that the Instant is the same point on the timescale as the person in London found, but their LocalDateTime was the time their clock shows (4 hours later than the person in London’s clock) and the ZonedDateTime matches the LocalDateTime but it has the time-zone embedded in.<br />
<br />
Let’s dig a little deeper into the definitions of these objects…<br />
<br />
An Instant is an actual point in time, expressed using UTC – a universal time scale. A ZonedDateTime is an actual point in time, but in a specific area of the world... so if you know the timezone you can convert reliably from an Instant to a ZonedDateTime. A LocalDateTime is a <i>representation </i>of the <i>concept </i>of a date and time, but doesn’t actually correspond to an actual point in time… or rather it can only be converted into an actual point in time if we ADD IN a timezone.<br />
<br />
Although LocalDateTime objects don’t necessarily correspond to an actual point in time, you can still do all the “date mathematics” you might want to with them, such as adding or subtracting days, minutes or nanoseconds.<br />
<h3>
Ok so how is this useful?</h3>
If you’re writing code that is going to manipulate dates, you now have a choice of what to use. In the United Kingdom, our clocks go forward for an hour in the summer, (known as daylight saving) so at some times in the year we are effectively operating at GMT and sometimes it’s GMT+1. <br />
<br />
This could cause confusion on the dates the clocks go back an hour from GMT+1 to GMT... the change happens at 2am – this year it was on Sunday October 26th. What this means is that if I looked at my digital clock, the minutes on Sunday 26th October changed like this…<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><span style="color: red;">01:58<br />
01:59<br />
01:00<br />
01:01<br />
</span></span>
<br />
<span style="font-family: Courier New, Courier, monospace;"><span style="color: red;"><br /></span></span>
As a result, the time 01:30am happened <b>twice </b>on 26th October…. At least as far as my clock is concerned. But my clock operates on LocalDateTime (or it would if it were running Java) – if I had an InstantClock it would have looked like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><span style="color: red;">00:58<br />
00:59<br />
01:00<br />
01:01<br />
</span></span>
<br />
<span style="font-family: Courier New, Courier, monospace;"><span style="color: red;"><br /></span></span>
And if had a ZonedDateTime clock it might have looked like this:
<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><span style="color: red;">01:58 BST<br />
01:59 BST<br />
01:00 GMT<br />
01:01 GMT<br />
</span></span>
<br />
<br />
(BST stands for British Summer Time – it’s another way of saying GMT+1)<br />
<br />
Now let’s suppose we were writing code that was going to run a critical piece of functionality each night at 1.30am. For example, maybe we are a bank, and it’s at 1.30am that our function starts that is going to calculate the daily interest on every customer's account. It would be important <b>not </b>to use a LocalDateTime object for this code, as it might run twice on 26th October (and not at all on 30th March 2014, the date that the clocks skipped an hour). In this example, I’d want to use an Instant - I want my critical process to run at fixed times on the time-line. <br />
<br />
In fact if I was coding up a system for a bank, that was recording every transaction in every account, I’d probably want to store the date and time for each transaction as an Instant object… that way I know exactly when it happened…. And because bank transactions can occur between countries, it makes sense to know the date and time of each transaction based on UTC, and then translate that into a local date and time for each country’s reports.<br />
<br />
So if we go on to write another piece of code that details, for example, the number of transactions by hour while the bank was open each day, for this we would want to use the ZonedDateTime object, to query transactions between fixed times in each location… this can tell us how many transactions occurred between 9am and 10am LOCAL time (the first hour of opening) in each country.<br />
<h3>
LocalDate and LocalTime</h3>
As you might suspect from their names these objects store a date or a time in isolation… and in fact a LocalDateTime is actually a combination of LocalDate and LocalTime… and the LocalDateTime object has a toLocalDate() and toLocalTime() method to easily extract each component. <br />
<br />
Now I think these are particularly useful, well LocalDate is. I often find I want to compare 2 dates ignoring their time values. I’ve traditionally used the Apache Commons DateUtils library in the past to help with this – it has a truncatedCompareTo method which allows you to say compare 2 dates but only consider (for example) the date part, or only consider the year and month.
<br />
<br />
Now you might think that you could do this with the Instant objects... consider this code for example:<br />
<br />
<pre class="brush:java">Instant instant1 = Instant.parse("2014-12-01T16:01:13.419Z");
Instant instant2 = Instant.parse("2014-12-17T15:17:22.305Z");
System.out.println(Duration.between(instant1,instant2).toDays());
</pre>
<br />
Here we have two dates - the 1st December at 4.01pm, and the 17th December at 3.17pm. I'd like to know how many days there are between these two dates, ignoring the times. The answer should be 17 less 1 = 16.<br />
<br />
However the output from my println is... 15. The reason is that there are actually 15 days, 23 hours and 43 minutes between these two dates and our .toDays() method tells us that's 15 days - it ignores the hours and minutes.<br />
<br />
So how do we find out the real number of days, ignoring the time?<br />
<br />
Well here's some code that will do this:<br />
<br />
<pre class="brush:java">Instant instant1 = Instant.parse("2014-12-01T16:01:13.419Z");
Instant instant2 = Instant.parse("2014-12-17T15:17:22.305Z");
LocalDate d1 = LocalDateTime.ofInstant(instant1, ZoneId.systemDefault()).toLocalDate();
LocalDate d2 = LocalDateTime.ofInstant(instant2, ZoneId.systemDefault()).toLocalDate();
System.out.println(Period.between(d1,d2).getDays());</pre>
<br />
In this code, we're taking 2 different Instant objects, converting them into LocalDate objects (note that we need to first convert them to LocalDateTimes... and I've just used the system default's time zone for the conversion), and then looking at how many days there are between the two local dates. We get the answer we're looking for - 16.<br />
<br />
But this introduces another new object - that of the Period. When we compared 2 Instants in the previous blog post, we used the Duration object - well if you try and compare 2 LocalDates with a Duration object you'll find it will compile but you'll get a rather horrible looking UnsupportedTemporalTypeException.<br />
<br />
So I guess we need to finish by understanding what the Period object is...<br />
<h3>
Periods or Durations</h3>
Well the official definition is that whereas the Duration object works with time - that is hours, minutes and seconds, whereas a Period object works with dates - or rather years, months and days. In reality I find you can forget this and just remember that if you're working with LocalDate you must use Period, if you're working with Instant, LocalDateTime, or ZonedDateTime use Duration.<br />
<br />
Admittedly it's not that simple (nothing is really with Java Time) - there's a rather interesting note in the JavaDocs that says that a Duration of 1 day will always be 24 hours, but a period of 1 day might be 23, 24 or 25 hours due to the impacts of daylight saving time changes.<br />
<br />
Confused? yes I am too - I guess until we have all been building lots of code that manipulate dates we won't be completely familiar with which is the best object type to use and when, but I do at least get a sense that the structure of java.time is comprehensive. So far I haven't found any aspect of date manipulation or date mathematics that I can't do with java.time, although it can sometimes take what feels like quite a lot of effort.<br />
<br />
So has Java finally come up with a replacement for Date that works? Well I want to say yes... It's a cautious yes for now but if I'm honest, I like what I'm using!Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com40tag:blogger.com,1999:blog-2561703915446281553.post-63990090004732588972014-11-20T06:07:00.000-08:002014-11-20T06:13:51.441-08:00Do the new Java 8 Date and Time objects make 3rd party date libraries redundant?This is the first of two blog posts which are a follow up to Virtual Pair Programmers’ popular <a href="https://www.virtualpairprogrammers.com/training-courses/Java-Fundamentals-training.html" target="_blank">Java Fundamentals training course</a>. This course was written with Java 7, and while everything in the course is still valid for Java 8, I thought a blog post about dates and times was worthwhile.<br />
<br />
There are other changes in Java 8, although I’d say that these don’t affect the fundamentals. The biggest change is the introduction of lambda expressions, and I’m currently working on an “Advanced Java” course for Virtual Pair Programmers, which will cover this amongst other topics…. more on that later!<br />
<br />
In the Java Fundamentals course, we say that the Date library in Java has always been a messy affair, and that while the GregorianCalendar object can be useful, if you need to do any kind of date manipulation in Java, you probably will be using an external library. In the course we <a href="http://www.joda.org/joda-time/" target="_blank">JodaTime</a> which seems to be the go-to library for most developers.<br />
<br />
However Java 8 introduces some new date and time functionality, through the new <b><span style="font-family: Courier New, Courier, monospace;">java.time</span> </b>library, so I thought I’d take a look and see whether this might now make JodaTime redundant. In this post we’ll look at how to manipulate dates and times in Java 8, and in the following post we’ll explore in more detail some of the different objects within the Java 8 date and time libraries.<br />
<br />
<h3>
Manipulating Dates with java.time</h3>
<br />
So our starting point for this post is the most common operation I find myself writing code for when it comes to working with dates… and that is comparing two dates to see if they’re the same. When I teach this to new programmers, I sometimes use the following example, as a way to practice date manipulation:<br />
<br />
Imagine that there’s a secret date that we’re trying to find out. We know it’s between 1st January 2000 and 31st December 2020.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEcoM3owBcpcG7XMukQLFZYemRGLT_dBo45ZlB_FtKD0PfcpcVmSS_VlvXoJi7MqEMsdM6gk3-abm15yjdRQ_pvbmuyD8pOLhyphenhyphenOHfEfrB93vTA_O-qfmJeGLWkSgtUI_g7qYhBJxQ_ITs/s1600/secretdate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEcoM3owBcpcG7XMukQLFZYemRGLT_dBo45ZlB_FtKD0PfcpcVmSS_VlvXoJi7MqEMsdM6gk3-abm15yjdRQ_pvbmuyD8pOLhyphenhyphenOHfEfrB93vTA_O-qfmJeGLWkSgtUI_g7qYhBJxQ_ITs/s1600/secretdate.png" height="110" width="568" /></a></div>
<br />
<br />
To find out what the secret date is, we can only ask the question in the format “how does it compare to, 16th November 2012 at 6.15am”?, and we’ll get the answer “the secret date is before, after or matches that date”.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2uU8iibIFPUrNL__wbpK6xC7y9bktf1h0snJ6xquvCxhRjLRUIqK_iaMrCWDY31wi19vk_WVURW6pIRe4SMEPVnedyaM-DVKYn1fa08vVkaCP1yJJcqmrtWqa4MKs2ny5cpJh3z69ajc/s1600/secretdate2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2uU8iibIFPUrNL__wbpK6xC7y9bktf1h0snJ6xquvCxhRjLRUIqK_iaMrCWDY31wi19vk_WVURW6pIRe4SMEPVnedyaM-DVKYn1fa08vVkaCP1yJJcqmrtWqa4MKs2ny5cpJh3z69ajc/s1600/secretdate2.png" height="156" width="568" /></a></div>
<br />
<br />
The implementation of this comparison question in JodaTime is really simple – we use the DateTime object to store the date, and use the compareTo function to compare 2 dates. This simple method does the job:
<br />
<br />
<pre class="brush:java"> public int compareDate(DateTime sampleDate) {
return sampleDate.compareTo( new DateTime(2012, 11, 16,6,15));
}
</pre>
<br />
<br />
The method takes a date and time (sampleDate) as a parameter and returns a +1 if the date and time we supply is after the date we’re looking for (the secret date), a 0 if it matches, or a -1 if the date and time we supply is before the date we’re looking for.<br />
<br />
So the work is, given that we can only ask this question, how do we find out what the secret date is?<br />
<br />
To find the answer, we play a game. We know that 1st Jan 2000 is before the secret date, and 31st December 2020 is after it. So let’s pick a date in the middle – say 1st January 2010, and ask the question for that date. The answer comes back “the secret date is after 1st January 2010”.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTbV9NSA7qPtNUsXgFoS3Fl1o8ScIUsUrLsaImFMjsbq_GAIdffuHbED_7k1aD-mUaLlTB5zqWTXjmPEulXgiCgq4FClqpBMxsU03nBjgV1imzvuJwbLG3IY1obMMvPPnv2cWEg-rgdI/s1600/secretdate3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTbV9NSA7qPtNUsXgFoS3Fl1o8ScIUsUrLsaImFMjsbq_GAIdffuHbED_7k1aD-mUaLlTB5zqWTXjmPEulXgiCgq4FClqpBMxsU03nBjgV1imzvuJwbLG3IY1obMMvPPnv2cWEg-rgdI/s1600/secretdate3.png" height="167" width="568" /></a></div>
<br />
<br />
Now we know the date lies between 1st January 2010 and 31st December 2020. So we’ll try a date between those two – perhaps 1st January 2015.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT5WKA5Nf9GbEobLouLUHqoOXG-4LU2xTxEE8M-yNAnwhCKWXdOCRlyOsXLGcAj_IZzsw8b-7xB3_Mrt4YFPSIPqIDwokcAJJ7GqdNrj5Imsu5L6p8xetPeoBqhEhBtptY759al7LON5M/s1600/secretdate4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT5WKA5Nf9GbEobLouLUHqoOXG-4LU2xTxEE8M-yNAnwhCKWXdOCRlyOsXLGcAj_IZzsw8b-7xB3_Mrt4YFPSIPqIDwokcAJJ7GqdNrj5Imsu5L6p8xetPeoBqhEhBtptY759al7LON5M/s1600/secretdate4.png" height="165" width="568" /></a></div>
<br />
<br />
We get the answer that the secret date is before 1st January 2015, so we now know it falls between 1st January 2010 and 1st January 2015.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhUe-oDs1QADYx95c9LFno_qtwH4GMgbLt5UOWyCu6GfHJve7Puu_ylhvqJdjMBhn19EJaw2oX2An2Es0L8NY2MNozSbhd3b7dGvqKU2DS1FBMBimB9Qgc9gW13NMRUHq8awU8UJktUFo/s1600/secretdate5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhUe-oDs1QADYx95c9LFno_qtwH4GMgbLt5UOWyCu6GfHJve7Puu_ylhvqJdjMBhn19EJaw2oX2An2Es0L8NY2MNozSbhd3b7dGvqKU2DS1FBMBimB9Qgc9gW13NMRUHq8awU8UJktUFo/s1600/secretdate5.png" height="117" width="568" /></a></div>
<br />
<div>
<br />
We can keep repeating this - choosing a date between our known upper and lower limits, and revising one of those limits each time until we find the date. Here’s the code that does this and the output it produces:<br />
<br /></div>
<pre class="brush:java">import org.joda.time.DateTime;
public class Main {
public static int compareDate(DateTime sampleDate) {
return sampleDate.compareTo( new DateTime(2012, 11, 16,06,15));
}
public static void main(String[] args) {
DateTime lower = new DateTime(2000,1,01,0,0);
DateTime higher = new DateTime(2020,12,31,23,59);
int result = 100;
int steps = 0;
DateTime foundDate = new DateTime();
while (result != 0) {
int difference = (int) ((higher.getMillis() - lower.getMillis()) / 2000);
foundDate = lower.plusSeconds(difference);
result = compareDate(foundDate);
if (result == -1) {
lower = foundDate;
}
else if (result == 1) {
higher = foundDate;
}
steps++;
}
System.out.println("Found date " + foundDate + " in " + steps + " steps.");
}
}
</pre>
<span style="font-family: Courier New, Courier, monospace;"><span style="color: blue;">Found date 2012-11-16T06:15:00Z in 29 steps.</span> </span><br />
<br />
I think this is a useful exercise for students new to JodaTime as it shows us:
<br />
<ul>
<li>how to compare two dates (using <span style="font-family: Courier New, Courier, monospace;"><b>compareTo</b></span>), </li>
<li>how to determine the length of time between two dates (using <span style="font-family: Courier New, Courier, monospace;"><b>getMillis</b></span>), and </li>
<li>how to add time to a date (using <span style="font-family: Courier New, Courier, monospace;"><b>plusSeconds</b></span>). </li>
</ul>
<br />
In a full lesson we would explore the other options to add days or weeks rather than seconds, but you get the idea. We cover a number of the main things that people tend to want to do with dates in 1 simple exercise.<br />
<br />
So let’s now suppose we have Java 8 and are not allowed to use JodaTime – does the new Java 8 Time library allow us to achieve this task?<br />
<br />
Well the good news is that the answer is yes, and in fact the code is almost identical to what we have above.
The two key objects we need are:<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;"><b>java.time.Instant</b></span> – this represents a Date and Time* – we'll consider that the equivalent to our JodaTime DateTime object, and </li>
<li><span style="font-family: Courier New, Courier, monospace;"><b>java.time.Duration</b></span> – this static object has a <span style="font-family: Courier New, Courier, monospace;"><b>between()</b></span> method which can give us the difference between two <span style="font-family: Courier New, Courier, monospace;"><b>Instants</b></span>, and a <span style="font-family: Courier New, Courier, monospace;"><b>toMillis()</b></span> function which converts that difference to milliseconds… </li>
</ul>
<br />
Here’s the new code… the output is identical to the JodaTime version!<br />
<br />
<div>
</div>
<pre class="brush:java">import java.time.Duration;
import java.time.Instant;
public class Main {
public static int compareDate(Instant sampleDate) {
return sampleDate.compareTo( Instant.parse("2012-11-16T06:15:00Z"));
}
public static void main(String[] args) {
Instant lower = Instant.parse("2000-01-01T00:00:00Z");
Instant higher = Instant.parse("2020-12-31T23:59:00Z");
int result = 100;
int steps = 0;
Instant foundDate = Instant.now();
while (result != 0) {
int difference = (int) (Duration.between(lower, higher).toMillis() / 2000);
foundDate = lower.plusSeconds(difference);
result = compareDate(foundDate);
if (result == -1) {
lower = foundDate;
}
else if (result == 1) {
higher = foundDate;
}
steps++;
}
System.out.println("Found date " + foundDate + " in " + steps + " steps.");
}
}
</pre>
On the basis that you understand the JodaTime version, the new Java 8 version is straight-forward.<br />
<br />
So it seems that for many date manipulation tasks the new Java 8 objects <u>will</u> meet our needs, and can be considered a success. JodaTime can do much more than just this, so it won’t be redundant just yet, but I think it will be an extra overhead we won’t need for basic date manipulation.<br />
<br />
What we have seen so far is 2 of the Java 8 classes from the <span style="font-family: Courier New, Courier, monospace;"><b>java.time </b></span>library – the <b><span style="font-family: Courier New, Courier, monospace;">Instant</span></b> and the <span style="font-family: Courier New, Courier, monospace;"><b>Duration</b></span> class. There are other useful classes in this library however, and we’ll look at some of these in the next post.<br />
<br />
<br />
<br />
* To say that an <span style="font-family: Courier New, Courier, monospace;"><b>Instant</b></span> represents a Date and Time is not the full story - it's got a very precise definition and we'll be exploring that in the next blog post.
Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com2tag:blogger.com,1999:blog-2561703915446281553.post-50837410684298776162014-10-13T09:08:00.002-07:002014-10-13T09:08:16.292-07:00Hadoop Course - Understanding the ScriptsOver the last week or so we've had a few support calls asking questions about the scripts provided in chapter 5 of the course, that are used to switch Hadoop between standalone and pseudo-distributed modes.<br />
<br />
This post will explain in a bit more detail what each script is and how it works. These are custom scripts that I've developed while working with Hadoop, so you won't (probably!) find them elsewhere on the internet, but I think they make the process of managing Hadoop configurations on a development machine really easy.<br />
<br />
Until you've got through chapter 8 of the course not everything in this post will make sense, but feel free to contact me if you have any questions after reading this - or raise a support call through https://www.virtualpairprogrammers.com/technical-support.html<br />
<br />
<br />
There are 4 scripts provided with the course:<br />
<br />
<u>(1) resetHDFS</u><br />
<br />
This script is designed to clear down your HDFS workspace - that is to empty out all the files and folders in the Hadoop file system. It's like formatting a drive. What the script actually does is:<br />
<br />
<ul>
<li>stop any running Hadoop processes</li>
<li>delete the HDFS folder structure from your computer</li>
<li>recreate the top level HDFS folder, and set its permissions so that the logged on user can write to it</li>
<li>run the hdfs format command - this will create the sub-folder structure needed</li>
<li>restart the hadoop processes</li>
<li>create the default folder structure within HDFS that's required for your pseudo-distributed jobs (/user/yourusername)</li>
</ul>
<br />
NOTES:<br />
<br />
(1) You must be in the folder where the script is located to run this script. You should run it by entering the following command:<br />
<br />
./resetHDFS<br />
<br />
(2) The script contains a number of lines that must be run with admin privileges - these contain the word sudo. As a result, running this script will require you to enter your admin password 1 or more times. Although this might seem frustrating, you will not be running this script regularly - only when you wish to delete all your data, and then it's a quick and easy way to do it.<br />
<br />
(3) Because this script creates the HDFS required file and folder structures, we use it to create them for the first time. When the course was first released there was a typing error - on line 2, sudo was misspelt sduo. This has been corrected but if you have downloaded a copy with the typo, you might wish to correct it!<br />
<br />
<u>(2) startHadoopPseduo</u><br />
<br />This script will switch Hadoop into Pseudo-distributed mode - if you're currently in standalone mode then this is the only script you need to run.<br />
<br />
What the script actually does is:<br />
<br />
<br />
<br />
<br />
<ul>
<li>remove the existing symbolic link to the configuration directory</li>
<li>create a new symbolic link to the configuration directory containing the pseudo-distributed configuration files</li>
<li>start the Hadoop processes</li>
</ul>
<div>
<u>(3) stopHadoop</u></div>
<div>
<br /></div>
<div>
This script simply stops the Hadoop processes - it should be run if you're in pseudo-distributed mode and are going to switch back to standalone mode. It doesn't change any configuration settings, it just stops the processes running. </div>
<div>
<br /></div>
<div>
<u>(4) startHadoopStandalone</u></div>
<div>
<br /></div>
<div>
This script removes the existing symbolic link to the configuration directory, and creates a new symbolic link to the configuration directory containing the standalone files. Although I've called this script "startHadoopStandalone" it doesn't actually start anything, as no processes run in standalone mode.</div>
<div>
<br /></div>
<div>
So... which scripts do you need to run and when:</div>
<div>
<br /></div>
<div>
If you're in standalone mode and you want to be in pseudo-distributed mode, just run startHadoopPseudo</div>
<div>
<br /></div>
<div>
If you're in pseudo distributed mode and you want to be in standalone mode, first run stopHadoop and then run startHadoopStandalone</div>
<div>
<br /></div>
<div>
If you have just switched on your machine and want to run in either mode - just run the relevant startScript. In this instance you don't need to run the stop script because you have no running processes if you have just booted up.</div>
<div>
<br /></div>
<div>
<br /></div>
Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com3tag:blogger.com,1999:blog-2561703915446281553.post-76749325254818470552014-10-03T02:21:00.000-07:002015-01-26T00:54:52.234-08:00Hadoop Course - Setting Environment Variables - correction to chapter 5We have just been made aware of an error in the Hadoop course, chapter 5, at approximately 19 minutes in the video. <b>This error has been fixed in and the video was replaced on 22nd October - so this will only affect you if you downloaded chapter 5 before the 22nd October 2014. All customers can download the replacement video if preferred.</b><br />
<br />
The issue relates to the part of the video that deals with setting your environment variables, and instructs you to edit either your .bashrc file (Linux) or .bash_profile (Mac)<br />
<br />
There is a mistake in the last 2 lines that I ask you to add to these files - the lines reference the HADOOP_INSTALL variable - this should in fact reference HADOOP_PREFIX as we haven't set HADOOP_INSTALL.<br />
<br />
The last 2 lines to be added should therefore be:<br />
<pre class="brush:java">export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_PREFIX/lib/native
export HADOOP_OPTS="-Djava.library.path=$HADOOP_PREFIX/lib"
</pre>
Please accept my apologies for this error. When I display my own .bashrc file (at about 20 minutes into the video) you'll see the correct information shown.<br />
<br />
<br />Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com2tag:blogger.com,1999:blog-2561703915446281553.post-88619753363751762582014-09-10T00:51:00.001-07:002014-09-10T00:51:23.058-07:00Groovy Course Correction - Chapter 21 (Files and Templates)I've been made aware today (thanks to a customer asking us to help solve a problem with his code relating to chapter 21 of the Groovy course) of a mistake on the video and with the file supplied for this chapter.<br />
<br />
In the exercise I set you to practice with templates, I show on screen the file called DailyCheckInTemplate.txt from the practicals and code folder. This is at approximately 15:22 on the video.<br />
<br />
The video tells you to copy the file from the templates folder in chapter 17, and shows you the file on screen. Unfortunately the file provided and shown is not right - it includes fields like $it.date - these should be $date.<br />
<br />
The problem with using $it.date is that Groovy will be looking for a key of it.date in the map of properties we supply to the template engine, but the keys won't be preceeded with the "it" - that is we'll be creating a map with a key of "date" and not "it.date".<br />
<br />
If you use the version of the template supplied in the starting workspace, you'll get an error message similar to this:<br />
<br />
<span style="background-color: #fafafa; color: #3e3e3e; font-family: Arial, Helvetica, sans-serif; font-size: 12.222222328186035px;">Caught: groovy.lang.MissingPropertyException: No such property: it for class: SimpleTemplateScript1</span><br style="color: #3e3e3e; font-family: Arial, Helvetica, sans-serif; font-size: 12.222222328186035px;" /><span style="background-color: #fafafa; color: #3e3e3e; font-family: Arial, Helvetica, sans-serif; font-size: 12.222222328186035px;">groovy.lang.MissingPropertyException: No such property: it for class: SimpleTemplateScript1</span><br style="color: #3e3e3e; font-family: Arial, Helvetica, sans-serif; font-size: 12.222222328186035px;" /><span style="background-color: #fafafa; color: #3e3e3e; font-family: Arial, Helvetica, sans-serif; font-size: 12.222222328186035px;">at SimpleTemplateScript1.run(SimpleTemplateScript1.groovy:1)</span><br />
<br />
The version of this file in the final workspace for chapter 21 is correct, so please pick up the DailyCheckinTemplate.txt file from the following location instead, and you'll not have any problems with your code:<br />
<br />
PracticalsAndCode / End of Chapter Workspaces / Chapter 21 - Files and Templates / Hotel Manager / templates / DailyCheckInTemplate.txtMatt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com0tag:blogger.com,1999:blog-2561703915446281553.post-25736203236934902092014-08-14T10:49:00.000-07:002014-08-14T10:49:00.570-07:00Hadoop - new course coming soon!I'm pleased to announce that recording of my next <a href="https://www.virtualpairprogrammers.com/" target="_blank">Virtual Pair Programmers</a> course is now almost complete. The course is covering Hadoop for Java Developers. If you haven't heard of Hadoop (is there anyone who hasn't?) this is a framework for distributing the processing of large amounts of data accross a a network of computers.<br />
<br />
The course assume some basic Java knowlege, but no prior knowledge of Hadoop or its Map Reduce programming model.<br />
<br />
Once recording is complete, there will be an edit phase and of course some post-production work to complete, but the likely running order is as follows:<br />
<br />
<br />
<ul>
<li>An overview of what Hadoop is, and introducing the concept of the map-reduce programming model</li>
<li>Getting to grips with map-reduce, including creating some map-reduce code in standard Java</li>
<li>Hadoop operating modes, and how to set up and install Hadoop</li>
<li>Creating our first Hadoop Map-Reduce job</li>
<li>The Hadoop Distributed File System (HDFS)</li>
<li>Understanding the map-reduce process flow, including combine and shuffle</li>
<li>Looking at map reduce job configuration options, such as file formats, runtime options</li>
<li>Creating custom data types </li>
<li>Chaining multiple jobs, and adding extra Map steps to jobs </li>
<li>Optimising jobs</li>
<li>Working with JDBC databases</li>
<li>Unit testing (with MRUnit)</li>
<li>Secondary Sorting (sorting the values as well as the keys)</li>
<li>Joining Data from multiple files</li>
<li>Using the Amazon EMR service</li>
</ul>
<div>
The course has a number of real world examples throughout and two large case studies to work through too so there's lots of practical exercises. As well as model answers and sample code throughout, I'm also including some templates that I use for my own map-reduce jobs which you'll be able to re-use in your own projects.</div>
<div>
<br /></div>
<div>
If you are a Microsoft Windows user, then you need to know that installing Hadoop on Windows is hard, so in the course, I ask you to use a virtual machine running Linux... and I'll talk you through how to install and configure that... no prior knowledge of Linux is required. Mac and Linux users can either install Hadoop directly, or also use a virtual machine - all the options are covered.</div>
<div>
<br /></div>
<div>
The course should be going live some time in September so keep an eye out on this blog or the <a href="https://www.facebook.com/VPPJavaTraining" target="_blank">Virtual Pair Programmers' facebook page</a> for more information.</div>
Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com5tag:blogger.com,1999:blog-2561703915446281553.post-82360453828674105182014-06-24T07:50:00.000-07:002014-06-24T07:50:04.912-07:00Why you can't use Derby with HadoopI'm currently in the middle of writing my next course for <a href="https://www.virtualpairprogrammers.com/" target="_blank">Virtual Pair Programmers</a>, which will be on using Hadoop. Typically in Virtual Pair Programmers courses, we use Apache's <a href="http://db.apache.org/derby/" target="_blank">Derby</a> database. We choose this because that's because it's light-weight, and so easy to distribute. It needs pretty much no installation / configuration etc. We can provide students with a full copy of the application and sample databases, and they can avoid having to spend time setting up and configuring a database server, such as MySQL, and having to import a database.<br />
<br />
One of the topics we'll be covering on the Hadoop course is the use of the DBInputFormat and DBOutputFormat to read from and write to a relational database (we'll be learning about Sqoop too but the same issue will affect Sqoop... it's just that I've not got to that part of the script just yet!).<br />
<br />
In preparing some data and test code to use on the course, I've today discovered that Hadoop just won't work with Derby. I find this somewhat surprising, given that both projects come from the Apache camp, but having spent several hours digging to find out why this might not work, I've finally found the issue. There's really not much available online about this point so I thought I'd write a blog post about it in the hope that it helps someone in the future avoid the pain I've been through today!<br />
<br />
On trying to get database reads working, I've been coming up with a horrible looking error message. I won't bore you with the full stack trace; the important part of it is:<br />
<br />
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "LIMIT" at line 1, column 75.<br />
<br />
The issue here is that Hadoop generates SQL statements in the background to read from the database. Rather than reading the whole table in one go, each map method call will read the next record. The SQL that Hadoop generates (that we can't see) includes the LIMIT keyword... and as per the <a href="http://db.apache.org/derby/faq.html#limit" target="_blank">derby FAQ</a> this keyword is not supported.<br />
<br />So it seems that there's just no easy way to read in or write out to a Derby database from Hadoop. So on the course we'll be using MySQL to learn how to work with relational databases directly from Hadoop, but for anyone using Derby and wanting to work with Hadoop, I think the only option is going to be to create a dump of the data in text format for Hadoop to import.<br />
<br />
If you have found a way to get Derby working with Hadoop please do let me know!Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com4tag:blogger.com,1999:blog-2561703915446281553.post-73316395889860953632014-05-01T06:53:00.000-07:002014-05-01T06:53:32.737-07:00Groovy Programming is now available!<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.virtualpairprogrammers.com/training-courses/Groovy-Programming-training.html" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;" target="_blank"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_4xeJKolbAaw28iQ8Zz60lRgsnnkbQo6GYEl2KwihvAYsHhiYLcnJ1aPG5-xiRnCi0STvhPanmNW7AH72Dpm8Zf3GF_21ffQG4H1odWIgP6kzm3zLz0Hf-6OgJGotrPuB86vJw1NS_Q8/s1600/Groovy-Programming.png" /></a></div>
I'm excited to announce that Groovy Programming, the latest training course from Virtual Pair Programmers (my second course for them) is now available to purchase!<br />
<br />
As with all Virtual Pair Programmers' courses, Groovy Programming is written from scratch for delivery by video, but is based on many years of experience in working with and teaching the language. We believe you'll learn far more quickly than from reading books - in fact you'll cover everything you need to be a competent Groovy programmer but at a fraction of the cost of a face-to-face course, and naturally with the convenience that our unique training methods give - the ability to download and keep all the video files, so you can study at a time and place that suits you!<br />
<br />
Groovy Programming contains 12 hours of video, but with lots of practical exercises it will take most students around a week to complete. Also included with the download are complete code for all worked exercises, and guidance notes for the tasks, as well as all the software you need (except Groovy and Eclipse, but we cover on the videos how to install and configure these!)<br />
<br />
There's a full breakdown of the content of Groovy Programming on our website, but if you have any queries about this course, you're welcome to contact me through https://www.virtualpairprogrammers.com/contact.html.
In the meantime, thank you for your continued support, and we hope you continue to enjoy our courses.<br />
<br />
<br />Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com1tag:blogger.com,1999:blog-2561703915446281553.post-71870325538041747932014-03-03T02:28:00.000-08:002014-03-31T02:41:46.076-07:00Running db-derby with recent releases of JavaThis blog post is an errata item for my Java Fundamentals course, and will also apply for the other Virtual Pair Programmers courses where we use the db-derby database.<br />
<br />
I discovered while recording the upcoming Groovy course that there has been a security change in the most recent release of Java (1.7.0.51) that has meant that the default configuration for db-derby no longer works. Running db-derby with the startNetworkServer command will result in an error message which says somewhere early on in the error message:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><b>access denied ("java.net.SocketPermission" "localhost:1527" "listen,resolve")</b></span><br />
<br />
The easiest and quickest way to overcome this seems to be to run the database on a higher port number, such as 50000 - to do this, instead of running the startNetworkServer command, run the following instead to start the db-derby database:<br />
<br />
<span style="color: blue; font-family: Courier New, Courier, monospace;"><b>NetworkServerControl -p 50000 start</b></span>
<br />
<br />
In your code, you'll need to change the connection strings to incorporate the new port number, so that the line of code which creates the connection includes the port number - it should look like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><b>conn = DriverManager.getConnection(<span style="color: blue;">"jdbc:derby://localhost:50000/library"</span>);</b></span>
<br />
<span style="font-family: Courier New, Courier, monospace;"><b><br /></b></span>
This should overcome the error - if you find you have any further unexpected errors that you can't resolve however, do get in contact via the Virtual Pair Programmers contact us page!Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com5tag:blogger.com,1999:blog-2561703915446281553.post-66429205622867319272014-02-08T03:21:00.002-08:002014-02-08T03:21:18.873-08:00Groovy Course coming soon<span style="color: #333333; font-family: Arial, Helvetica, sans-serif;"><span style="background-color: white; line-height: 20.799999237060547px;">One of the topics that we've been asked to provide a course on at Virtual Pair Programmers a number of times over the last few years is Groovy... so I'm pleased to announce that I'm currently making good progress on creating the Groovy Course, which I hope will be released around the end of March 2014.</span></span><br />
<span style="color: #333333; font-family: Arial, Helvetica, sans-serif;"><span style="background-color: white; line-height: 20.799999237060547px;"><br /></span></span>
<span style="color: #333333; font-family: Arial, Helvetica, sans-serif;"><span style="background-color: white; line-height: 20.799999237060547px;">While I've been talking about the Groovy course to fellow Java programmers and trainers, in particular I've had a number of conversations about what it should cover , everyone seems to agree that once you start with Groovy you don't want to switch back to plain old Java, and I guess this is primarily because everything you can do in Java can be done in Groovy, often more quickly, and of course you can do more too. I've come to the conclusion that for many Java programmers it's really quite easy to get up and running in Groovy, but to really harness it's power, and get the most out of the language, it needs a really quite thorough course.</span></span><br />
<span style="color: #333333; font-family: Arial, Helvetica, sans-serif;"><span style="background-color: white; line-height: 20.799999237060547px;"><br /></span></span>
<span style="color: #333333; font-family: Arial, Helvetica, sans-serif;"><span style="background-color: white; line-height: 20.799999237060547px;">For anyone who doesn't know what Groovy is, I've pasted below a response to the question "what is groovy" taken from <a href="http://stackoverflow.com/questions/287598/what-is-groovy" target="_blank">Stack Overflow</a>... although this isn't the top answer on that site, it's the one that I like the most as I think it gives a real flavour of what Groovy is really about from a programmer's perspective:</span></span><br />
<br />
<blockquote class="tr_bq" style="background-color: #ccffcc;">
<span style="font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 17.804800033569336px;">Groovy is a dynamically typed language that runs on the Java platform and includes some features that a lot of people wish were in Java (ex: closures). One nice thing about Groovy is that it reduces the amount of code needed to do common tasks such as parsing XML files and accessing databases. While learning Groovy you can always mix in straight Java code. This is nice since it allows you to ease into Groovy at your own pace while delivering functional code. If you've been using Java for a while I think you'll appreciate the simplicity of using Groovy since you can program more functionality using less keystrokes. The inclusion of closures was a big selling point for me. One word of caution: if you use Groovy for production code you should make sure there is descent test coverage (since Groovy is a dynamic language). Even if you decide not to use Groovy, it's not a huge time investment to learn and experiment a bit.</span></blockquote>
<br />
<span style="background-color: white; color: #333333; font-family: Arial, Helvetica, sans-serif; line-height: 20.799999237060547px;">The chapter list for our forthcoming course isn't quite complete, but the likely structure and outline content is as follows:</span><br />
<ul style="background-color: white; color: #333333; line-height: 20.799999237060547px;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Introduction: The difference between Groovy and Java, installing Groovy and setting up a development environment</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Part One: Getting started - looking at the power of key aspects of programming in Groovy, such as objects, methods, strings, operators, closures, ranges and looping and unit testing</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Part Two: Case Study - using everything we have learned to start to build a working application - our example is going to be a hotel room booking system</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Part Three: Going deeper - more on closures, working with files including XML, databases, Meta Object Protocol, using stubs and mocks in unit testing and finally packaging and deployment</span></li>
</ul>
<span style="color: #333333;"><span style="background-color: white; font-family: Arial, Helvetica, sans-serif; line-height: 20.799999237060547px;">Our case study will start after we have studied the basics, and we'll be developing a back-end system to help a small hotel manage its room bookings. As we learn more advanced topics, we will then enhance the back-end system to provide more functionality. </span></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br style="background-color: white; color: #333333; line-height: 20.799999237060547px;" /></span>
<span style="background-color: white; color: #333333; font-family: Arial, Helvetica, sans-serif; line-height: 20.799999237060547px;">We'll put an update on progress nearer the release date, but in the meantime, if you're welcome to contact me through <a href="http://www.virtualpairprogrammers.com/">www.virtualpairprogrammers.com</a></span>Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com1tag:blogger.com,1999:blog-2561703915446281553.post-66820551246287978572013-12-06T08:01:00.000-08:002013-12-06T08:01:20.369-08:00Java Fundamentals - follow up post on Automatic Resource ManagementThis is the second of two follow up videos for the Java Fundamentals course. In this video, I take the Java try with resources statement a little bit further to tidy up the code we created in chapter 26 of the course. <br />
<br />
The video is hosted on youtube - for best viewing results, watch in full screen and choose the HD quality option if that doesn't come up by default when you click on play!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.youtube.com/watch?v=xByaTRRd6JU">Click here for the video</a></div>
Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com0tag:blogger.com,1999:blog-2561703915446281553.post-51569092319178306732013-06-22T13:04:00.000-07:002013-06-22T13:04:00.149-07:00Follow-up video blog on the keyword StaticOne of the topics that didn't make it into the Java Fundamentals course was an explanation of the keyword static... so I've done a short follow up video which goes into detail about that. In the video, I cover what the keyword means and how to use it correctly (both static methods and static variables).<br />
<br />
The video is hosted on youtube - for best viewing results, watch in full screen and choose the HD quality option if that doesn't come up by default when you click on play!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://img.youtube.com/vi/VPeuSuiA_1Y/0.jpg" height="266" width="320"><param name="movie" value="http://youtube.googleapis.com/v/VPeuSuiA_1Y&source=uds" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://youtube.googleapis.com/v/VPeuSuiA_1Y&source=uds" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<br />
<br />Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com7tag:blogger.com,1999:blog-2561703915446281553.post-37351166068938921992013-06-20T15:41:00.002-07:002013-06-20T15:41:46.850-07:00Java Fundamentals now liveWell I'm pleased to say that after months and months of hard work, the Java Fundamentals course is now live and available for purchase from <a href="https://www.virtualpairprogrammers.com/training-courses/Java-Fundamentals-training.html">https://www.virtualpairprogrammers.com/training-courses/Java-Fundamentals-training.html</a><br />
<br />
I'm really pleased with how it has turned out - it's a really comprehensive course now, about 12 hours in length, and I think we've covered object orientation in a really accessible way, which I'm most proud of! <br />
<br />
Just want to thank <a href="http://richardchesterwood.blogspot.co.uk/">Richard Chesterwood</a>, my fellow VPP trainer, for his help and guidance throughout this process - and I'm looking forward now to starting work on the next one!<br />
<br />
<br />Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com1tag:blogger.com,1999:blog-2561703915446281553.post-33653156609605112612013-02-28T15:45:00.001-08:002013-02-28T15:45:04.228-08:00Content of the new introductory Java CourseThe new Introductory Java course is now being edited. As a result I have a pretty good idea of the final content and running order, although the editing and review process will highlight any key areas that need to be changed, or added, so this might not exactly match the final course content or structure.<br /><br />I have written the course from the perspective of someone with some programming experience (in any language, such as C, Visual Basic, PHP or just JavaScript) and so this is very much a "conversion" to Java. The first part focuses on how to do things in Java that you are likely to be familiar with in another language, such as declaring variables, conditions and loops, and the second part then covers topics that are more unique to Java and so may be completely new.<br /><br />I'm conscious that some people will want to use the course having done little programming before, so I've been careful to make sure that any concepts not fully explained are easily understandable by the novice if they are willing to spend a bit of time doing their own online research.<br /><br />So here's the likely running order:<br /><br />1 - Introduction to Java<br />2 - Installing Java and Eclipse<br />3 - Key aspects of Java syntax <br />4 - Introduction to Object Orientation <br />5 - Structuring applications<br />6 - Java libraries and Javadocs<br />7 - More advanced Object Orientation (including inheritance and abstract classes)<br />8 - Exceptions<br />9 - JUnit<br />10 - Collections<br />11 - Yet more object orientation (Interfaces and polymorphism)<br />12 - Databases<br />13 - Distributing your software<br /><br />In any of the books or other courses I have seen on Java, I find that trainers struggle with object orientation (OO) - the issue is finding an example that individuals can understand and relate to. I have been really careful to ensure that we build up the OO aspects in a practical and logical way, and rather than talking about something that is really not related to programming, such as the number of legs on an insect (I do remember that being the example when I first learned about object orientation, and I certainly didn't get it at the time), our examples are hopefully modern, understandable, and useable in real world applications.<br /><br />Throughout the course we have a key project that we work on together, and while we don't fully complete the application, we do end with a good solid framework and code base that could be extended to be a live, functional and useful application.<br /><br />I've give another update as we get close to the launch date.Matt Greencrofthttp://www.blogger.com/profile/00492164421933687329noreply@blogger.com2