Monday, October 7, 2013

Silicon Code Camp 2013: "12 Take-Aways: Managing the Unmanagable" Summary

This is the first in a series of posts about what I found out at the 2013 Silicon Valley Code Camp (#svcc).  This post is about the information presented in the presentation "12 Take-Aways: Managing the Unmanageable" by Ron Lichty (@RonLichty).  I feel compelled to disclose gain on my part; that there was a raffle for a free copy of his book "Managing the Unmanageable" (link below) which I won.  Just from reading a selection of 30 pages or so about "Managing Yourself" I can tell that the book is also really good.  With that in mind we can continue on to major points from the slides.

There is so much technical expertise expected of a programmer to possess, but so little management knowledge expected to manage programmers.  In many organizations a programmer is promoted to a manager of programmers with no formal training or even required reading!  Not even the Mythical Man Month (link below)!  Compare this to automotive companies where managers are sent for six weeks of just training in the lean methodology.  (There is going to be a summary of a presentation on lean start-ups in this series too).  Most software managers are not provided with a mentor or given clear tasks beyond the project deadlines.  These tasks are typically removing impediments to the team; setting goals and objectives for the team and team-members and advocating the process used for development.

Doing these tasks well and in different circumstances right now can be bolstered by rules of thumb (coincidentally in his book).  Some of these are that you should always be recruiting and bad hires happen to everyone.

Dealing with problem employees can be done via having an intervention, crafting performance plans, or letting the employee go.  There is also a book on just this subject, "Handling the Difficult Employee" (link below).  The goal of an intervention is to turn them around (and if that doesn't work they will typically leave on their own). This is the most time consuming option for preparation, the intervention itself and for the follow-up as well.  As for execution you state the problem behavior (have a problem with the behavior, not the person) and the impact of that behavior on the team.  Then let them vent, they will typically blame others for everything, this will take a lot of time (block off 4 hours).  Follow up with them weekly.

Another rule of thumb: follow up 1 on 1 weekly with ALL of your employees.

Get to know your people's personality types and coding styles, this will help with problems not showing up to begin with.  He almost suggests doing a full psych profile since not all programmers are alike.  Disciplines are different (system programmers vs web app guys vs mobile app guys), generations and ages vary, some people are morning people and some are night people, employees vs contractors, local or remote and cowboys ("get it done" whoCaresAboutBadStyleLikeHowLongVariableNamesShouldBe) vs farmers (cultivate good, clean code).  These personalities are who will work on the product.

At the start the concern about the product will be about scope, budget and schedule but at the end the question is "do people love it?"  To put it another way, "It's the Product, Stupid" (meme).  Getting a good product out can come down to leadership.

Leading by example happens, whether you like it (or want to) or not and take time for reviews of your progress.  Especially with people who have recently had a change in role.

What made you successful in one role can get in your way in another.  Needing the concentration to get into a flow state to code doesn't mesh with having an open door (e.g. "interrupt me whenever you need to") policy.  When they do come in you need to give them your complete focus though while balancing micromanagement vs fire-and-forget delegation.  In addition to leadership and listening you have to pay attention to motivations.

There is a difference between motivators and things that are not demotivators.  As an example low compensation is a demotivator but high compensation over good compensation isn't a motivator.  Motivators are things like making a difference, learning and growing, toys and technology, recognition and praise, having fun and having good relationships.  Especially with money, be careful what your reward.

You get what you measure is a rule of thumb and this applies to employee metrics.  Want a bloated code base?  Then you measure lines of code.  Want a terrible code base?  Then reward features and ignore efforts on refactoring.  Want people to be working for money instead of for passion?  Then reward them with money.  That applies when you're being managed as well.

The most important leader in your organization is your boss.  Assume that perceptions are real to those that have them and (again) focus on listening.  There were topics that he didn't cover; the runners up in the top 12 list and things that came up in discussion.

These topics included recruiting, the first day of getting a new hire, fostering a culture (there will be a post on that as well) and teamwork.  Covered during the discussions were topics like: how do you manage being a programmer AND a manager in a small company (block off a few hours of coding time a day, open door for the rest of the day); how you manage remotely (dig for problems, ask "what do you hate" or "how could I manage better"); self-reviews (if in a VERY small company) and what to do if people show up late for an 8 person meeting (bring delicious cookies, 7 of them).

Next in the line up is going to be about corporate culture.

Further Reading

Book: Managing the Unmanageable
Book: Handling the Difficult Employee
Book: Manage It!, the Programmatic Programmer book on management
Book: The Mythical Man Month
Book: Peopleware
Magazine: Harvard Business Review
Author: Danial Pink
Blog: ronlichty.blogspot.com

Tuesday, October 1, 2013

Here Be Dragons: Apache DeltaSpike on Google App Engine

I recently tried using Apache DeltaSpike, CDI extensions that are the official successor to Seam. On the Google App Engine.

Unfortunately, as of this writing (and version .4 of DeltaSpike) the library triggers the infamous Restricted Class error:

[INFO] Oct 01, 2013 11:59:04 PM com.sun.faces.config.ConfigureListener contextInitialized
[INFO] SEVERE: Critical error during deployment: 
[INFO] com.sun.faces.config.ConfigurationException: Factory 'javax.faces.context.FacesContextFactory' was not configured properly.
[INFO]  at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:330)
[INFO]  at com.sun.faces.config.processor.FactoryConfigProcessor.process(FactoryConfigProcessor.java:236)
[INFO]  at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:435)
[INFO]  at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:214)
[INFO]  at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
[INFO]  at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
[INFO]  at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
[INFO]  at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
[INFO]  at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
[INFO]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
[INFO]  at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
[INFO]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
[INFO]  at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
[INFO]  at org.mortbay.jetty.Server.doStart(Server.java:224)
[INFO]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
[INFO]  at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:249)
[INFO]  at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:306)
[INFO]  at com.google.appengine.tools.development.AutomaticInstanceHolder.startUp(AutomaticInstanceHolder.java:26)
[INFO]  at com.google.appengine.tools.development.AbstractModule.startup(AbstractModule.java:79)
[INFO]  at com.google.appengine.tools.development.Modules.startup(Modules.java:88)
[INFO]  at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:240)
[INFO]  at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:399)
[INFO]  at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
[INFO]  at com.google.appengine.tools.development.DevAppServerMain.<init>(DevAppServerMain.java:334)
[INFO]  at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:310)
[INFO] Caused by: javax.faces.FacesException: org.apache.deltaspike.jsf.impl.listener.request.DeltaSpikeFacesContextFactory
[INFO]  at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:710)
[INFO]  at javax.faces.FactoryFinder.getImplementationInstance(FactoryFinder.java:572)
[INFO]  at javax.faces.FactoryFinder.access$500(FactoryFinder.java:140)
[INFO]  at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:1120)
[INFO]  at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:379)
[INFO]  at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:328)
[INFO]  ... 24 more
[INFO] Caused by: java.lang.reflect.InvocationTargetException
[INFO]  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[INFO]  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
[INFO]  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[INFO]  at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
[INFO]  at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(Runtime.java:127)
[INFO]  at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Runtime.java:135)
[INFO]  at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:690)
[INFO]  ... 29 more
[INFO] Caused by: java.util.ServiceConfigurationError: org.apache.deltaspike.core.spi.config.ConfigSourceProvider: Provider org.apache.deltaspike.core.impl.config.DefaultConfigSourceProvider could not be instantiated: java.lang.NoClassDefFoundError: javax.naming.InitialContext is a restricted class. Please see the Google  App Engine developer's guide for more details.
[INFO]  at java.util.ServiceLoader.fail(ServiceLoader.java:224)
[INFO]  at java.util.ServiceLoader.access$100(ServiceLoader.java:181)
[INFO]  at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:370)
[INFO]  at java.util.ServiceLoader$1.next(ServiceLoader.java:438)
[INFO]  at org.apache.deltaspike.core.util.ServiceUtils.loadServiceImplementations(ServiceUtils.java:55)
[INFO]  at org.apache.deltaspike.core.api.config.ConfigResolver.resolveConfigSources(ConfigResolver.java:224)
[INFO]  at org.apache.deltaspike.core.api.config.ConfigResolver.getConfigSources(ConfigResolver.java:203)
[INFO]  at org.apache.deltaspike.core.api.config.ConfigResolver.getAllPropertyValues(ConfigResolver.java:160)
[INFO]  at org.apache.deltaspike.core.util.ClassDeactivationUtils.initConfiguredClassDeactivators(ClassDeactivationUtils.java:152)
[INFO]  at org.apache.deltaspike.core.util.ClassDeactivationUtils.getClassDeactivators(ClassDeactivationUtils.java:143)
[INFO]  at org.apache.deltaspike.core.util.ClassDeactivationUtils.initDeactivatableCacheFor(ClassDeactivationUtils.java:88)
[INFO]  at org.apache.deltaspike.core.util.ClassDeactivationUtils.isActivated(ClassDeactivationUtils.java:73)
[INFO]  at org.apache.deltaspike.jsf.impl.listener.request.DeltaSpikeFacesContextFactory.<init>(DeltaSpikeFacesContextFactory.java:42)
[INFO]  ... 36 more
[INFO] Caused by: java.lang.NoClassDefFoundError: javax.naming.InitialContext is a restricted class. Please see the Google  App Engine developer's guide for more details.
[INFO]  at com.google.appengine.tools.development.agent.runtime.Runtime.reject(Runtime.java:51)
[INFO]  at org.apache.deltaspike.core.impl.util.JndiUtils.<clinit>(JndiUtils.java:51)
[INFO]  at java.lang.Class.forName0(Native Method)
[INFO]  at java.lang.Class.forName(Class.java:186)
[INFO]  at com.google.appengine.tools.development.agent.runtime.RuntimeHelper.checkRestricted(RuntimeHelper.java:70)
[INFO]  at com.google.appengine.tools.development.agent.runtime.Runtime.checkRestricted(Runtime.java:64)
[INFO]  at org.apache.deltaspike.core.impl.config.LocalJndiConfigSource.getPropertyValue(LocalJndiConfigSource.java:53)
[INFO]  at org.apache.deltaspike.core.impl.config.BaseConfigSource.initOrdinal(BaseConfigSource.java:54)
[INFO]  at org.apache.deltaspike.core.impl.config.LocalJndiConfigSource.<init>(LocalJndiConfigSource.java:39)
[INFO]  at org.apache.deltaspike.core.impl.config.DefaultConfigSourceProvider.<init>(DefaultConfigSourceProvider.java:49)
[INFO]  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[INFO]  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
[INFO]  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[INFO]  at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
[INFO]  at java.lang.Class.newInstance0(Class.java:372)
[INFO]  at java.lang.Class.newInstance(Class.java:325)
[INFO]  at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:362)
[INFO]  ... 46 more

Monday, September 16, 2013

Logging out with Apache Shiro and Spring Web Flow

In this article I will attempt to save others the frustration of figuring out how to log out with Apache Shiro security in a Spring Web Flow app. The Shiro site has a nice link on Spring integration and from incorporating that and finding the Subject.logout() method, only to use it resulting in a Spring Web Flow error about being unable to serialize a non-existent session (since you just killed it):
[INFO] Caused by: org.springframework.webflow.execution.repository.NoSuchFlowExecutionException: No flow execution could be found with key 'e1s2' -- perhaps this executing flow has ended or expired? This could happen if your users are relying on browser history (typically via the back button) that references ended flows.
[INFO]  at org.springframework.webflow.execution.repository.support.AbstractFlowExecutionRepository.getConversation(AbstractFlowExecutionRepository.java:172)
[INFO]  at org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository.updateFlowExecutionSnapshot(DefaultFlowExecutionRepository.java:141)
[INFO]  at org.springframework.webflow.engine.impl.FlowExecutionImpl.updateCurrentFlowExecutionSnapshot(FlowExecutionImpl.java:427)
[INFO]  at org.springframework.webflow.engine.impl.RequestControlContextImpl.updateCurrentFlowExecutionSnapshot(RequestControlContextImpl.java:222)
[INFO]  at org.springframework.webflow.engine.ViewState.updateHistory(ViewState.java:324)
[INFO]  at org.springframework.webflow.engine.ViewState.exit(ViewState.java:248)
[INFO]  at org.springframework.webflow.engine.Transition.execute(Transition.java:225)
[INFO]  at org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)
[INFO]  at org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)
[INFO]  at org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)
[INFO]  at org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)
[INFO]  at org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)
[INFO]  at org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)
[INFO]  at org.springframework.webflow.engine.ViewState.handleEvent(ViewState.java:231)
[INFO]  at org.springframework.webflow.engine.ViewState.resume(ViewState.java:195)
[INFO]  at org.springframework.webflow.engine.Flow.resume(Flow.java:537)
[INFO]  at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)
[INFO]  ... 54 more
[INFO] Caused by: org.springframework.webflow.conversation.NoSuchConversationException: No conversation could be found with id '1' -- perhaps this conversation has ended? 
[INFO]  at org.springframework.webflow.conversation.impl.ConversationContainer.getConversation(ConversationContainer.java:126)
[INFO]  at org.springframework.webflow.conversation.impl.SessionBindingConversationManager.getConversation(SessionBindingConversationManager.java:117)
[INFO]  at org.springframework.webflow.execution.repository.support.AbstractFlowExecutionRepository.getConversation(AbstractFlowExecutionRepository.java:183)
[INFO]  at org.springframework.webflow.execution.repository.support.AbstractFlowExecutionRepository.getConversation(AbstractFlowExecutionRepository.java:170)
[INFO]  ... 70 more
[INFO] 
From digging deeper into the documentation you can find a log out filter for Shiro, but using this instead of Subject.logout() in an action method (i.e. the action attribute of a button or link, not an action-state) will still give the same error. Lastly, you can find a blog post by BalusC (under Programmatic Logout) that describes how to tell JSF that you just logged out via Omnifaces in the action but that doesn't quite do the trick either. However, calling Subject.logout(), the code BalusC describes and then returning NULL from the action does it. Apparently the log out code doesn't stop SWF from trying to resume the flow, but returning null does. To summarize, the following will let you log out of Apache Shiro and Spring Web Flow when bound to the action of something like an h:button:
 public String logoutAction() throws IOException {
  SecurityUtils.getSubject().logout();
  Faces.invalidateSession();
  Faces.redirect("/faces/loginflow");
  return null;
 }

Monday, August 19, 2013

JSF 2.2 with Google App Engine, Maven and Eclipse

Introduction

As noted in my last post, starting with a Maven JSP archetype (there is no JSF archetype at the time of this writing) and trying to upgrade it to JSF met with disaster.  However, starting with a new JSF project and upgrading it to Maven was doable!  This article outlines the steps and potential errors on the way.  At the end we will have a working (including the Expression Language) JSF 2.2 Hello World with the Google App Engine (GAE) and Maven.

To begin I'd like to note that as I first started working with the Google App Engine I didn't fully appreciate that it IS your deployment container.  I was thinking that there would be something like WebLogic that happened to be running on Google's infrastructure, but was incorrect.  The GAE replaces the traditional managed container of WebLogic, WebSphere, Glassfish and Tomcat, and has it's own custom configuration.  That brings us to the philosophy of how this deployment will be done.

Outline

We will essentially be merging the Maven JSF archetype provided by Google with a new JSF project created via the GAE plugin for Eclipse.  The JSF part is essentially a modification to a current tutorial provided by Wildstar Technologies with info from the GAE Guestbook archetype.  This leads us to having the required starting technologies of Eclipse (I used version 4.3 Kepler), the GAE plugin for Eclipse, Maven 3.1 and the Maven plugin for Eclipse.  The first step will be to create the JSP Archetype.

Create GAE JSP Maven Guestbook Archetype

Go to the Guestbook link and view the steps under Building the Guestbook Demo using guestbook-archetype.  You'll be wanting to use the Eclipse IDE to do similar.

Make a New Maven Project

In Eclipse, go to the Project Explorer -> context menu (right click) -> New -> Other... as in the following screen shot:
and then select Maven -> Maven Project:

Add the New Maven Archetype From Google

Click on Next >, and then accept the defaults for the next screen by selecting Next > again.  This brings us to the Maven Archetypes box.  You'll want to click on New Archetype and fill out the info for the GAE JSP Guestbook archetype:

Click on Next > after you select your newly added archetype and on the next screen give it a name like "mavenjsp" as we'll be deleting it later and an appropriate Group Id (or com.gaetest if you're not sure).

Conclusion of Creating the New Project from the GAE Archetype

Click on finish and this will give you a shiny new JSP Maven project:
You can also notice from expanding the Deployed Resources that your webapp directory is the root of your webspace (e.g. you put your landing page index.xhtml here).  However, in the GAE project it creates a WebContent directory that is your root (see below) and it populates (i.e. wipes out) the Deployed Resources file.  It took me several hours to figure out what was happening here.  Now that we have our Maven template project, we can start on the GAE JSF project.

Create GAE Web Application Project

We start with creating and configuring another new project, with the steps largely outlined already.

Create New Web Application Project

See the right screen shot of the toolbar.

Configure the Web Application Project

Follow the steps for Creating a New Project in the Wildstar tutorial starting at step 2.

The Google App Engine Facet

The Google App Engine facet (Eclipse facets are discussed below) had some issues at the time of this writing: it was only compatible with the Dynamic Web Module 2.5 even though 3.1 was available, it would just hang until I Reverted or Canceled the Facets screen when I selected Further configuration available....  Lastly without configuration it would not even work, giving an error of 
Failed While Installing Google App Engine 1
Later in this tutorial we will configure the project to be compatible with GAE manually, but if the facet can work for you, you may be able to save a lot of steps later on.  As is, let's get to the facets we will install.

Add Working Facets to Project

Next up we want to JSF-ize the project by adding the Dynamic Web Module 2.5 facet and the JavaServer Faces 2.2 facet.  To do this, go to the Project's context menu -> Properties -> Project Facets and select Dynamic Web Module 2.5, next enable JavaServer Faces and Further Configuration to have it manage your web.xml file and not provide a library (that's what Maven is for).  See the below two images:

Confirm everything and you may see some errors like:
cvc-elt.1: Cannot find the declaration of element 'jdoconfig'
in your Eclipse project.

Fix jdoconfig.xml

Go to the Markers view at the bottom (by default) and select the error about jdo.  Comment out the entire file except for the first line.
<?xml version="1.0" encoding="utf-8"?>
<!-- <jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig" -->
<!--    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -->
<!--    xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig"> -->

<!--    <persistence-manager-factory name="transactions-optional"> -->
<!--        <property name="javax.jdo.PersistenceManagerFactoryClass" -->
<!--            value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"/> -->
<!--        <property name="javax.jdo.option.ConnectionURL" value="appengine"/> -->
<!--        <property name="javax.jdo.option.NontransactionalRead" value="true"/> -->
<!--        <property name="javax.jdo.option.NontransactionalWrite" value="true"/> -->
<!--        <property name="javax.jdo.option.RetainValues" value="true"/> -->
<!--        <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/> -->
<!--        <property name="datanucleus.appengine.singletonPMFForName" value="true"/> -->
<!--    </persistence-manager-factory> -->
<!-- </jdoconfig> -->
That should do the trick.

Configure web.xml

Bring up /WebContent/WEB-INF/web.xml.  Not the one in /war, not the one in /Deployed Resources.  Put the following just before the last closing tag.  This is the "good stuff" from the Wildstar tutorial:
   <!-- ***** Designate client-side state saving. *****  -->
   <context-param>
      <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
      <param-value>client</param-value>
   </context-param>
   <!-- Set the default suffix for JSF pages to .xhtml -->
   <context-param>
      <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
      <param-value>.xhtml</param-value>
   </context-param>
   <welcome-file-list>
      <welcome-file>index.html</welcome-file>
   </welcome-file-list>
Delete the preconfigured welcome-file-list at the top.  I had issues where the GAE got confused if there was more than one welcome-file and would just display a blank-screen.  It's easier to have an index.html page automatically redirect to the .jsf or .xhtml page you want.  Save your change and we're ready to test it out!

Convert to Maven Project

If you forget this step before you run maven verify (see below) you'll get something like the following:
[ERROR] The goal you specified requires a project to execute but there is no POM in this directory
oops (I did this).  To Maven-ize your project go to the project's context menu -> Configure -> Convert to Maven project.

Pick your Group Id, name and description and you're done Maven-izing the project, but it still won't verify.

Adding Maven Dependencies for Servlets

The first error if you try to mvn verify will be something like:
[ERROR] ... package javax.servlet.http does not exist
So we add servlets as a dependency to the pom.xml.  Open the pom.xml for the project, go to the Dependencies tab and add the servlet-api with the information below:

To mark the dependency as provided you'll need to select it and click on Properties..., which brings up the above screen.  Now you can run mvn verify:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.503s
[INFO] Finished at: Mon Aug 19 12:54:31 PDT 2013
[INFO] Final Memory: 15M/218M
[INFO] ------------------------------------------------------------------------

Configure for Google App Server

There are a few steps to do before you can run the Google App Server though; just because Maven is OK with the code doesn't mean the app server is.

Add Google Dependencies to pom.xml

If you try to run the app server now (see below for instructions) you'll get an error like:
[ERROR] No plugin found for prefix 'appengine' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories...
Clearly the pom.xml needs some work.  There are a lot of elements that depend or the app engine version, so make a POM property (edit pom.xml, Overview tab, Properties -> Create) of appengine.target.version with value "1.8.3".   Add the following dependencies:

  • com.google.appengine:appengine-api-1.0-sdk:${appengine.target.version}
  • com.google.appengine:appengine-testing:${appengine.target.version}, scope: test
  • com.google.appengine:appengine-api-stubs:${appengine.target.version}, scope: test
Manually edit (the pom.xml tab) project/build/plugins to add the following:
<plugin>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>${appengine.target.version}</version>
</plugin>

Save your pom.xml and move on to the appengine-web file.

Copy appengine-web.xml to project

Now if you mvn verify and run the app engine you'll get something like:
[INFO] com.google.apphosting.utils.config.AppEngineConfigException: Could not locate ...\WEB-INF\appengine-web.xml
When we converted the project to JSP it started using /WebContent instead of /war as the base path; move the appengine-web.xml from war/WEB-INF to WebContent/WEB-INF.

Update Version (if needed)

If you verify and run the server again, you may get a major warning about having an out of date GAE.  If you get no such warning, skip on to the next section.  The instructions were simple but the new GAE is quite large and can take 10 minutes to download on a good cable connection.  If you have to upgrade, grab some coffee or a spot of tea while you verify and run the server again.

Copy Logging properties file

If you verify and devserver again, the server will run with many errors and warnings.  The top-most of these will be something like:
[INFO] java.io.FileNotFoundException: ...\WEB-INF\logging.properties (The system cannot find the file specified)
If you actually ran the server from inside of Eclipse, be sure to see the Killing the Zombie Server section below.  Fixing this error is the same as the prior section, copy the file in question from /war to /WebContent.

Add JSF Dependency

If you did a verify and devserver cycle again, you would not get the logger error, but would get:
[INFO] java.lang.ClassNotFoundException: javax.faces.webapp.FacesServlet
Looks like it's time to put in a JSF Maven dependency.  This is a little tricky.  For implementations we have the following choices:

  • java 7 ee, provided dependency that comes with JSF
    • I couldn't get this to work; same error
  • Apache MyFaces
  • GlassFish has a provided dependency... only for the GlassFish server.
  • Amazingly, Oracle made something that worked, and I wound up going with Oracle JSF 2.2.2.
    • AKA Mojarra, that is part of Glassfish but works on other application containers.
To add the Oracle JSF dependency create a new Maven property, jsf.version with the value of 2.2.2, then add in com.sun.faces:jsf-api:${jsf.version}, com.sun.faces:jsf-impl:${jsf.version}.

Create index.html and index.xhtml

If you cycle your server again... it will work with no errors!
Let's bring up our page at localhost:8080... and get a 403 error.  If you try index.html manually you'll get a 500 error about an ExternalContext (detailed below).  Wait, we don't have an actual faces file.  Let's go get one.
Create a new HTML file in /WebContent with the following content, that I found on stackoverflow:
<!DOCTYPE HTML>
<html lang="en-US">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="refresh" content="1;url=index.xhtml">
        <script type="text/javascript">
            window.location.href = "index.xhtml"
        </script>
        <title>Page Redirection</title>
    </head>
    <body>
        <!-- Note: don't tell people to `click` the link, just tell them that it is a link. -->
        If you are not redirected automatically, follow the <a href='index.xhtml'>link to example</a>
    </body>
</html>

Now that we have redirection to index.xhtml let's put up a hello world.  Create a new XHTML file (also under /WebContext) and replace the contents with what you find under Creating index.jsp, step 8 on the wildstar tutorial.

Celebrate

Upon cycling the server again (or if you haven't been following along every road block, start the server for the first time as detailed below) and brining up http://localhost:8080/faces you may get a:
HTTP ERROR 500 ... java.lang.IllegalStateException: Response has already been committed
following the url with a / does the trick: http://localhost:8080/faces/.
In fact, you can try out some EL by including
<p>Hello #{param.name}!</p>
inside of the f:view element in the xhtml page, then go to http://localhost:8080/faces/index.xhtml?name=you.
I know, this was a @^$@ long Hello World.

(Optional) Configure the Expression Language

You may come across an error like:
com.sun.faces.config.ConfigurationException: It appears the JSP version of the container is older than 2.1 and unable to locate the EL RI expression factory, com.sun.el.ExpressionFactoryImpl.  If not using JSP or the EL RI, make sure the context initialization parameter, com.sun.faces.expressionFactory, is properly
set.
Even though it's written for Tomcat 6, this tutorial should help you out if you get the error and this one by my old teacher at SJSU helps as well (it's a small dev world afterall).
You can find the el-api in both 2.2 and 3.0 versions... but 3.0 is still a draft with no implemenation at the time of writing, so use 2.2 for the API and the GlassFish (works with non-GlassFish servers) impl.

Run the Google App Engine Server From Eclipse

To actually run the server, go to Run (either toolbar icon or top menu) -> Run Configurations, you will want to input something like the following (but with a Goals of "appengine:devserver"):

Your base directory will be different, but the Maven Runtime must be the external 3.1 runtime.  Click on Apply and then Run, load up localhost:8080 and win!

Killing the Zombie Server

Unfortunately when it's time to say goodbye to the server (usually because you want to mvn clean) Eclipse doesn't pass through a control-c to kill the program but gives you a red box to stop it.  The server is immune to such petty things as red boxes, but only the mighty control-c or TaskManager (or ProcessExplorer) can lay it low.  If you go to TaskManager and the Processes tab you can see multiple java.exe's from servers that didn't truly die.  You can kill them manually every time you need to (rememer, "java.exe", "javaw.exe" is your Eclipse!) or you can run the mvn command for the server from the command line.  I do this personally... when I remember, and love to use the program Console2 instead of the standard console, and came across a great article about configuring it for awesome.

Other Errors

You may get a warning like
The ELResolvers for JSF were not registered with the JSP container.
This is irrevelant (who wants to go back to JSP anyway?)

Upon loading up a page, you may get a warning like the following:
[INFO] WARNING: /faces/index.xhtml: com.sun.faces.context.FacesFileNotFoundException: /index.xhtml Not Found in ExternalContext as a Resource
This is a fancy way of saying 404 not found and is most likely caused by confusion about servlet mappings and where the real root of your webspace is.  We mentioned that the root was /Deployed Resources as a non-jsf project and this looked to be a duplicate of /war.  After converting to JSF only /WebContent mattered and you could delete /war after gutting it for files (e.g. an index.xhtml put into /war won't show up in the WAR file, it's super intuitive).   Also, just because the servlet mapping is for /facelets/ doesn't mean that there has to be an actual directory called facelets holding your index.xhtml.  The mapping removes the facelets part and searches your regular old /WebContent directory for the file.  If you put the file into /WebContent/facelets/index.xhtml it'll be missed and you'll get this error!  This part is also hyper-intuitive.  Stackoverflow, again, helped me out a lot to figure this out.  You can also review your project settings by going to your project properties -> Web Deployment Assembly to see how it works for yourself.

Conclusion

This was quite a long ride with, yes I counted, fifteen (15!) possible errors on the way and one zombie process... that would cause a locked file error on a mvn clean.  We covered how to create a Maven Google App Engine JSP project, how to create a JSF project, and how to convert the JSF project to use Maven and the Google App Engine.  Now that you have this working, you can actually get going on your features!

Happy coding all.

Wednesday, August 14, 2013

JSF 2.2 with Google App Engine: A Hurricane of Errors

Three days trying to do what should be a simple upgrade from the JSP Hello World to JSF and it still isn't working.

Long story short, when you get started with Google App Engine you'll find a nifty tutorial from Google that gets you up and going with a simple Guestbook JSP project.  I use Maven with my Eclipse so I used the Maven Archetype instead (also JSP).  At the time I was unable to find a detailed tutorial that starts with JSF to begin with.  There will be a future post with my experience of using that one instead (UPDATE: done, see this post).

As is, I setup the configuration for JSF and Apache MyFaces doing it the old-fashioned, manual way.  I had problems finding documentation on how to do it (and couldn't even find it again).  So, this is what NOT to do:

  1. Include Apache MyFaces in your Maven dependencies.
  2. Update your web.xml to be at least version 2.5 (this is actually a good idea) and include the following
(UPDATE: below code is properly presented now)

  Faces Servlet
  javax.faces.webapp.FacesServlet
  1



  Faces Servlet
  /faces/*
  3. Put a simple JSF hello world file into your /faces directory and load it up.  Even better, don't use an EL #{} expression so that you don't know that EL is broken until much, much later.

As stated, this worked three years ago with Eclipse 3.6 or so, but NOW Eclipse 4.3 Kepler has a concept called Project Facets under the Project properties screen and if you don't specify that you're using JSF here... it blows away your custom web.xml to the default jsp version.  This was Gotcha #1.

After reverting that mess and configuring the Facet I'm expecting a smooth ride... but get the now dredded: javax.naming.InitialContext is a restricted class error, and try the fix suggested by the link just previous.  I do not catch the subtext that this fix is only for Sun's (not Apache's) JSF implementation, and for an older version than I'm using at that!  So I change to Sun's JSF, track down the new WebConfiguration.java and comment out the needed code and at least it compiles but it still doesn't work, so I go back to MyFaces, download the source and comment out their references that I track down.  Then I have to track down a couple of other libraries that the one source file uses and it finally compiles.  At least the Hello World works at this point.  Now I know that the more recent JSF implementations have this issue fixed!  So don't mess around with commenting out the InitialContext code, just change the JSF implementation (the latest Mojarra works).  If you're keeping track, these are Gotchas 2 to 7.

Upgrading to Facelets is as easy as it is supposed to be.  However, this is when I realize that my EL isn't working.  After trying and reading various articles I came across new errors.  I found that I got ClassNotFoundException: javax.faces.webapp.FacesServlet and the ELResolvers for JSF were not registered with the JSP container not because it could not be found, but because it could be found too often (and I had to include it as provided instead of as a jar).  The novel cannot_find_facelet_taglib turned out to just be an Eclipse thing.  All in all, I still wasn't able to patch it up after finding about 6-12 other gotchas.

Friday, April 5, 2013

Senior Developer Interviews: Tales from the Trenches

From my experience as a Junior Software Engineer and Java Developer, since there is such high demand for software developers as soon as you qualify for a job in the field you have a pretty good chance of landing one in short order.  Trying to go for a Senior Developer job broke the mold in a number of ways.

First off, people rise up through the pay grades for the first two levels pretty rapidly, which means that you're competing with people with approximately your experience level.  However, people with TEN years experience can be applying for a Senior Developer job.  This of course means that the required 5+ years experience is going to put your résumé not looking too hot on paper.  However, you can tell yourself that you "punch above your weight" so you'll impress them on the purely technical side.  Easier said than done as they say.

In the first two tiers, you're treated as a technical specialist.  You just have to be an expert in JavaScript OR Java OR SQL, and you're not even really expected to know in detail how those fussy clusters of computers with their web containers work in detail, that's IT's job right?  Not at the Senior level though.  You're expected to be able to prance about the entire software stack with ease and grace.  Saying that the JavaScript prototype concept is kinda like Java inheritance and leaving at that isn't going to cut it.  Confusing your jQuery with your XPath is not going to cut it.  Not knowing how to make a Java Singleton a true Singleton when deployed to a clustered environment isn't going to cut it.  Not knowing the difference between an inner and outer SQL joins isn't going to cut it.  Not knowing the details of your web containers' class loader isn't going to cut it.  On top of all of this, you're expected to have excellent soft skills at this level as well.

Just getting over social anxiety by taking a metric ton of Prozac every day is just the preliminaries of the soft skills you're going to need.  In addition to being able to charm people ("Hay!  I thought engineers were allowed to be socially awkward!"  Nope) and having the standard "Excellent Written and Verbal Communication Skills" where you thought communication skills were being able to feign interest in Steve's ukulele collection and your bosses Whole Foods shopping, veiled "spirituality" references and superstitious neo-hippy quasi-Eastern bull****, but also be able to orate and deliver technical speeches / presentations and be able to handle yourself in the office-politics charged meetings that you'll be invited to more and more. All the while keeping your code throughput high and keeping your inboxes at 0 (you also should have read Getting Things Done by now, or the context switching will require a few buckets of daily anti-psychotics as well).  Did I mention a strong social media presence and a great Klout score too?

In summary to snag that $100k+ Senior Developer job you won't just need to hone your existing skill sets, but learn many additional ones as well.  You will need to possibly hold a regular Programmer position until you have 8-10 years experience.  You will need to know the entire software stack to the point of being a quasi-superhero of computation.  Lastly you will need truly overwhelming social skills, including conducting presentations, giving prepared speeches and attending and holding meetings.  All in all, I have about 7,000 pages of books queued up to read to bring myself up to these levels, because possibly the most valuable skill you can have is being able to rise to a challenge.

Wednesday, January 23, 2013

Drinking from the Firehose... again...

If you don't know, drinking from the firehose means that you are inundated with information and need to parse through and absorb it quickly.  Most typically it occurs in a difficult course or changing jobs.  Changing to starting your own company is no exception.

First order of business is almost always a business plan, but since I never "got" business plans  I picked up my first For Dummies book, Business Plans Kit for Dummies.  It's straightforward and reads like a work book, I'm finding it super useful so far.

Going through it is still exhausting and reminds me of a difficult college course, but it's worth it to pick up a new and highly needed skill.

Sunday, January 20, 2013

Adventures in Certification & New Ads

There is a great forum topic about the Oracle Certified Associate, Java test over at DreamInCode that gives a good overview of what to expect.

Also expect subtle ads from VigLink (see icon) from here on in when I blatantly plug products like encouraging people to not pirate their Adobe software.

Friday, January 18, 2013

Developers and Testers: Breaking Down the Wall

Over at TheServerSide they pointed out an insightful article at Neotys.com on how to get testers and developers to get along and understand each other better.

The salient points were that how easy the testing tool can adapt to change is a big deal, and that having devs go through some QA training to be able to "think like" QA can be beneficial.

Wednesday, January 16, 2013

Wordpress & XAMPP

So, if you're not familiar XAMPP is an all-in-one solution running on multiple platforms (X), Apache, MySql, Perl and PHP (and Tomcat).  I've used this well for PHP development before back around 2006.

However when I went to use this to host a local Wordpress instance for development purposes I kept getting an invalid database connection message.  After hours of struggle and frustration, wikihow had a great article with a step by step tutorial on this.  It turned out my DB encoding was wrong (thanks regular tutorial and error messages for being so obtuse!).

Tuesday, January 15, 2013

Freelancing & News

Ah, the Brave New (to me) World of freelancing.  I already have an old friend who started a business and needs some work done, but for additional work I evaluated some of the freelancing sites: freelancerodesk & elance.  It looks like the general pay-scale of the work offered indicates that freelancer is more for the inexpensive end of the market, odesk is the mid-range and elance has some well paid work there.  I bet a bunch of people contract on elance and then subcontract on odesk or freelancer.

As for the impending ads that were mentioned in an earlier post, they will be delayed indefinitely; read on in peace!

Monday, January 14, 2013

Adventures in Certification: The Journey Begins

At a certain point in your career you may realize that you've specialized on accident, so you may as well "cert up" and go with it.

That was my exact situation, so after a bit of study found out that the Java starting certification is currently (Jan 2013) the Java SE 7 Certification.  Achieving this bestows the title of Oracle Certified Associate (OCA) Java SE 7 (aka OCAJ).  The old Java 6 equivalent appears to still be called a Sun certification, so that caused me some confusion that I hope to spare the reader.  Achieving the cert involves passing the 1Z0-803 exam, and this goes for under $500 USD so it's relatively reasonable given how much the further certs go for.

Copyright belongs to respective
content owners.
How to prepare was a bit vexing as well; an initial Googling of the exam number revealed a few scammy websites at first, the following sites all have poor reviews or prominent ripoffreport rankings: selftestengine.com (self test engine review), actualtests.com(actualtests reviews), pass4sure.com (pass4sure reviews) & realtests.com (realtests reviews).  You DO want to pick up a book on it.  I'm going through the OCA Java SE 7 Programmer I Study Guide by McGraw Hill just to brush up on the basics again.

Lastly, on a different note I'm making the plunge into freelancing, so I finally had to break and put in AdSense ads.  I hope that people find this informative and thanks for reading!