Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Tuesday, 30 August 2011

Null is okay

Most of the bugs that you find or are reported to you in java applications are NullPointerExceptions [1]. NPE are rife in the beginning of a product’s life cycle, and they never go away.


The consequences are bug fixing which checks if:
  • input is null

  • if interface calls return null

  • if method calls return null

  • if properties and collections are null


So this original pizza ordering method:
public void orderPizza(PizzaOrder pizzaOrder){
  for( Pizza pizza : pizzaOrder.getPizzas()){
    kitchen.makePizza(pizza);
  }
}


Morphs into this:
public void orderPizza(PizzaOrder pizzaOrder){
  if( pizzaOrder != null) {
    if( pizzaOrder.getPizzas() != null ||
        Collection.isEmpty(pizzaOrder.getPizzas())) {
      if( kitchen != null) {
        for( Pizza pizza : pizzaOrder.getPizzas()){
          if( pizza != null) {
            kitchen.makePizza(pizza);
          } else {
            throw PizzeriaTechnicalException(“No pizza!!!”);
          }
        }
      } else {
        throw PizzeriaTechnicalException(“No kitchen!!!”);
      }
    } else {
      throw PizzeriaTechnicalException(“No pizzas in order!!!”);
    }
  } else {
    throw PizzeriaTechnicalException(“No pizza order!!!”);
  }
}

(Or alternativly many “assert pizzaOrder != null” that are useless in production)

Madness, and very messy.

Blinkered coding standard:
This happens when code ownership is not clear, when desire for clean code is not existant, when fixing bugs with blinkers on.
When developers are time constrained or scared of changing code.
When development is outsourced but authority and knowledge is not, so refactoring is avoided or not part of SLA.


Why are we so afraid of NullPointerExceptions?
What is wrong with null?


Null is okay. Null is exactly that. Don't avoid it like the plague, but try to not pass the problem to others. Tidy up your gateway interfaces, trust internally null does not happen. If it does then don't hide the problem.

Do not check for null inside you application. Check for null on your edges:

Validate user interface inputs. “Users” are always causing trouble, but we can not live without customers. Validate the essentials, but remember duck walking, don’t scare your customers with perfection validation.

Validate external 3rd party api interfaces. Probably validate internal api interfaces. Remember duck walking. If an internal system quite close to your application erroneously passes null values, fix that system instead. It is a gray zone however so some null pointer validation is fine. Just don’t complicate your system because of the laziness of another within your team/company.

Do not validate calls between your applications layers. Trust the edges has validated the data. Use unit tests to ensure integrity.

Dealing with NPE/Null?


If you encounter a Null or anything resembling empty when not possible etc: throw a NullPointerException. Don’t sugar coat and masquerade it as something else. An NPE is an NPE! It says what it is on the tin! It is easily understood by all developers, and easily traced. Obviously don’t show that to the end user, but don’t catch it too far down your stack.

If you get bug report about an NPE. Fix the edge validation, factory generation or inside the api call. Do not add a “== null“ condition inside your application.

It is easier to avoid internal NPE by not passing external DTO and domain objects through your own application. If you act on it, it should be your applications objects, not an external one. This avoids complicated null pointer validation.

“Clean Code” book suggest “specific case object” for method calls that may previously return null. I am not a big fan, but it may solve internal api NPEs. I definitely support the pattern of returning empty collections in find* calls instead of null when nothing was found.


How would I deal with Null in the Pizza Order scenario?

PizzaOrder object should be validated beforehand in the interface layer. It is not the responsibility of this method.

Same layer before this method should call a factory method that sets pizzas collection to an empty collection if no pizzas.

Kitchen is always injected or constructed externally to this method and not its responsibility.

Factories in mapping/creating the PizzaOrder before this method call should also ensure no Pizza objects are Null.

The one possible valid check is if there are any pizzas in the order. The Collection.isEmpty(pizzaOrder.getPizzas()) But it is not a null pointer check, as previous interfaces/factories will ensure a collection object exists. However the interface or application before this method call should probably have validated the actual order, to ensure an order contains pizzas!


So Null is okay and NullPointerException can be your friend.

Friday, 2 July 2010

Maven Jetty and Tomcat dependencies with JSP / JSTL errors

I use Jetty as a Maven plugin during development, but tend to run Tomcat as my deployment server. (Not sure "production" is appropiate as it's my personal server). My applications are often java MVC based utilising some form of JSP.

This combination creates a slight issue with dependencies for JSP and JSTL. If you have ever seen this error when running mvn jetty:run:

java.lang.ClassNotFoundException: org.apache.el.ExpressionFactoryImpl

Or these errors when running in tomcat when it was okay in jetty:

javax.servlet.jsp.JspApplicationContext
.getExpressionFactory()Ljavax/el/ExpressionFactory


or

org.apache.jasper.JasperException: Unable to read TLD "META-INF/c.tld" from JAR file

or

java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/catalina/loader/WebappClassLoader) previously initiated loading for a different type with name "javax/el/ExpressionFactory"

Over the last few years I have perservered and solved this flat wheel in different ways. However in my recent deja-vue I now have a tidy solution. (the project where this is visable is my up4 project. github source, demo)

I am utilising the jetty maven plugin, and the tomcat maven plugin to show how this works.


<plugin>
<groupId>org.mortbay.jetty</groupId>
   <artifactId>jetty-maven-plugin</artifactId>
   <version>7.0.2.v20100331</version>
</plugin>
<plugin>
   <groupId>org.codehaus.mojo</groupId>
   <artifactId>tomcat-maven-plugin</artifactId>
</plugin>


To utilise JSP pages and JSTL EL with e.g. Spring MVC / Struts Tiles you perhaps expect these types of maven dependencies, remembering that most containers include support for Servelet API and JSPs:


<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>jsp-api</artifactId>
   <version>2.1</version>
   <scope>compile</scope>
</dependency>
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
</dependency>


If you then try mvn clean jetty:run you may end up with a:

java.lang.ClassNotFoundException: org.apache.el.ExpressionFactoryImpl

A response which will solve the jetty problem is to include some jstl EL dependencies:


<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>jsp-api</artifactId>
   <version>2.1</version>
   <scope>compile</scope>
</dependency>
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
</dependency>
<dependency>
   <groupId>org.apache.tomcat</groupId>
   <artifactId>jasper-el</artifactId>
   <version>6.0.26</version>
</dependency>


mvn jetty:run

This should now work fine in Jetty (test in browser as well).

Now try the application in tomcat: mvn clean tomcat:run . It will moan about unable to read some the JSTL taglibs:

org.apache.jasper.JasperException: Unable to read TLD "META-INF/c.tld" from JAR file

This due to the compile scope of the jsp-api dependency, changing this to provided:


<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>jsp-api</artifactId>
   <version>2.1</version>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
</dependency>
<dependency>
   <groupId>org.apache.tomcat</groupId>
   <artifactId>jasper-el</artifactId>
   <version>6.0.26</version>
</dependency>


Test first in mvn jetty:run , which should be okay.

Then in mvn clean tomcat:run . It starts ok, but on the first browser test this error appears:

javax.servlet.jsp.JspApplicationContext
.getExpressionFactory()Ljavax/el/ExpressionFactory


Okay, so Tomcat does not like JSTL EL dependencies as it provides them itself, so my initial respone was to have a separate profile which changed the scope of the dependency to provided for tomcat builds only. However on further reflection it turns out the spec says JSP & EL should be provided by the container. So in fact the problem lays with Jetty, and it turns out the move to eclipse.org created a licensing issue with JSP, so jetty does not include the appropiate libs. So to fix this the correct dependencies will have to be:

In your plugins section:


<plugin>
   <groupId>org.mortbay.jetty</groupId>
   <artifactId>jetty-maven-plugin</artifactId>
   <version>7.0.2.v20100331</version>
   <dependencies>
     <dependency>
       <groupId>org.mortbay.jetty</groupId>
       <artifactId>jsp-2.1-glassfish</artifactId>
       <version>9.1.1.B60.25.p2</version>
     </dependency>
     <dependency>
       <groupId>org.apache.tomcat</groupId>
       <artifactId>el-api</artifactId>
       <version>6.0.26</version>
     </dependency>
     <dependency>
       <groupId>org.apache.tomcat</groupId>
       <artifactId>jasper-el</artifactId>
       <version>6.0.26</version>
     </dependency>
   </dependencies>
</plugin>


And in your normal dependencies section:


<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>jsp-api</artifactId>
   <version>2.1</version>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
</dependency>
<dependency>
   <groupId>org.apache.tomcat</groupId>
   <artifactId>el-api</artifactId>
   <version>6.0.26</version>
   <scope>provided</scope>
</dependency>
<dependency>
   <groupId>org.apache.tomcat</groupId>
   <artifactId>jasper-el</artifactId>
   <version>6.0.26</version>
   <scope>provided</scope>
</dependency>


mvn jetty:run & mvn tomcat:run

Voila.


Ps. If you are providing a WAR for another jetty container, you may want to create a profile section which include the provided dependencies.

Ps2. If you prefer Sun's EL libs then replace the org.apache.tomcat dependencies with:

<dependency>
   <groupId>javax.el</groupId>
   <artifactId>el-api</artifactId>
   <version>2.2</version>
   <scope>compile</scope>
</dependency>
<dependency>
   <groupId>org.glassfish.web</groupId>
   <artifactId>el-impl</artifactId>
   <scope>runtime</scope>
   <version>2.2</version>
</dependency>

Tuesday, 9 February 2010

oracle java blog - netbeans

So Oracle has now finally gotten their Sun. What does this mean for me and the javasphere?

A lot of people have strong feelings about the aqcuisition/merger and some feel strongly against Oracle. I don't. I don't love Oracle, but I think Java will be fine, if not better with their stewardship.

Java



Oracle needs Java, they use it all over their own product line and obviously especially with their former Bea products Java is core to their business. So an evolving, healthy and competitive Java is in their interest.

So Java, JEE, the Java VM platform etc will be fine, with more money available than at Sun. Actually it may be better as Oracle has a lot more funding and marketing capability, and it may revive the ailing JCP?


But what about the other Sun products, and specifically those related to Java?


Glassfish


I don't use glassfish, at least not directly, so personally I have no strong feelings on how Oracle will proceede with Glassfish compared to its more corporate Weblogic.

I use Weblogic at work and either Jetty or Tomcat on pet projects at home.


Kenai


Kenai was to be killed, but read somewhere today it may be saved.
I don't use it. I have a few projects on Sourceforge, and future ones may be on SF or perhaps google code or Github.


Netbeans


Netbeans however I do use.

In the initial press release by Oracle on its plans for Sun's product line they stated it was to be focused as a scripting IDE and leave JEE, java enterprise level, to their own JDeveloper and Eclipse tools.

I use it with Maven and JEE modules so this feature strategy change would affect me very much. I dabled with eclipse for a few years, and still use when forced to at work, but prefer Netbean's cleaner interface (Its not made by IBM...)

However again in an updated press release they have a seperate java tooling page regarding their plans and they may not restrict it to that. Lets hope not.


Cloud


Oracle killed Sun's cloud computing ambitions. Fine by me. They are not into being a hosting provider.

I use Amazon's ec2 a lot, and will not miss it. However I did not know enough about its features compared to ec2 and Google's App engine. It would have to be much better than those to have been worth it. Maybe it was more like Ubuntu's cloud offering with hardware hosting?


VirtualBox


VirtualBox I do use, and glad it looks like it will be kept as is, I think.


Solaris


I have no strong feelings for or against Solaris, but keeping it competitive is probably in their interest.

The hardware and other areas I am not too bothered about. I used Sparc at university, but not since.

Other links:
http://blogs.oracle.com/devtools/2010/02/updated_faq_for_the_developer.html
http://www.oracle.com/ocom/groups/public/documents/webcontent/038563.pdf

Sunday, 14 September 2008

No value specified for parameter when using MySQL with JPA/Hibernate

I came across a problem when swithching database for a project from HSQLDB to MySQL.

I am using memory based HSQL for unit tests.
I am using file based HSQL for development testing.
I have changed my integration tests to using MySQL from file based HSQL.
Final production release will probably use MySQL or Firebird.
(This isn't commercial work, so no Oracle in any stack...)

But when I switched to MySQL, JPA/Hibernate starting complaining about: No value specified for parameter 2. As usual the generic multiple vendor reasons for using JPA/JDBC usually is not true...

Was a bit dumbfounded with this error, but eventually found the solution : http://opensource.atlassian.com/projects/hibernate/browse/HHH-2605.

As it turns out there is a bug in the version of Hibernate that I use.

I depend on
 <dependencies>
 ...
   <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-   entitymanager</artifactId>
    <version>3.3.1.ga</version>
   </dependency>
 ...
 </dependencies>

And this version in the maven repositories was uploaded with wrong transparent dependency to hibernate 3.2.4.ga, which is buggy.

But the quick fix is to change my own dependency management to use version 3.2.6.

Thus this change solved the problem:
 <dependencyManagement>
 ...
   <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate</artifactId>
    <version>3.2.6.ga</version>
   </dependency>
 ...
 </dependencyManagement>

Maven causes problems, but also solves problems...

Thursday, 4 September 2008

Off to javazone!

JavaZone is on again next week. Complete geekfest, but I still enjoy it.

Tend to be very excited the first day, attending most presentations and then start missing a few the second day which is the last day. Spending more time in the stands chatting to companies, trying to blag freebies instead. The first evening also has social events in the evening, which Ive avoided before, as it seemed quite geeky and I was new to this country. Also last year clashed with a football match, which I went to my local pub to watch instead. But suppose Im a geek as well, and Ill have a few pints at least, especially if they are free..

Back to work afterwards I am usually very keen to try all the new technologies and methods.
A few days later dissapointed that I wont have to time investigate most of them.
And a week or two later, forgotten most...

But I do usually pick up something, which does improve my abilities, and then usually able to apply it to work. If not immidietly, I usually apply it to some of my hobby projects instead. Which then usually I reuse at work sometime later, when a new project starts. So I think the two days of non invoicing is worth it in the long run.

Excited to hear or even meet people which work you read on the net. People from Springsource, Google and Sun et al. Last year it was good fun to see the JavaPosse people, listen to Matt Raible, who's work always seem to encounter the same issues I have.

Attended several Mule presentation's last year(2007). Including one by Ross Mason himself, although the one by two guys from Atos Origin, Jos Dirksen and Tijs Rademakers, was much more useful. But even though I think it is a great product, I still haven't had the time to implement it anywhere yet.

Wish those damn 36hour days would soon be standard...

Friday, 14 September 2007

JavaZone

Another JavaZone finished. Two full days of geektime, but fun. Stressfull, as there were too many simultaneous presentations. But it is well planned, with a lot of renowned presentors.

Best presentations was:

* Tijs Rademakers and Jos Dirksen showing how to use Mule in a easy to follow style.

* James Coplien debunking some agile myths.

* Matt Raible comparing web frameworks.



My hands have been itching for a chance to test some the new tech and methods. A vaccine jab at the doctor today killed all that though!

ClubZone, the evening entertainment, while looked good on paper and probably a lot of effort to plan, was a disaster. The problem was the Norway-Greece footy match. Fitting 2500 people (okay probably some were not into football ) into the only place that showed the match was never going to work. So my group all went home to catch the second half. No free beer for us.

Now how can I introduce Mule into our stack, without a special need for it....