Våra medarbetares bloggar
Bloggar
2010-07-05
Magnus K Karlsson
Your First Cup of Coffee
A friend of mine asked me to provide a simple getting started guide for a first time Java programmer and it so happened it were other people that also wanted the same thing, so all of you out there here it comes, a simple learning by example guide in Java.
The example is a simple Web application that do simple Create, Retrieve, Update and Delete (CRUD) operation against a MySQL database.
Before starting writing you need to install the following on your system.
- Java 1.6 SE (http://java.sun.com/javase/downloads/index.jsp)
- MySQL Server and Query Browser (http://dev.mysql.com/downloads/)
- Maven2 (http://maven.apache.org/download.html)
- Eclipse EE 3.5.2 (http://eclipse.org/downloads/)
That's it! That took 3 minutes on a modest Internet connection. Are you still stuck on downloading the files on your Windows machine? And thereafter looking forward to reboot you system after each installation?
The Eclipse Ubuntu installation bundle is sadly quite old and therefore it is better to download the zip file manually and extracted it anywhere of you liking and run eclipse.exe (eclipse) in the eclipse folder.
Now lets create your database. Start the MySQL Query Browser and right click in the Schemata dockable window and then select Create Schema.... Enter simpledb.
Now double click on the newly created schema and then right click again to create a new table.
From here you can take several paths, either create a new project with maven archetype 'simple-webapp' (http://www.sonatype.com/books/mvnex-book/reference/web-sect-creating-project.html) or you can install the m2eclipse plugin (http://m2eclipse.sonatype.org/installing-m2eclipse.html) and create your project from Eclipse. Here, I will hopefully, choose the easiest way and do it manually, since we only will be needing two source files, where one will be empty – web.xml and index.jsp.
Now create you Maven Project Object Model file pom.xml in first-coffee/pom.xml
Now create your first-coffee/src/main/webapp/WEB-INF/web.xml
And finally your dynamic web page, where all your work be done.
To test your application, simply start the Maven built in web server, from your first-coffee directory.
Now open your web browser and enter the address http://localhost:8080/first-coffee/.
If you want to continue to further evolve this simple example, you can leave the jetty server running and simply refresh you web server, after saving your changes.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-07-05
2010-07-03
Magnus K Karlsson
Getting Starting with Google Web Toolkit, GWT, Development
To get started first install appropriate plug-in for your IDE, in this article we will use Eclipse, but there are other great plug-in for other IDE as well.
Eclipse GWT plugin
http://code.google.com/eclipse/docs/download.html
One of the biggest difference between GWT 1.* and 2.* is the ability to debug and run your GWT application without the need to render/compile it. Now you can directly run/debug your GWT Java code without the time consuming compile step. But to do this you first need to install a plug-in to your web browser.
GWT Development Mode plugin for Firefox, IE and Safari
http://groups.google.com/group/google-web-toolkit/msg/51c5a09630ac61dc
After restarting Eclipse and your Web browser you are now ready to start developing. Begin with creating a new project and select Google → Web Application Project.
Enter project details. In this article we will not create a Google App Engine Application, which is a platform for writing cloud application for the Google cloud platform. To read more about Google App Engine, visit http://code.google.com/appengine/.
After finishing creating your project. Lets fire it up and start debug the complete GWT project. The GWT team has already configured a default debug goal. So simple press the debug icon in the Eclipse toolbar.
Now is a URL presented in the Eclipse Console output View. Right click on that URL and select Copy. Paste the URL in your web browser.
Now lets set a breakpoint in your application and the enter a name in your browser and click submit. And now you are debugging your first GWT application.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-07-03
2010-07-01
Magnus K Karlsson
Getting Started with Apache Camel and Prepare for Apache ServiceMix Deployment
Apache Camel is dream framework for any developers that is confronting with any type of integration task. What makes Apache Camel so great is:
- Testability. It is design from the beginning to be a framework that going to support Test Driven Development. With this follows a fast development cycle, since all code can be debugged and executed from a simple JUnit test case.
- Solves the two foremost problem that an integrator faces:
- Seamless protocol crossing, i.e. no coding for fetching data from e.g. HTTP and forwarding it to JMS.
- Default implementation of Enterprise Integration Pattern (http://www.eaipatterns.com/toc.html) that is easy to extend and configure. If you are not familiar with EIP, I recommend you to take the time and read the EIP homepage or if you do not want to miss a thing read the complete book written by Hophe and Woolf (http://www.amazon.com/Enterprise-Integration-Patterns-Designing-Deploying/dp/0321200683).
The next best thing is that Apache Camel is a POJO based solution, which means that it can be deployed and ran in any deployment environment:
- Standalone Java Application
- Web Container
- J2EE Container
When talking of deployment and integration the most common question is. What about ESB? And this is also when Apache Camel shines. Apache Camel is fully supported by Apache Camel parent project Apache ServiceMix, that supports the industry standard Java Business Integration standard. The JBI specification has been criticized about being a slow way of developing integration software and in many aspect that is true, but with Apache Camel as core developing framework that is no longer true.
The reason to select an ESB platform to deploy your integration software is:
- Management. The ESB platform is specially design to manage integration programs.
- Redundancy and Scalability. A good ESB platform is specifically design to handle these issues when the load and uptime requirements increases.
But one thing, that in my opinion, the Apache Camel homepage lack is good starting example of showing the above strength. So lets get started with NOT writing a production code example, but instead lets write a JUnit test case that you can debug, then you can continue of writing your production code.
In the below example I will also take into account that one day, you might want or NOT take the next step and move your Apache Camel code into a full blown ESB environment.
Lets first look at your Maven pom.xml.
To read more about all configuration options for the above endpoints, see http://camel.apache.org/components.html
An Apache Camel route can also be configured in a XML file, which is the natural choice since you want things to configurable and not static defined in a Java class, but more about in my next blog.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-07-01
2010-06-28
Magnus K Karlsson
Problem Running Eclipse on Ubuntu 10.04 (Lucid Lynx)
I have been using Ubuntu for some time and it is really a great OS, but it is amazing why it is always Eclipse that brings the most headache when upgrading Ubuntu. For a couple a days ago I upgraded to Ubuntu 10.04, and everything works smoothly until I started Eclipse 3.5 SR1, with bug fixes I have previously described.
http://magnus-k-karlsson.blogspot.com/2009/11/problem-running-eclipse-in-ubuntu-910.html
This time the solution was to upgrade to Eclipse 3.5 SR 2 (Galileo), without the above bug fix. But thereafter m2eclipse gave me some problem, but now it seams to work after reinstalling m2eclipse and following the guideline in
http://m2eclipse.sonatype.org/installing-m2eclipse.html
“Note about 0.9.8 Workspace Incompatibility: If you are using m2eclipse 0.10.0 with a workspace that contains projects created under m2eclipse 0.9.8, you must remove the workspaceState.ser file. The workspaceState.ser file is located within the workspace directory in $workspacedir/.metadata/.plugins/org.maven.ide.eclipse/workspaceState.ser. If you remove this file, m2eclipse 0.10.0 will regenerate it as needed.”
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-06-28
2010-04-28
Divine Programmer
Slides from seminar on Dynamic Languages
The following are slides from a seminar on Dynamic programming langauges, given at MSC Konsult, Stockholm, April 28, 2010.
Better Software with Dynamic Languages
Mikael Kindborg
2010-04-28
License: Creative Commons Attribution-Noncommercial-Share Alike 2.5 Sweden License
Programming background
Programming languages I have used:
ASTA 1982
Cobol 1982
Simula 1983-1984
CS4 1983
Lisp 1983-1990, 2000-2003 *
Logo 1983-1984 *
Prolog 1984-1985
Pascal 1985-1986 *
C 1985-1999 *
Scheme 1987-1988
Smalltalk 1985-1989, 2003-2010 *
HyperTalk/SuperTalk 1997-1991 *
Lingo 1990-1994, 1997 *
C++ 1993-1999, 2006-2008 *
PowerBuilder 1995-1996 *
Visual Basic 1996 *
Java 1995-2010 *
JavaScript 1995-1999, 2009-2010 *
ToonTalk 1999-2006
PHP 2001-2010 *
Erlang 2002, 2004, 2008
Oz 2003-2005
Python 2003-2010 *
Ruby 2005, 2008
(* = paid work)
Children's programming tools I have developed:
Concurrent Comics
Magic Words
Favourite languages:
C
Lisp
Smalltalk
Python
JavaScript (CoffeScript)
Language I would like to learn:
Factor
Habits, conciousness, awareness
- Who has decided which language you are using in your project?
- Why is it used?
- What are the alternatives?
World's most popular programming environment
- Dynamic typing
- Strong typing
- Incremental
- Modeless (no build cycle)
- Visual/spatial
- Image-based
- Functional
This happens to be the spreadsheet!
Resolver - Spreadsheet in Python
This is an advanced spreadsheet that uses Python:
Prototyping vs Production
Dynamic languages are good for prototyping because they are fast to develop in.
Static languages are good for production because they are slow to develop in?
Myths
- Dynamic languages are slow (Scheme/Lisp, Erlang, Node.js (JavaScript) are fast)
- Dynamic languages cannot scale (Erlang, Smalltalk, GemStone/S scale)
- Dynamic languages are not safe (Erlang is for real-time systems)
- Dynamic languages are harder to code in, inexperienced programmers can screw up too easily
- Dynamic languages are a new trend. (Dynamic languages were big in 1980,
boosted by AI-research, Lisp, Smalltalk, Prolog, Concurrent Logic Programming, Logo)
Benchmarks: http://shootout.alioth.debian.org/
History
Modern languages and user interfaces have one big influence, Smalltalk and Alan Kay's team at Xerox PARC 1970-1980
- DynaBook
- Object-oriented programming
- Overlapping windows
- Bitmapped graphics
- Mouse interaction
- Networking (Ethernet)
- Font technology
- Printing technology
- Desktop publishing
http://gagne.homedns.org/~tgagne/contrib/EarlyHistoryST.html
Alan Kay Quotes
"Actually I made up the term 'object-oriented', and I can tell you I did not have C++ in mind."
"I'm not against types, but I don't know of any type systems that aren't a complete pain, so I still like dynamic typing."
"Java is the most distressing thing to hit computing since MS-DOS."
Demo of Squeak/Pharo
http://www.pharo-project.org/home
Code example:
Morph subclass: #Drawing
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'MyClasses'
initialize
super initialize.
self color: Color white.
self borderColor: Color black.
self borderWidth: 2.
self extent: 600@400.
self position: 50@50.
self clipSubmorphs: true.
self on: #mouseDown send: #createCircle: to: self.
createCircle: event
| circle |
circle := EllipseMorph new.
circle color: Color red.
circle borderColor: Color black.
circle borderWidth: 2.
circle extent: 100@100.
circle center: event position.
self addMorphFront: circle.
StrongTalk and the history of the Java Jitter
To: self-interest@self.smli.com
Subject: Sun buys Java compiler technology based upon Self!!!
From: keith@uniteq.com (Keith Hankin)
Date: Tue, 18 Feb 1997 17:38:17 -0800
Sun has just announced that they are buying Animorphic Systems, which for the
last 2+ years has been developing JIT compiler technology for Java and
Smalltalk. And, guess what? It's based upon the Self project!!!
---
Source: http://www.merlintec.com/old-self-interest/msg01011.html
From: Dave Griswold <David.Griswold....@gmail.com>
Date: Tue, 2 Sep 2008 12:14:32 -0700 (PDT)
Local: Tues, Sep 2 2008 9:14 pm
Subject: Chrome and V8
Hi everyone,
It's been a while, but now that Google has announced Chrome and V8, I
can finally make a little clearer a major reason why I haven't been
pushing Strongtalk development for quite a while: Chrome's new
JavaScript engine V8.
The V8 development team has multiple members of the original
Animorphic team; it is headed by Lars Bak, who was the technical lead
for both Strongtalk and the HotSpot Java VM (as well as a huge
contributor to the original Self VM). I think that you will find
that V8 has a lot of the creamy goodness of the Strongtalk and Self
VMs, with many big architectural improvements
---
Source: http://groups.google.com/group/strongtalk-general/browse_thread/thread/40eb8f405fbd3041/0abb010f0eac18e9
http://www.strongtalk.org/history.html
On the StrongTalk Type System: It contains the first fully developed strong, static type system for Smalltalk (hence the name Strongtalk).
The type system is both optional and incremental, and operates completely independently of the compiler
technology (which means that normal untyped Smalltalk code runs just as fast as typed code).
Readability
- Shorter code is easier to read and to maintain and refactor
- Need balance between cryptic and expressive
Smalltalk:
square
^self * self
JavaScript:
function square(x) {
return x * x;
}CoffeeScript:
square: (x) ->
x * x
Java:
public int square(int x) {
return x * x;
}CoffeeScript: http://jashkenas.github.com/coffee-script/
More examples
Smalltalk:
self on: #mouseDown send: #createCircle: to: self.
button on: #mouseDown send: #value to: [Object inform: 'You clicked me'].
JavaScript:
button.setOnClickListener(function (view) {
view.setText("You Clicked Me!");
});CoffeeScript:
button.setOnClickListener((view) -> view.setText("You Clicked Me!"))Java:
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
(Button) view).setText(""You Clicked Me!")
}
});More CoffeeScript
CoffeeScript:
mood: greatly_improved if singing
if happy and knows_it
claps_hands()
cha_cha_cha()
date: if friday then sue else jill
expensive: or do_the_math()
Compiles to JavaScript:
var date, expensive, mood;
if (singing) {
mood = greatly_improved;
}
if (happy && knows_it) {
claps_hands();
cha_cha_cha();
}
date = friday ? sue : jill;
expensive = expensive || do_the_math();
Things that make life difficult
Source code analysis is clearly helpful, and optional type
declarations can add value, but in static languages that is not all you get.
You also get some less desirable things:
- Static inheritance relation - cannot be changed at runtime
- Type hierarchy lock in, not true polymorphism
- Interfaces are not protocol specifications, they are hierarchical types
- Primitive types
- Modifiers
- Generics
- Extreme line noise
- Things change, and static types, as the name implies, are not friendly to change
This:
public static final synchronized
List<Map<String, Product>> getProductList() {
List<Map<String, Product>> productList =
new ArrayList<Map<String, Product>>();
...
}
Can be:
def getProductList():
productList = []
...
Strong points of dynamically typed languages
- Fast to develop
- Late binding
- Incremental development (no build cycles)
- Shorter code
- Easier to read code
- Easier to maintain/refactor code
- Aggressive Jitting possible with late binding
- Polymorphism/Duck typing
- High-level constructs, e.g. first-class functions and closures
- Syntax for data structures (tuples, lists)
- DSL-friendly
As one participant at the seminar pointed out, many of these points are also true of functional languages based on type inference, like Haskell and Ocaml.
Duck typing: "If it walks like a duck and talks like a duck, it must be a duck"
What makes Smalltalk special?
- Truly incremental development
- Late binding taken to the extreme
- Source code at your fingertips
- Innovative keyword syntax
- Succinct closure syntax
- Rich programming environment (doit, debugger, inspector, senders/implementors, refactoring browser...)
Weak points
- Type declarations serves as documentation
- Type declarations make refactoring tools more reliable
- Weak typing is a source of mistakes
- Implicit variable declarations are error prone
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-04-28
2010-04-18
Magnus K Karlsson
Administrating JBoss MBean From the Command Line Using twiddle
In production environment you usually monitor and administrate the JBoss Application Server through ssh and command line and this is adequate when starting, stopping and reading logs, but when you want to inspect, see status and change MBean values, the command line alternative is quite limited and since the MBean architecture is central in JBoss one really wants to use the JMX-console. The JMX-console is not the most user friendly tool, but has improved with JBoss 5 and the Web Console.
But there is an alternative if you want (or must) stick with the command line alternative – twiddle. The twiddle tool is not new and has been around since JBoss 4.3. And here follows a short walk through by examples.
To print out help information use:
Here you see the most imported commands: info, get, invoke and setattrs.
To get attribute and operation info:
To get attribute value:
To invoke an operation:
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-04-18
2010-04-15
Divine Programmer
RhinoDroid - JavaScript for Android
RhinoDroid is an experimental JavaScript app that runs on Android. The app contains a tiny HTTP server that accepts PUT requests with JavaScript as content. The app is based on the Mozilla Rhino Engine and the Android port by Brice Lambson.
Update: RhinoDroid is now called DroidScript. Get it at GitHub: http://github.com/divineprog/droidscript
Check ut the browser-based editor for DroidScript: http://droidscript.se
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-04-15
2010-04-06
Divine Programmer
Y Combinator explained
I have spent some time to look into the Y Combinator, a function for defining recursive functions without using conventional recursion support.
The Y Combinator is quite legendary in functional programming, and appears in "The Little Schemer", by Daniel P. Friedman and Matthias Felleisen. The idea is to show how recursion can be expressed in a language that does not support recursion (but has support for higher-order functions). As implementation language I will use JavaScript, and I will also show how Y can be expressed in Smalltalk and in Erlang.
A good article on Y written by James Coglan can be found here: http://blog.jcoglan.com/2008/01/10/deriving-the-y-combinator/. Like James Coglan, I write this blog article to better understand Y, and I use a somewhat different approach to explain it. A tool you can use to interactively experiment with the functions below, is this live browser-based JavaScript editor: http://droidscript.se/jsedit.html
Typically a recursive function is said to "call itself", like this recursive definition of the factorial function in JavaScript:
function factorial(n) {
if (n == 0) { return 1; }
else { return n * factorial(n - 1); }
}
The trick to understand recursion, and the Y Combinator, is that a recursive function actually does not "call itself", it calls an instance of a function that has the same function body, but with its own values for the actual parameters. Thus, recursion is not iterative, but consists of a chain of function calls lined up waiting for each other to return (unless you have optimised tail recursion, but that is another story). When the recursion has reached the end and returns, the function calls that wait return one by one, each using their local variable values to compute their result in the call chain.If I could draw a diagram of this (not easily done with primitive blog tools!), it would become more clear than using plain words. But we can picture the call chain like this:
factorial(3)is the same as:3 * (2 * (1 * (1)))This is what we get if we substitute the calls with the actual variable values in each function instance. The innermost 1 is the number returned by the factorial function when the value of n is zero.The point of Y Combinator is to show that recursion can be expressed without referring to the name of the recursive function. Of little practical relevance, but an interesting exploration of recursive functional structures.
Lets start by this recursive JavaScript function:
function repeat() {
if (confirm("Continue?")) { repeat(); }
}
How can this be written without referring to the name of the function? To do this, we will use an anonymous function that takes another anonymous function as a parameter.Anonymous functions are functions that do not have a name, here is a quick example before we continue.
This:
function twice(n) { return n * 2; }
alert(twice(22));
Can be written as:fun = function(n) { return n * 2 };
alert(fun(22));
Or, if we substitute the variable fun with the expression it refers to:result = (function(n) { return n * 2 }) (22);
alert(result);
Now back to the version of repeat written with anonymous functions:(function(fun) { fun(fun); })
(function(fun) {
if (confirm("Continue?")) { fun(fun); });
What happens here is that the function (function(fun) { fun(fun); }) gets called and "kick-starts" the recursion. This is an anonymous function that takes another function as a parameter. It then calls that function with the very same function as the argument. The actual function being called is the other anonymous function, which is a variation of our continue function. Inside that function, the function is again called, with the very same function as its argument! This means that we will get an endless chain of function calls until the user chooses not to continue, in which case the recursive function application is not called, and the call stack unwinds and the function call chain terminates.Another way to write the same thing:
repeat = (function(fun) {
if (confirm("Continue?")) { fun(fun); });
repeat(repeat);
Here we use a variable to refer to the anonymous function, and apply it to itself. Note that this is not cheating, it is not a named recursive function call, and we could just as well have replaced the occurrences of repeat in the call on the second line with the function expression it refers to.This "trick" of calling a function with another function as a parameter (which happens to be the same function), is at the heart of the Y Combinator.
Before showing Y, we will use one more intermediate step. The above example does not take a parameter, and does not return anything useful. To recursively compute something, say the factorial of a number, we need to be able to supply parameters to and return values from the recursive function applications.
Here is factorial written as a "kick-started" anonymous recursive function; then we call the function using the variable factorial, which refers to the expression that starts the computation:
factorial = (function(fun) { return fun(fun); })
(function(fun) {
return function(n) {
return n == 0 ? 1 : n * fun(fun)(n - 1); } } );
alter(factorial(9));
Tadam! Here we have proper recursion without using named functions. But what does the variable factorial in the above piece of code refer to? It refers to an instance of the anonymous function that starts on line 3, with the local variable fun referring to the anonymous function that starts on line 2. The function returned on line 3 is an example of a closure; a function instance that has some of its local variables initialised, but has not yet started to execute. On line 5, that function gets called with the argument value 9. And on line 4 the same process continues and drives the recursion.It is still a bit cumbersome and non-general to have to apply fun to itself inside factorial. It would be nicer to have something that looks like a proper recursive function call, and this is what Y accomplishes.
Finally, here is the definition of Y Combinator, using a style similar to the one we have used above:
Y = function(fun) {
return (function(recurse) { return recurse(recurse); })
(function(recurse) { return function(x) {
return fun(recurse(recurse))(x); }; });
};
Y neatly packages the recursive function application into one single closure; the function that is returned on line 3 above. The difference from the previous example is that we have separated the function fun that does the specific computation (factorial in our example below) from the function that does the recursive application (recurse). It should also be noted that this definition of Y is limited to recursive functions that take one argument.Y is used with functions that have this form:
factorial = function(recurse) {
return function(n) {
return n == 0 ? 1 : n * recurse(n - 1); } };
};
And here is how to call it:alert(Y(factorial)(9));
Y can (as far as I know) be written in any language that supports higher-order functions and closures. Here is a version in Smalltalk that uses block closures:
y := [:fun | [:recurse | recurse value: recurse] value:
[:recurse | [:x | (fun value:
(recurse value: recurse)) value: x]]].
Example on use (produces a pretty big number):factorial := [:recurse | [:n | n = 0
ifTrue: [1]
ifFalse: [n * (recurse value: n - 1)]]].
(y value: factorial) value: 5000.Erlang is a cool functional language, and here goes two variations of Y:Y = fun(Function) ->
(fun(Recurse) -> Recurse(Recurse) end)
(fun(Recurse) -> fun(X) ->
(Function(Recurse(Recurse)))(X) end end) end.
Somewhat simplified with a variable that refers to the recursive function:Y = fun(Function) ->
Go = fun(Recurse) -> fun(X) ->
(Function(Recurse(Recurse)))(X) end end,
Go(Go) end.
And how to use (Erlang too can handle big numbers):Factorial = fun(Recurse) ->
fun(0) -> 1;
(N) -> N * Recurse(N - 1) end end.
(Y(Factorial))(5000).
A good way to understand how the above code examples work is to draw diagrams on paper of how the anonymous functions are instantiated and called.Y Combinator is also the name of a start-up venture firm funded by Paul Graham.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-04-06
2010-04-05
Divine Programmer
New version of DroidScript - JavaScript on Android
There is a new version of DroidScript available, see the DroidScript blog:
http://droidscript.blogspot.com/2010/04/version-4-of-droidscript.html
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-04-05
2010-04-05
Android development in Scheme - How to build Kawa for Android SDK 2.0
If you are into languages like Lisp and Scheme, you will appreciate Kawa, a Scheme implementation written in Java. Thanks to the work of Per Bothner, Kawa is available for Android.
The following is a how-to for installing Kawa for Android SDK 2.0 and getting started to write Scheme programs for Android. The how-to is based on a blog entry by Per Bothner. Note that you need to install Android SDK 2.0 before you proceed.
First build Kawa:
1) Go to the directory where you want Kawa to be installed. On my machine, this is:
cd /home/miki/android
Then download the sources from the Kava svn-repository with the command:
svn -q checkout svn://sourceware.org/svn/kawa/trunk kawa
2) Configure and build Kawa for Android. Go to the kawa directory and run configure, then make. You need to supply the location of the android.jar file in the Android 2.0 SDK. On my machine, the command sequence is:
cd /home/miki/android/kawa
./configure --with-android=/home/miki/android/android-sdk-linux/platforms/android-2.0/android.jar --disable-xquery
make
Next, create a Scheme project:
3) We will start by creating a standard Android Java project, and then modify it.
This is how you create a project template:
android create project \
--target 1 \
--name HelloScheme \
--path /home/miki/android/projects/HelloScheme \
--activity HelloScheme \
--package miki.helloscheme
4) Now, we will modify the project so that it can compile Scheme files. First of all, delete the generated Java source file (I'm using the full path in these examples, for clarity):
rm /home/miki/android/projects/HelloScheme/src/miki/helloscheme/HelloScheme.java
Copy the Kawa jar-file to your project's lib-folder (this is where external libs are stored; alternatively you can create a soft link to the kawa-1.9.90.jar):
cp /home/miki/android/kawa/kawa-1.9.90.jar /home/miki/android/projects/HelloScheme/libs/kawa.jar
Then replace /home/miki/android/projects/HelloScheme/build.xml with this customised version of build.xml.
The project is now configured to build Scheme programs.
Finally, write the Scheme version of Hello World:
5) Open a text editor and create the file: /home/miki/android/projects/HelloScheme/src/miki/helloscheme/HelloScheme.scm
Enter the following code into the file:
(module-extends android.app.Activity)
(module-name miki.helloscheme.HelloScheme)
(define (onCreate (savedInstanceState :: android.os.Bundle)) :: void
(invoke-special android.app.Activity (this) 'onCreate savedInstanceState)
(let ((textview :: android.widget.TextView (make android.widget.TextView (this))))
(textview:setText "Hello, Android from Kawa Scheme!")
((this):setContentView textview)))
There is a more compact version of this program on Per Bothner's blog, but I didn't get it to work at the time of writing this.
Build and install on the emulator with:
ant install
Note that eval does not seem to be supported yet. Hopefully the ability to dynamically compile to Dalvik bytecode will be included into Kawa in the future.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-04-05
2010-03-26
Divine Programmer
Sikuli - Python source code with pictures
I love Sikuli! What I like most is that the source code contains pictures! Since I have a background in visual programming and programming languages based on comic strips, one might have guessed that I would fall for Sikuli :-) Even better, the programming language is Python (Jython), which makes for really clean code.
Now, what is Sikuli? It is a tool for scripting user interfaces, and it is based on matching images (for example an image of a button in the ui). I introduced Sikuli to a client the other day, and now they are using it to create automated ui tests for a web application.
I have one hint, importing modules with Python's standard import statement does not work, instead use execfile to load your Python modules (see link below).
Links:
http://groups.csail.mit.edu/uid/sikuli/
https://answers.launchpad.net/sikuli/+question/102003
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-03-26
2010-03-24
Divine Programmer
Talk on dynamic Android apps at SWDC2010
I will be giving a talk on dynamic languages on Android at the Scandinavian Web Developer Conference 2010. It goes without saying that I am proud of being invited to speak at this high-profile conference. I am looking forward to Marcus Ahnve talking about TDD and Android, and to Nikolai Onken's talk on accessing hardware from the browser, to name a few.
It is interesting to note that after years of having a trend towards browser based applications, the popularity of iPhone and Android has shifted focus back to "fat clients" in the form of mobile apps. Obviously, native apps have the potential for a richer user interface experience than what is possible with today's browser based apps.
But mobile apps tend to be a bit heavy going. In the case of iPhone, this is especially noteworthy. Not only is there a substantial development cycle (edit, compile, run) for native apps, Apple's notorious process for accepting apps to the app store stretches the deployment cycle to the magnitude of weeks.
Android development and deployment is quite smooth, thanks to the Eclipse plugin for Android, and to the fact that one can easily and legally deploy the app on any web site (you are not restricted to Android Market). Still there is some effort involved in deploying and installing new versions of an app. And the development process is still based on the build centric edit-compile-run cycle.
When it comes to web development, there is no need to rebuild and redeploy the application on every edit-run cycle. Thanks to JavaScript being a dynamic language, you can edit and reload only the part that has been updated. A web application is also trivial to deploy and upgrade (ahem, well in theory that is ;-).
In my talk at SWDC2010, I will discuss how dynamic languages like JavaScript can be used as a basis for a platform where applications can be deployed and updated with the same ease as for browser based applications. Furthermore, I will discuss how to take advantage of the dynamic nature of JavaScript for incremental development of applications, and demo the interactive editor in DroidScript, which is a simplistic but illustrative example of a Smalltalk inspired programming tool for Android.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-03-24
2010-03-23
Magnus K Karlsson
How To Remove Automatically Started Programs in Ubuntu 9.10 Karmic Koala
I while ago I blogged about how to setup Apache mod_proxy as a reverse proxy and I installed Tomcat and Apache Web Server with Synaptic Package Manager. The Synaptic Package Manager worked flawless as usual, but it left me with one problem. The Tomcat Server did start automatically every time I booted Ubuntu, this is typically not wanted on a developer laptop, since you probably also are using some other Java Container that is default using port 8080.
Before we dive into how to remove the auto start in Ubuntu, lets first see how things are configured to be automatically started. As you know the start scripts are located in the
And to make programs autostart then there are soft links in the
There are several /etc/rc catalogs, and here follows the extract from one of mine catalog.
So one obvious option would be to directly delete all the soft links in these catalogs, but this is error prone and not recommended, but also it exists a tool to do exactly this – update-rc.d.
Now is Tomcat no longer automatically started when booting Ubuntu.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-03-23
2010-03-21
Divine Programmer
More DroidScript
I have written a couple of code examples that illustrate how to create ListViews in JavaScript on Android. See the DroidScript blog: http://droidscript.blogspot.com
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-03-21
2010-03-03
Divine Programmer
Google Closure
These are notes for a talk on Google Closure I will give tomorrow at GTUG Stockholm.
Note that Google Closure is a JavaScript library and toolkit, not to be confused with the Lisp dialect Clojure (which happens to be pronounced as "closure").
Overview
The Closure toolkit consists of the following parts:
- Closure Compiler - JS to JS compiler; optimises and checks your JavaScript code.
- Closure Library - very comprehensive; UI widgets, graphics, modules, packaging, DOM manipulation, communication, test framework, and much more.
- Closure Templates - dynamic generation of HTML using a template language; "small components that you compose to form your user interface"; for both client side (JavaScript) and server side (Java).
- Closure is used by large-scale web applications; it is the foundation for Gmail, Calendar, Docs, Blogger, and other Google products.
The compiler is an optimising JavaScript to JavaScript compiler. There is an interactive compiler tool available that is very cool, just paste in your JavaScript and optimise it. There is also Service API for calling the compiler from a program. One feature of the compiler is the optional use of doc tags annotations and type expressions for providing type hints etc.
As an experiment I ran the jQuery library through the compiler. Here are the numbers:
Compiling http://code.jquery.com/jquery-1.4.2.js
Original Size: 160.01KB (45.04KB gzipped)
Compiled Size: 63.86KB (22.75KB gzipped)
Saved 60.09% off the original size (49.49% off the gzipped size)
Compiling http://code.jquery.com/jquery-1.4.2.min.js
Original Size: 70.48KB (24.03KB gzipped)
Compiled Size: 63.84KB (22.75KB gzipped)
Saved 9.42% off the original size (5.33% off the gzipped size)
The Google optimiser generates a bit more compact code than the minimised jQuery library. I have not done any performance tests, so I cannot say how the Google version performs compared to the original jQuery code.
Personally, I think it is a bit sad with the tendency to deliver optimised JavaScript code, because one of the truly great things with the web was to be able to view the source of any web page. That boosted knowledge about HTML and web design, and I would prefer if the JavaScript engine would take care of the optimisation. To always have the source code available is a huge advantage. This is one of the things that makes Smalltalk so productive; the code for the whole library and even the compiler is available to study and learn from.
Closure Templates
Closure includes a template language. It provides a common language for both JavaScript (client-side) and Java (server-side), and the idea is to write small, composable units that are used to build web applications. The syntax is based on curly-bracket tags, not as painful for the eye as XML, but it goes without saying that it is a freaky syntax, and one might indeed ask what motivates template languages in general. I have never understood the benefits of having a half-done semi-markup and semi-programing language when you can have the full power of a dynamic language with internal DSLs if needed. A strong point of XML and other markup languages is that they describe structure and content in a declarative way. But you have always had this for free in Lisp, and with proper DSL-design and other language extensions, the same can be done in Python, Ruby, JavaScript, Smalltalk, et. al.
Closure Library
The JavaScript library is the heart of Closure, and it is a massive library that covers most aspects you could ask for when developing advanced web applications. There is a module system, with proper namespaces, and it is easy do define your own namespaces and modules.
A hint; as an alternative to download the entire library from Google's Subversion repository, you can refer to the base file in a script tag, using this url: http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js
JavaScript Live Editor
To get started and dive into the Closure library, I decided to create a web-based JavaScript editor that could interactively evaluate Closure code. I would also use Closure itself when writing the editor. I already had the DroidScript live editor for programming JavaScript on Android, which is implemented using jQuery and CodeMirror. So I took that editor and rewrote it using Google Closure. It is a very small project, just one web page with some embedded JavaScript that evaluates code, but it was an useful experience. The editor, which contains a number of Closure code examples, is here: http://droidscript.se/jseditor
The editor works like a Smalltalk workspace; select a piece of code and evaluate it. This proved to be a useful tool for experimenting with the Closure library, and it should be equally usable for interactive exploration of jQuery, or any JavaScript library, or JavaScript programming in general. I have never understood why most REPLs are command-line oriented. Long time since we used paper-based teletype terminals ;-)
Finally, I wish to give massive amounts of cred. to Marijn Haverbeke, the author of CodeMirror, a syntax highlighting code editor written in JavaScript (note that it is *not* part of the Closure library). It is the best web-based code editor I have seen, with a clean API that is very easy to use.
To sum up on Closure, it is definitely seems like a very capable library. Heavier and more complex than for example jQuery, but for large applications it provides much more support and features. It feels like GWT without Java, and using JavaScript rather than Java is by definition a good thing ;-)
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-03-03
2010-02-28
Magnus K Karlsson
Using JAX-WS in a Web Archive, as a Servlet, Running on JBoss 5.1
In my previous blog I showed how to get started with JAX-WS in a EJB archieve, in this blog I will show you how to do the same thing, but in a web archive instead, as a Servlet. If you think about it, the two different approaches ends with the same result – a Servlet that answer HTTP request with SOAP content.
Now lets create a simple web archieve with Maven archetype plugin.
Now lets add EJB dependency and JBoss Maven plugin that will do our deployment work.
Then we continue with our Web Service class.
Not that we don't need to define a interface. Then we write our web.xml, that points to our concrete Web Service class.
Finally we need to add the JBoss specific web deployment descriptor. Note the location of the file – src/main/webapp/META-INF/jboss-web.xml, i.e. not in the WEB-INF directory, beside the web.xml.
Now we are ready to build and deploy our archieve
Then we start our JBoss server and opens a web browser pointing to http://localhost:8080/ws-web/personServiceBean?wsdl and checks that the web service is working. Instead of building a web service client by hand, we use the soapUI tool.
Now soapUI has created us a testcase that we can double click and click the green play button on.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-02-28
2010-02-25
Magnus K Karlsson
How To See Expiration Date and other Information of a p12 File (PKCS12).
Sooner or later your client or server certificate will expire and it will be nice to update that before it really happens, but to do that you need to know how to get that information. In this blog I will show you how to do that in a Linux environment with openssl, that is a typical scenario when the certificate is located on a remote Linux server that you access with ssh.
First thing to do is to convert the p12 file (PKCS12 format) to X509 format, to do so we use the openssl command.
When prompted enter the password. Now is the content printed out, find out which CN (Common Name) that is for the server, typically it is the dns name of the server. After located the certificate then copy everything between the below start and end tag,
Past the copied content into a file with prefix .crt. If you were on a Windows system you could now simple double click the crt-file and the information of the certification would be display, but here we will continue using openssl. To use openssl, use the below command using the file name of the file you pasted the certificate into.
Now is the expiration date printed among other information.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-02-25
2010-02-21
Magnus K Karlsson
Configure Apache Web Server as Reverse Proxy in front of a Tomcat or J2EE Container
One production like scenario when using SSL or load balancing is to use a Apache Web Server in front of a Java Web Container or J2EE Container. There are two ways to make the Apache Web Server and the behind Java container – mod_proxy or mod_jk. In this blog I will show you how to use the mod_proxy alternative, acting as a reverse proxy. I will also use Ubuntu to show you how easy there is to install software on Ubuntu with Synaptic Package Manager.
The first thing to do is to install Apache Web Server and the Tomcat Container.
After installing the above software you can use the apache2ctl command to view the active sites configuration
or you can also list the files in /etc/apache2/sites-enabled
Before continue you can also check that everything is working by open a web browser and open http://localhost/ (Apache Web Server) and http://localhost:8080/ (Tomcat)
Now we go ahead and creating a new virtual host that is going to act as reverse proxy.
After creating the new site we need to link it from sites-enabled, either use ln -s or you can use the apache tool – a2ensite.
With the configuration in place, you need to separate the virtual host in customapp and default. For a locale environment you can separate them by using different IP – 127.0.0.1 and your computer IP.
The last thing before restarting the Apache Web Server is to install proxy and proxy_http modules you can do that with the Apache tool a2enmod
And finally you need to restart the Apache Web Server.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-02-21
2010-02-20
Divine Programmer
DroidScript - JavaScript for Android
I have published a post at my DroidScript blog that describes a tool for programming Android devices interactively in a web browser using JavaScript.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-02-20
2010-02-18
Magnus K Karlsson
Getting Started with JBoss Web Serivce using JAX-WS on JBoss 5.1 using Maven, OpenEJB and eviware soapUI
The easiest way to get started with writing Web Service is using Java API for XML Web Service, JAX-WS. The downside with this is that the creation of the WSDL file is automatic, and that is not the preferred way of writing cross platform independent web service. If that is your design goal, you should handwrite the WSDL, i.e. contract first. But if you know that the only clients are going to be Java client, than automatically generating the WSDL could be fine.
A good practice when writing all kind of code, is to make the code testable and also make it testable outside the container. To achieve that I will use OpenEJB, if have never heard or used OpenEJB and you are writing EJB 3.0 applications, it is definitely worth the time to check it out.
Lets start with writing a standard Stateless EJB.
src/main/resources/META-INF/ejb-jar.xml
src/main/resources/META-INF/jboss.xml
pom.xml
Now lets test our EJB with OpenEJB. The first thing we need to do, is to add the OpenEJB dependency to our pom.xml
Then we write our JUnit test case.
After verifying that our Stateless Session Bean is working, we now continue to deploy it to the JBoss container.
We start our JBoss container and checks that the EJB is successfully deployed.
Now lets add Web Service support to our EJB.
Now lets write our JUnit test case, to test our web service outside the JBoss container.
Before running the testcase we need to update our pom.xml with a concrete web service implementation.
After running the testcase from withing Eclipse, we can now be confident that we our is executing as expected. Now lets deploy our EJB to the JBoss container.
If you have stopped the JBoss, then restarted and verify that everything is looking healthy in the server log. Verify that the web service is working by firing up a web browser and go to http://localhost:8080/jbossws-example/HelloServiceBean?wsdl, to verify that you see the wsdl file.
Instead of writing a web service client, we are going to use a good test tool for testing web service – eviware soapUI. Start the soapUI and then select new project.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-02-18
2010-02-17
Magnus K Karlsson
Viewing/Monitoring your Log4j Generated Log File with Chainsaw
Chainsaw is a open source tool for viewing and/or monitoring Log4j generating system. But the documentation on the homepage lack some explanation how to get started. To begin with maybe the simplest scenario, to view a log4j generated log file. The first thing one might misunderstand is that you need to defines a new configuration file for Chainsaw, so just pointing to your log4j.xm configuration file is not enough. Lets start with a example.
And the configuration file for Chainsaw.
Before we open Chainsaw lets write a small test program, that generates some log post, so we have something to view.
Now lets open Chainsaw. When first starting Chainsaw you are prompted to define a Receiver. Here we select our configuration file.
After selecting our Chainsaw configuration file, Chainsaw opens our log file in a new tab.
You might have already noticed the different formatting of logFormat attribute, compared with the Log4j and it is a question to me why they have done that. You can read more about the format in the LogFilePatternReceiver Javadoc.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-02-17
2010-02-14
Magnus K Karlsson
Sending Log Errors with Log4j and SMTPAppender
Log4j comes with several Appenders and if you like to send mail notification if severe errors occur the you will be pleased to see, that Log4j comes with a SMTPAppender, but there are some pitfalls when using the SMTP appender:
- The SMTP apppender does not out of the box support a different SMTP port.
- Using secure connection, such as SSL or TLS.
- The derived standardized method setThreshold is ignored, and replaced with TriggeringEventEvaluator class.
If your mailserver is configured to answer on a different port than the default 25 for SMTP, you need to configure the underlying javax.mail.Session property "mail.smtp.port". But when looking at the API for SMTPAppender you see no set method for that. What to do? Writing you own extended log4j class? No, that is not neccessary. If you look at the source code of SMTPAppender, you see the following in the createSession():
These means that SMTPAppender is reading system properties, which means you can add the following argument when starting you application.
This is a not gracefefully way, and sometimes also not applicable, because you are not in charge of the deployment environment. And what happens when you have two different application hosted on the same server, that wants to use different ports?
There is also the oppurtunity to do it programmatically:
This has also drawbacks. For examaple if your application is a J2EE application or a web application your code is not the main start class. You can of course always write a boot strap class, but what happens when you have several bootstrap classes, then things starts to get more hard to overlook for a more junior programmer.
Another way if you have problems settings the System Property is to create a class that implements the interface org.apache.log4j.spi.TriggeringEventEvaluator and there set the system properties and then in your log4j properties or xml file override the default EvaluatorClass for SMTPAppender. This is a little hacky, but it will get the work done and it keeps your code clean from log4j configuration code that should in the first place be placed in the log4j configration file.
Also what is lacking is, if you are deploying to a container you might want to define your java.mail.Session properties in the container and then bind them to JNDI, then it should be nice if Log4j could read these property from JNDI, but that is not possible.
Using Secure Connection
The next problem comes when your mailserver uses secure connection as TLS or SSL, then you need to add the following javax.mail.Session properties:
Bellow follows the source code for the example.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-02-14
2010-02-11
Divine Programmer
Book Review: "Beginning Android"
Book Review: "Beginning Android"
Mark L. Murphy
Apress, 2009
ISBN: 978-1-4302-2419-8
I got a review copy of this book from Apress. Here is the review.
This is a book for programmers who have a basic knowledge of Java and want to get an introduction to the elements of Android programming. The book should be useful for both professionals and hobbyists. It is easy to read and well structured, and not too extensive, which makes it comprehensible. The 350 pages do a good job at covering a fair amount of the Android API. One area that is not covered is development tools, here the book refers to the Android web site (www.android.com). Setting up a development environment for Android can be tricky if you are new to programming, so this is an area where less experienced readers are left on their own.
The book covers Android 1.5, which is an old version by now. I however found the text and the code examples useful also for Android 2.1 development. The back inside cover mentions that there is a companion eBook available. An updated eBook would be of great added value, but it should be provided for free to customers who have purchased the book, not at additional cost as seems to currently be the case.
The style of writing is clear and the text is easy to read. The book is structured into several short chapters, where each chapter covers an aspect of Android development and the related parts of the API. Each chapter begins with an introduction that explains the topics covered in the chapter. Then follows a complete, runnable, and often short and concise code example that illustrates the chapter topic. This makes the book useful as a cookbook.
One not-so-nice aspect of the text is the use of supposedly funny section titles. I find titles like “Mother, May I”, “Halt! Who Goes There?”, ”When IPC Attacks!”, and “Seeing Pestering in Action”, to be quite irritating and distracting. The subject is interesting on its own merits, and the silly section titles actually make it harder to find what you are looking for in the book. There may, however, be readers who will find the titles entertaining. Another less good aspect of the book is the code style used, with no blanks between the parts of an expression. The first chapters use the correctly spaced Java-code style, but the majority of the chapters do not, and this is bad since it can establish bad coding practices among readers (especially beginners).
It is quite common for programming books to list classes and methods in the APIs covered, something which I find superfluous since the most current API documentation is available online. This book does not provide API listings, which is positive because it makes the text more coherent and flowing. It also saves pages, and makes room for more code examples and explanatory texts, which are added values compared to the online API documentation, and a reason for buying a book.
For me, the major value of the book has been as a cookbook of code examples. The examples in the book are often short, clear, useful, and on the spot on what you want to do.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-02-11
2010-02-01
Magnus K Karlsson
Java Generics Example Strategy Pattern
With Java Generics Java has continued its path to make it's language more strong typed, with comparison to all new dynamic language where they have thrown out strong typing. But Java Generics can also be hard to understand and one of the best example to show the main benefit with it is the strategy pattern. Lets start to look of a example.
If we were using Java JDK 1.4 we have to do down-casting in the concrete strategy classes, but with Generics that is not necessary.
The Strategy Context/Client
The Strategy itself
And the extended Data classes
And the extended Strategy
And our test class.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-02-01
2010-01-30
Magnus K Karlsson
Maven Reporting with Cobertura, Dashboard, Change Report, FindBugs and PMD
I have been using maven coberture plugin before but it has one unimplemented function, aggregate cobertura report from multiple module. This can be solved by sonar and dashboard maven plugin, but Sonar requires that is run on a server, i.e. that you have a continuous integration server, but in some cases you have not got there and still is building your application locally than you can use the maven Dashboard plugin.
The parent pom.xml
The jar module pom.xml
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2010-01-30
2010-01-19
Divine Programmer
Twitter and refactoring (totally unrelated!)
I am now on Twitter @divineprog - but don't expect frequent updates, I am not the Twitter type really ;-) But perhaps I will grow fond of it once I learn how to use the Twitter infrastructure.
A couple of days ago, when renaming a bunch of methods in Eclipse using the refactoring function, it struck me, why not make changing the name of something do an automatic refactoring by default? It seems reasoable that if I change the name of en existing object, I would like everyone using the name of that object to update their references, right? It would make sense to ditch source text files and go all the way and manage the source code in an presistent in-memory database (I guess Eclipse maintains some kind of database-like view of the source code). Smalltalk has of course had this since the 70:ies ;-)
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2010-01-19
2009-12-29
Divine Programmer
Interactive development with Clojure
Here is a very nice video demo that illustrates interactive servlet development with Clojure. Same thing could be done on Android using the techniques referred to in the previous post.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-12-29
2009-12-29
Clojure REPL on Android
Found this thread where George Jahad explains how he implemented dynamic evaluation of Clojure on Android. Very cool how he dexed the dexer!
Interactive development and experimentation using a Read-Eval-Print-Loop is a great feature of dynamic languages. Really nice to see that Clojure attracts attention, it would be sad if Lisp would be forgotten. Lisp is one of the most productive languages I have ever worked with, and actually the first programming languages I was paid to program in.
Speaking of REPL, the way you can evaluate text in any window in Smalltalk is truly cool - just select an expression and "doit". I take this feature so for granted that I forget that this is not widely known outside the Smalltalk community. It would be nice to see a programming environment on Android that supports such a style of development, and RhinoDroid is one step on the way. I am working on a web based development tool for interactive programming on Android using JavaScript, hope to have that up and running soon.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-12-29
2009-12-14
Magnus K Karlsson
How to handle XML Schema Version?
Use the Schema verison attribute.
Pros:
- Simple
- No XML Schema enforcement when stepping version and version number is concealed for user.
- Do no use.
Change the Schema location and keep the namespace.
Pros:
- Good för maintaining backward compability. No depending XML files needs to be altered, simply upgrade implementing jar.
- Cannot tell from the XML file which implementing jar version is used.
- Use this technique to handle minor version upgrade.
Example:
http://camel.apache.org/schema/spring/camel-spring-1.6.X.xsd, in version 1.6.0-1.6.3 is the same targetNamespace used.
Change the Schema location and the namespace.
Pros:
- Forces the user to upgrade the client code, when stepping version. Hard versioning control, no chanse to make misstake.
- No seamless upgrade. Upgrade will cost.
- Use this when stepping major version.
For you using JAXB, is it a good reminder that the namspace versionnumber is direclty reflected in the package name. So when uppgrading and if the depending generated code has changed namespace, i.e. package name will the depending code not compile. This can be a advantage since it will directly be apparent where in your code you have the dependencies.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-12-14
2009-12-14
XML Schema Design Pattern - Handling Versioning and Reuse
In my last project I have been working with service orientated integration and ESB, in such an architecture the domain model is represented with a canonical model of a XML schema. There several way you can design your schema which I will describe bellow, but what is more imported is the implication it has on:
- Level of possibility to reuse your canonical model in different service.
- Level of possibility to handle different version of same service.
- Level of possibility to split your canonical data model into bit of pieces and process them in parallel.
Definition:
Root element – the first element a XML must contain. If a schema contains several root element it is possible to slice the XML document into several new XML document.
Global element – the elements that directly comes after the root element, possibly elements are 'element', 'complexType' and 'simpleType'.
Local element – nested element inside global element.
Russian Doll Example
Pros:
- One root element, good for encapsulation.
- All elements are local and encapsulated.
- No reuse of elements.
- Easier to get started with.
Example Book-RussianDoll-v1.0.0.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://ns.msc.se/examples/book-russiandoll/v1_0_0"
xmlns:russ="http://ns.msc.se/examples/book-russiandoll/v1_0_0"
elementFormDefault="qualified">
<xs:element name="book">
<xs:complexType>
<xs:sequence>
<xs:element name="Title" type="xs:string" />
<xs:choice>
<xs:element name="AuthorList" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Author">
<xs:complexType>
<xs:sequence>
<xs:element name="givenName" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Salami Slide
Pros
- Many root elements, the XML file can be sliced into numerous ways.
- All elements are global, which allows reuse in other Schemas.
Cons
- Does not encapsulate and hide the schema.
- Usage of namespaces are almost a most, which makes usage more complex.
Example Book-SalamiSlice-v1.0.0.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://ns.msc.se/examples/book-salamislice/v1_0_0"
xmlns:salv1_0_0="http://ns.msc.se/examples/book-salamislice/v1_0_0"
elementFormDefault="qualified">
<xs:element name="book">
<xs:complexType>
<xs:sequence>
<xs:element ref="salv1_0_0:Title" />
<xs:element ref="salv1_0_0:AuthorList" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Title" type="xs:string" />
<xs:element name="AuthorList">
<xs:complexType>
<xs:sequence>
<xs:element ref="salv1_0_0:Author" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Author">
<xs:complexType>
<xs:sequence>
<xs:element ref="salv1_0_0:GivenName" />
<xs:element ref="salv1_0_0:Surname" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="GivenName" type="xs:string" />
<xs:element name="Surname" type="xs:string" />
</xs:schema>
When generating code via JAXB, wee can see that several classes are annotated with the @XmlRootElement. This says that we have several possible root element.
In the next example we show how to handle version and extending previous schema version.
Example Book-SalamiSlice-v1.0.1.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://ns.msc.se/examples/book-salamislice/v1_0_1"
xmlns:salv1_0_0="http://ns.msc.se/examples/book-salamislice/v1_0_0"
xmlns:salv1_0_1="http://ns.msc.se/examples/book-salamislice/v1_0_1"
elementFormDefault="qualified">
<xs:import namespace="http://ns.msc.se/examples/book-salamislice/v1_0_0" schemaLocation="Book-SalamiSlice-v1.0.0.xsd" />
<xs:element name="book">
<xs:complexType>
<xs:sequence>
<xs:element ref="salv1_0_1:Title" />
<xs:element ref="salv1_0_1:Category" />
<xs:element ref="salv1_0_0:AuthorList" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Title">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="3" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Category" type="xs:string" />
</xs:schema>
Venetian Blind
Pros:
- Only one root element, good for encapsulation.
- All element are global, which allows reuse in other Schemas.
- Usage of namespaces are almost a most, which makes usage more complex.
Example Book-VenetianBlind-v1.0.0.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://ns.msc.se/examples/book-venetianblind/v1_0_0"
xmlns:ven="http://ns.msc.se/examples/book-venetianblind/v1_0_0"
elementFormDefault="qualified">
<xs:element name="Book">
<xs:complexType>
<xs:sequence>
<xs:element name="Title" type="ven:TitleType" />
<xs:element name="AuthorList" type="ven:AuthorListType" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="TitleType">
<xs:restriction base="xs:string">
</xs:restriction>
</xs:simpleType>
<xs:complexType name="AuthorListType">
<xs:sequence>
<xs:element name="Author" type="ven:AuthorType" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="AuthorType">
<xs:sequence>
<xs:element name="GivenName" type="ven:GivenNameType" />
<xs:element name="Surname" type="ven:SurnameType" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="GivenNameType">
<xs:restriction base="xs:string">
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="SurnameType">
<xs:restriction base="xs:string">
</xs:restriction>
</xs:simpleType>
</xs:schema>
Example Book-VenetianBlind-v1.0.1.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://ns.msc.se/examples/book-venetianblind/v1_0_1"
xmlns:ven1_0_0="http://ns.msc.se/examples/book-venetianblind/v1_0_0"
xmlns:ven1_0_1="http://ns.msc.se/examples/book-venetianblind/v1_0_1"
elementFormDefault="qualified">
<xs:import namespace="http://ns.msc.se/examples/book-venetianblind/v1_0_0" schemaLocation="Book-VenetianBlind-v1.0.0.xsd" />
<xs:element name="Book">
<xs:complexType>
<xs:sequence>
<xs:element name="Title" type="ven1_0_1:TitleType" nillable="true" />
<xs:element name="Category" type="ven1_0_1:CategoryType" nillable="true" />
<xs:element name="AuthorList" type="ven1_0_0:AuthorListType" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="TitleType">
<xs:restriction base="xs:string">
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="CategoryType">
<xs:restriction base="xs:string">
<xs:enumeration value="SPORT" />
<xs:enumeration value="COOKING" />
<xs:enumeration value="PROGRAMMING" />
</xs:restriction>
</xs:simpleType>
</xs:schema>
Conclusion
When starting of thinking of Schema one come to the conclusion that schema design is much like tradition OO design, where one must always consider if a properties and method should be hidden or exposed to other classes. The same yields for Schemas and in the real world one would scarcely use just one design pattern, but rather combine them.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-12-14
2009-12-09
Divine Programmer
Domain Specific Languages
Today, I made a presentation on Domain Specific Languages at the MSC Office in Stockholm. The slides are here: http://www.comikit.se/dsl/dsl_talk_20091209/DSLSlides.html Press S to enter slide show mode, use N for next slide and P for previous slide. Or just scroll the document!
The presentation is written in a Python Slide Show DSL I made for the presentation, here is the source for the slides: http://www.comikit.se/dsl/dsl_talk_20091209/DSLSlides.py
The source code for the DSL is here: http://www.comikit.se/dsl/dsl_talk_20091209/SlideShow.py
My next DSL-related project is an interactive Game Development DSL in JavaScript for Android.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-12-09
2009-11-30
Divine Programmer
Interactive JavaScript on Android
I now have working version of a remote JavaScript scripting app running on Android. The app runs a HTTP server that accepts incoming PUT requests with JavaScript code as content. The code is evaluated on the Android, and the result is sent back to the client. Also have a workspace in Squeak/Pharo that I use to evaluate JavaScript on the Android. It is kind of neat to be able to interactively create views, buttons and so on. Will demo this on the upcoming GTUG meeting in Stockholm on Thursday December 3.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-11-30
2009-11-21
Divine Programmer
JavaScript (Rhino) on Android
Finally I have found a great dynamic language for writing Android apps - Rhino, a JavaScript implementation in Java. Rhino can run in interpreted mode, which makes it suitable for running on Dalvik (since on-the-fly byte code generation on Dalvik isn't implemented by dynamic languages, yet).
I used the work by Brice Lambson as a starting point. He has created a version of Rhino for the Android Scripting Environment (ASE). With the new release of the ASE you can now write scripts using JavaScript.
Since I want to write applications for Android in a dynamic language, I decided to experiment with embedding Rhino in an Android app. I created a new Android Java project, grabbed the Rhino jar-file from the ASE web site and dropped it in the libs directory. By browsing the documentation at the Rhino web site, it was quite straightforward to write a working demo.
Here is the code:
package miki.jsapp;
import android.app.Activity;
import android.os.Bundle;
import org.mozilla.javascript.*;
public class JSApp extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
doit(
"var widgets = Packages.android.widget;\n" +
"var view = new widgets.TextView(TheActivity);\n" +
"TheActivity.setContentView(view);\n" +
"var text = 'Hello Android!\\nThis is JavaScript in action!';\n" +
"view.append(text);"
);
}
void doit(String code)
{
// Create an execution environment.
Context cx = Context.enter();
// Turn compilation off.
cx.setOptimizationLevel(-1);
try
{
// Initialize a variable scope with bindnings for
// standard objects (Object, Function, etc.)
Scriptable scope = cx.initStandardObjects();
// Set a global variable that holds the activity instance.
ScriptableObject.putProperty(
scope, "TheActivity", Context.javaToJS(this, scope));
// Evaluate the script.
cx.evaluateString(scope, code, "doit:", 1, null);
}
finally
{
Context.exit();
}
}
}
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-11-21
2009-11-04
Divine Programmer
PyConcordion - Writing Concordion tests in Python
Concordion is an open source test framework that encourages writing tests in a specification driven style. A key aspect is that tests are integrated into the textual specification of the system. This makes it possible to write requirements and tests simultaneously, and from a maintainability point of view, it is a great advantage to have requirements and tests tightly integrated.
PyConcordion allows you to write tests in Python, rather than Java (a very nice feature from the perspective of this blog!).
Each PyConcordion test has two parts, and HTML-file and a Python file. Specifications and declarative definitions of the tests are written in HTML. The scripting parts of the test that connects to the system being tested and implements services for the declarative tests are written in Python. Note that the Python code can be written in a declarative DSL-driven fashion, see the discussion on this page. The principle is to write a specification of a scenario, rather than coding a test script.
To try out PyConcordion, I downloaded PyConcordion and made an example based on this tutorial.
The example defined a very simplictic bank account object, called Account. Here goes the HTML-part of the specification.
File: Account.html
<html xmlns:concordion="http://www.concordion.org/2007/concordion">
<body>
<h1>Account</h1>
<h2>Overview</h2>
<p>The Account object supports the following operations:
<ul>
<li>Ask for the account balance</li>
<li>Deposit an amount</li>
<li>Withdraw an amount</li>
</ul>
</p>
<h2>Examples</h2>
<p>
A new account object has a balance of
<span concordion:assertEquals="getBalance()">0</span>.
</p>
<p>
If I open a new account and deposit
<span concordion:execute="deposit(#TEXT)">1200</span>,
the balance is
<span concordion:assertEquals="getBalance()">1200</span>.
</p>
<p>
If I deposit another
<span concordion:execute="deposit(#TEXT)">600</span>,
the new balance is
<span concordion:assertEquals="getBalance()">1800</span>.
</p>
<p>
If I withdraw
<span concordion:execute="withdraw(#TEXT)">100</span>,
the balance is
<span concordion:assertEquals="getBalance()">1700</span>.
</p>
</body>
</html>
And here is the Python code that defined the Account class.
File: AccountTest.py
#! /usr/bin/python
class AccountTest:
def __init__(self):
self.balance = 0
def getBalance(self):
return str(self.balance)
def deposit(self, amount):
self.balance = self.balance + int(amount)
def withdraw(self, amount):
self.balance = self.balance - int(amount)
To run the test, go to the folder that contains these two files, and run the command:
concordion_folder_runner ./
There are straightforward instructions on the PyConcordion web site on how to install the system under Linux.
When writing Python methods, remember to use self rather than this, especially if you are new to Python, and come from languages like C++, C#, or Java rather than Python. (Actually you can name the self-parameter anything, as it is explictly declared, but the convention is to use self.)
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-11-04
2009-11-02
Magnus K Karlsson
Problem Running Eclipse in Ubuntu 9.10 Karmic Koala
After upgrading to Ubuntu 9.10, Eclipse started to behave strangely. Button seams to be non-responsive, so I googled for a solution and came up with this link.
http://www.norio.be/blog/2009/10/problems-eclipse-buttons-ubuntu-910
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-11-02
2009-11-01
Divine Programmer
How to install Android SDK 2.0
The following is the procedure I used to install the Android SDK 2.0. It applies to Mac OS X and Linux (in my case Ubuntu). Note that Java SDK 1.6 (1.5 should also work?) must to be installed, before installing the Android SDK.
First download the SDK (SDK = Software Development Kit):
1) Download the SDK for your platform at: http://developer.android.com/sdk/
2) Unzip the SDK and move it to the directory where you want it installed. On my Ubuntu machine, I installed it in my home folder:
/home/miki/android/android-sdk-linux/
3) Add the SDK tools directory to the path by adding the following line to .bashrc. On my machine, it is:
export PATH=${PATH}:/home/miki/android/android-sdk-linux/tools
Next download additional SDK components using the Android SDK and AVD Manager:
4) Open the terminal and start the Android SDK and AVD Manager with the command:
android
5) Now a window opens where you can configure the SDK and create virtual devices. I had to force the manager to use http: rather that https: by selecting "Force..." under Settings, to be able to download the SDK components.
6) Select and install SDK packages under Available Packages. I installed:
- SDK Platform Android 2.0, API 5, revision 1
- Google APIs by Google Inc., Android 2.0, API 5, revision 1
Now we need to create an AVD (AVD = Android Virtual Device):
7) I find this to be most convenient to do using the command line, rather than the Manager. This creates a virtual device called myavd:
android create avd -t 2 -n myavd
8) Start the device on the emulator with this command:
emulator -avd myavd &
Note that it takes a while for the device to boot (one minute or so). If successful you are presented with the Android desktop (or is it called phonetop? ;-).
Finally, create the Hello World application:
9) Create a template project with this command:
android create project \
--target 1 \
--name HelloWord \
--path /home/miki/android/projects/HelloWorld \
--activity HelloWorld \
--package miki.hello
The --target switch specifies the id of the target platform. This command lists available targets:
android list targets
The reason we specify target 2 for the virtual device and target 1 for the project is that we want to emulate the most advanced device, but we want the project to run on all devices (this is, at least, how I understand it).
10) The template project created actually is a compilable and runnable application.
Go to the project folder, in my case:
cd /home/miki/android/projects/HelloWorld
Then compile and install the application on the emulator with the command:
ant install
Switch to the emulator window, click the tab at the bottom of the screen, and then click on your application, called HelloWorld.
When you have recovered from the avesome experience of running your app, lets change the text it displays to something more appropriate.
Go back to your project, open the file res/layout/main.xml in a text editor, and change the content of the android:text attribute (this is the text shown in the window of the application), to something you feel you want to tell the world, for example:
android:text="Oh I wish I could program this is Scheme!"
That is it! Now you are ready to explore the world of Android development! Google's site http://developer.android.com has lots of useful information on the Java API, and there are already a number of other sites on the web devoted to Android development.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-11-01
2009-10-31
Magnus K Karlsson
Effective Unit Testing EJB 3.0 with OpenEJB
In my latest project we used EJB 3.0 and Maven2. And as any good programmer I wanted to have good code quality, which means good unit test test coverage, but my expectation on how to achieve this in an efficient manner was quite low, since mine previous experience with EJB 2.1 did not include any good testing experience. Even if coding EJB 3.0 has been greatly simplified, the fact still remains that the enterprise bean has still to be deployed before it can be tested. Of course can one program such that the logic is in a POJO rather directly in the bean itself, but to really be sure it is working the enterprise bean has to be deployed in a container, to be testable. So I started looking at different Maven plugin such as, jboss-maven-plugin and cargo-maven2-plugin, but then came across OpenEJB, which is really the salvation if you are developing EJB 3.0 and want good testing possibility. OpenEJB enable unit testing of enterprise beans as any POJO class! Lets look at some examples.
public class UserServiceSLSBTest {
private static final String EXPECTED_USERNAME_1 = "fornamn.1.efternamn@domain.com";
private static final String EXPECTED_USERNAME_2 = "fornamn.2.efternamn@domain.com";
private static final String EXPECTED_USERNAME_3 = "fornamn.3.efternamn@domain.com";
private Context ctx;
@BeforeClass
public static void oneTimeSetUp() {
}
@AfterClass
public static void oneTimeTearDown() {
}
@Before
public void setUp() throws Exception {
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.LocalInitialContextFactory");
props.put("blogUnmanaged", "new://Resource?type=DataSource");
props.put("blogUnmanaged.JtaManaged", "false");
props.put("blogUnmanaged.JdbcDriver", "com.mysql.jdbc.Driver");
props.put("blogUnmanaged.JdbcUrl", "jdbc:mysql://localhost:3306/blog");
props.put("blogUnmanaged.username", "root");
props.put("blogUnmanaged.password", "");
// TODO fix properties hibernate.hbm2ddl.auto=create-drop
ctx = new InitialContext(props);
}
@After
public void tearDown() {
}
private UserServiceLocal createUserService() throws Exception {
Object obj = ctx.lookup(UserServiceSLSB.class.getSimpleName() + "Local");
assertNotNull(obj);
assertTrue(obj instanceof UserServiceLocal);
return (UserServiceLocal) obj;
}
@Test
public void testCreateUser() throws Exception {
UserServiceLocal userService = createUserService();
User user = new User();
user.setUsername(EXPECTED_USERNAME_1);
user.setPassword(EXPECTED_USERNAME_1);
user.setRoles(Roles.ADMIN);
userService.storeUser(user);
}
}
And the Stateless Session Bean
@Stateless
public class UserServiceSLSB implements UserServiceLocal {
private static final Logger log = LoggerFactory.getLogger(UserServiceSLSB.class);
@PersistenceContext(name = "blog-ejb", unitName = "blog-ejb")
protected EntityManager em;
@Resource
private SessionContext context;
@Override
public User findUserByUsername(String username) {
log.info("findUserByUsername username='" + username + "'...");
Query q = em.createQuery("SELECT u from User as u where u.username=:username");
q.setParameter("username", username);
List list = q.getResultList();
return (list.size() > 0) ? (User) list.get(0) : null;
}
private void checkExistingUser(User user) throws DuplicateException {
User existingUser = findUserByUsername(user.getUsername());
if (existingUser != null)
throw new DuplicateException("Duplicate " + user);
}
@Override
public void storeUser(User user) throws CredentialException, DuplicateException {
log.info("storeUser " + user + "...");
checkExistingUser(user);
if (user.getUserId() == null)
em.persist(user);
else
em.merge(user);
}
}
And the SLSB local interface.
@Local
public interface UserServiceLocal {
public User findUserByUsername(String username);
public void storeUser(User user) throws CredentialException, DuplicateException;
}
And in the pom.xml simply add the dependency to OpenEJB and you are ready to go.
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>3.1.1</version>
<scope>test</scope>
</dependency>
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Installing Firefox 3.5 on Ubunut 9.04 – the Jaunty Jackalope
After several crashes with Firefox 3.0x I decided to install the new Firefox 3.5, since the new version is managed with Synaptic Package Manager everything went smoothly, but with one gotcha. Do not remove the old Firefox, otherwise will panel shortcut and menu item be removed and when clicking on html files will nothing happens. Instead do the following:
sudo apt-get install firefox-3.5 firefox-3.5-gnome-support
Redirect the firefox link to the new version:
sudo rm /usr/bin/firefox
sudo ln -s /usr/bin/firefox-3.5 /usr/bin/firefox
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Bundle a Common Jar Into EJB Jar with Maven Plugin maven-ejb-plugin
Yesterday I had some problem with packing an EJB3 jar with Maven plugin maven-ejb-plugin. The problem seemed quite common. To bundle a common jar dependency into an EJB jar, but after reading the documentation for the maven-ejb-plugin at http://maven.apache.org/plugins/maven-ejb-plugin/, it seemed clear that the plugin lacked this capability. After several hour of failure I ran into a workaround . Instead of configure the maven-ejb-plugin I used the maven-dependency-plugin to copy the desired dependency jar into the target/classes directory and then configure maven-dependency-plugin to run before the package phase.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<generateClient>false</generateClient>
<ejbVersion>3.0</ejbVersion>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>process-classes</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>se.msc.development</includeGroupIds>
<includeArtifactIds>common</includeArtifactIds>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
And if you need to add the common.jar to the classpath in the MANIFEST file add the following configuration to maven-ejb-plugin.
<archive>
<manifest>
<addclasspath>true</addclasspath>
</manifest>
<manifestfile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestfile>
</archive>
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Configure Log4J DailyRollingFileAppender with custom PatternLayout
For some time I haven been planning to learn the mystic configuration of the org.apache.log4j.PatternLayout for Log4j and finally I have taken the time to do so.
- c - The calling class name, if giving without precision is the fully qualified name returned.
- C - The fully qualified class name.
- d - The date of the logging request, can be formatted with java.text.SimpleDateFormat, i.e. %d{yyyy-MM-dd}
- F - The name of the calling File.
- l - The location information, same as %C%M(%F:%L). This can be slow.
- L - The calling class line number
- m - The logging message.
- M - The calling class method.
- n - The platform dependent line separator.
- p - The logging Level.
- r - The relative date in millisecond since application start.
- t - The invoking thread.
- [x|X] - the Message Diagnostic (MDC) information.
Now for some example. To be compliant with large open-source project such as Hibernate Annotation we use SLF4J as Logger interface. To use SLF4J, simply add the following to your Maven pom.xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.4.2</version>
</dependency>
And if we run 'mvn dependency:tree', we see that the artifact also contains the log4j.jar implementation.
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'dependency'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Log4J Test
[INFO] task-segment: [dependency:tree]
[INFO] ------------------------------------------------------------------------
[INFO] [dependency:tree]
[INFO] se.msc.development:log4j-test:jar:1.0-SNAPSHOT
[INFO] +- org.slf4j:slf4j-log4j12:jar:1.4.2:compile
[INFO] | +- org.slf4j:slf4j-api:jar:1.4.2:compile
[INFO] | \- log4j:log4j:jar:1.2.13:compile
[INFO] +- javax.mail:mail:jar:1.4.1:compile
[INFO] | \- javax.activation:activation:jar:1.1.1:compile
[INFO] \- junit:junit:jar:4.5:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Mon Aug 24 03:05:27 CEST 2009
[INFO] Final Memory: 12M/144M
[INFO] ------------------------------------------------------------------------
And here follows an example of how to use SLF4J in your code.
package se.msc.log4j;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Log4JTest {
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
private static final Logger log = LoggerFactory.getLogger(Log4JTest.class);
//import org.apache.log4j.Logger;
//private static final Logger log = Logger.getLogger(Log4JTest.class);
@Test
public void testFoo() throws Exception {
log.info("Info log message.");
log.error("Fatal log message.", new NullPointerException("Null pointer exceptopn."));
}
}
An the log4j configuration file log4j.properties
# configure the root logger
log4j.rootLogger=INFO, STDOUT, DAILY
# configure the console appender
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.Target=System.out
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%p] %c:%L - %m%n
# configure the daily rolling file appender
log4j.appender.DAILY=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DAILY.File=/tmp/log4j/log4jtest.log
log4j.appender.DAILY.DatePattern='.'yyyy-MM-dd
log4j.appender.DAILY.layout=org.apache.log4j.PatternLayout
log4j.appender.DAILY.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%p] %c:%L - %m%n
and when running the JUnit test:
2009-08-24 03:00:47.775 [INFO] se.msc.log4j.Log4JTest:18 - Info log message.
2009-08-24 03:00:47.783 [ERROR] se.msc.log4j.Log4JTest:19 - Fatal log message.
java.lang.NullPointerException: Null pointer exceptopn.
at se.msc.log4j.Log4JTest.testFoo(Log4JTest.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
And now I final word about the DatePattern for the org.apache.log4j.DailyRollingFileAppender:
log4j.appender.DAILY.DatePattern='.'yyyy-MM-dd-a
Rolls over at midnight each day, as is the expected behaviour of a rolling log.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Firefox 3.5 brakes Eclipse 3.4
In mine previous blog I was writing about how to install Firefox 3.5 on Ubuntu 9.04, but that also had some unwanted side effect - it broke the Eclipse 3.4 installation!! Read more about http://hello-world-2-0.blogspot.com/2009/08/firefox-upgrade-broke-eclipse.html.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Getting rid of notification “Network service discovery disabled” in Ubunut 9.04
After installing the latest Ubuntu I have haunted with the annoying notification “Network service discovery disabled. You current network has a .local domain, which is not recommended and incompatible with the Avahi network service discovery. The service has been disabled.”
First of all I have to google what Avahi is and found the following short summary here: https://help.ubuntu.com/community/HowToZeroconf
After that, I got rid of the notification message, by removing the below file and then starting the Avahi service, since some files where not properly auto-created during installation.
sudo rm /var/run/avahi-daemon/disabled-for-unicast-local
sudo /etc/ini.d/avahi-daemon start
After that I disabled the Avahi service, because I could not see any reason to autostart it when Ubuntu booted. You can disabled auto-services from System->Administration->Services. The last thing I did was to reboot and the problem was gone.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Presentation for "Integration solutions with agile framework and Enterprise Service Bus, ESB"
Here comes the presentation for the "Integration solutions with agile framework and Enterprise Service Bus, ESB" seminar I held for some time ago.
http://docs.google.com/fileview?id=0BxdWn5V3EudmY2U3MGYxNGMtMGE0NS00NzhiLTk2Y2QtMDI4OWI5YTA4YTlk&hl=en
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Presentation for "Efficient J2EE Development with JPA, EJB3, Wicket, Maven2 and JBoss 5"
For some ago I held a presentation for "Efficient J2EE Development with JPA, EJB3, Wicket, Maven2 and JBoss 5" and here comes the material:
http://docs.google.com/fileview?id=0BxdWn5V3EudmNmRiNGEyZGMtMDFjZC00Zjg4LWJiYWEtODJmNDE1MGI5OTM5&hl=en
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
How to Enable Code Completion and Syntax Control Against XML Schema with Eclipse
When I was writing Apache Camel configuration XML files, I was frustrated over that I had no code completion or XML syntax check against Apache Camel Schema, but of source is that doable in Eclipse. Simple download the Schema to your computer and then open Eclipe:
Window->Preferences->XML->XML CatalogClick on Add and File System and select the downloaded Schema.
Now you can right-click in your XML file and select Validate.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Clearlook Theme for Ubuntu – Clearlooks OSX
In the beginning I found it quite hard to find new themes, that was compatible with the standard Ubuntu way to install theme, i.e. from System->Preferences->Appearance.
But yesterday I found a nice OSX look that is not so grey as Mac OSX, it is also packaged in the standard Ubuntu installation way.
http://www.gnome-look.org/content/show.php/ClearlooksOSX?content=69487
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
How to Install Swedish Dictionary and Thesaurus for Open Office Writer
If you have installed a English distribution of Ubuntu you have already Open Office installed, but with no Swedish dictionary or Thesaurus. Do this to install:
- Open Office Writer.
- Select Tools->Language->More Dictionaries Online...
- Download the two wanted files Dictionary and Thesaurus. Now you have to oxt-files on your computer.
- Select Tools->Extension Manager and click Add then select oxt-file.
- Restart Open Office and from Tools->Language->For All Text->More. In the window select installed language for selected document.
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Writing to Syslog with Log4J and Testing It on Ubuntu 9.04 Jaunty
The preferred way to log in Linux is to write to the Syslog. For you that comes from the Windows world, Syslog is the equivalent for the Windows NT Event Log. Before you can ran the example below you need to enable Syslog Facility LOCAL1 on Ubuntu. The Facility can be looked as a filter and if you are running multiple programs on the same server, you might want to consider to let each program write to different Facility LOCAL[0-7].
To enable Facility LOCAL1 on Ubuntu 9.04 you first need to edit /etc/syslog.conf
>sudo gedit /etc/syslog.conf &
and add the following line
local1.* /var/log/local1.log
But we are not done yet, since Log4J org.apache.log4j.net.SyslogAppender is using the underlying writer class org.apache.log4j.helpers.SyslogWriter that is using the java.net.DatagramPacket which is writing to the syslog remotely, we need to enable remote access to Syslog. We do that by changing:
>sudo gedit /etc/default/syslogd &
And changing the following:
SYSLOGD="-r"
Now we are done and we need to restarts the system log daemon, to make our changes take affect:
>sudo /etc/init.d/sysklogd restart
Finally we add the following configuration to our log4j.properties.
# configure the root logger
log4j.rootLogger=INFO, STDOUT, DAILY, SYSLOG_LOCAL1
# configure Syslog facility LOCAL1 appender
log4j.appender.SYSLOG_LOCAL1=org.apache.log4j.net.SyslogAppender
log4j.appender.SYSLOG_LOCAL1.threshold=WARN
log4j.appender.SYSLOG_LOCAL1.syslogHost=localhost
log4j.appender.SYSLOG_LOCAL1.facility=LOCAL1
log4j.appender.SYSLOG_LOCAL1.facilityPrinting=false
log4j.appender.SYSLOG_LOCAL1.layout=org.apache.log4j.PatternLayout
log4j.appender.SYSLOG_LOCAL1.layout.conversionPattern=[%p] %c:%L - %m%n
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Maven2 Reference Literature
For some time the best book on Maven2 was “Better Builds with Maven” which can be downloaded from http://www.maestrodev.com/better-build-maven, but now there is finally a more updated book, “Maven: The Definitive Guide“. Which is available from
http://www.sonatype.com/books/maven-book/reference/public-book.html
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
The Promising Standardized JSR 303 Bean Validation and Example of Usage
For too long have the Java world lived without a standardized bean validation specification and soon will the final approval hopefully be approved (2 Nov 2009). What does this imply?
- Better Domain Driven Design, by putting the shallow domain validation in the POJO where it belongs.
- Hopefully we can finally get rid of Value Objects Pattern which is a dark heritage from the EJB 2.1 age and instead use domain POJO beans through out our architecture. There is of course exception to this rule, e.g. in service layer where the exposed model is totally different than the domain model or in a UI layer with heavy usage of line charts, there an OO model does not fit into a point orientation representation.
Here follows a simple example of the usage of Bean Validation.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>se.msc.examples</groupId>
<artifactId>validation-domain</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Validation :: Domain</name>
<url>http://www.msc.se/examples/validation</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>repository.jboss.org</id>
<url>http://repository.jboss.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<!-- common logging library -->
<!-- version is depended on hibernate-annotations v3.4.0.GA -->
<!--
http://repo1.maven.org/maven2/org/hibernate/hibernate-annotations/3.4.0.GA/hibernate-annotations-3.4.0.GA.pom
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.4.2</version>
</dependency>
<!-- sun bean validation api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<!-- hibernate bean validation impl -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.0.0.GA</version>
</dependency>
<!-- test support -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
package se.msc.examples.validation.domain;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private Long personId;
private String firstName;
@NotNull
@Size(min=1)
private String surname;
@NotNull
@Pattern(regexp=".+@.+\\.[a-z]+")
private String mail;
public Long getPersonId() {
return personId;
}
protected void setPersonId(Long personId) {
this.personId = personId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
}
package se.msc.examples.validation.domain;
import static org.junit.Assert.*;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class PersonTest {
private Validator validator;
private Person person;
@BeforeClass
public static void oneTimeSetUp() throws Exception {
}
@AfterClass
public static void oneTimeTearDown() throws Exception {
}
@Before
public void setUp() throws Exception {
validator = Validation.buildDefaultValidatorFactory().getValidator();
person = new Person();
person.setFirstName("Magnus K");
person.setSurname("Karlsson");
person.setMail("magnus.k.karlsson@domain.se");
}
@After
public void tearDown() throws Exception {
}
private void debugPrint(Set> violations) {
for (ConstraintViolation violation : violations) {
String propertyPath = violation.getPropertyPath().toString();
String message = violation.getMessage();
System.out.println("invalid value for: '" + propertyPath + "': " + message);
}
}
@Test
public void testValidate_OK() throws Exception {
Set> violations = validator.validate(person);
assertTrue(violations.size() == 0);
debugPrint(violations);
}
@Test
public void testValidate_FAIL_MAIL() throws Exception {
person.setMail("magnus.k.karlsson@domain");
Set> violations = validator.validate(person);
assertTrue(violations.size() == 1);
debugPrint(violations);
}
@Test
public void testValidate_FAIL_SURNAME() throws Exception {
person.setSurname(null);
Set> violations1 = validator.validate(person);
assertTrue(violations1.size() == 1);
debugPrint(violations1);
person.setSurname("");
Set> violations2 = validator.validate(person);
assertTrue(violations2.size() == 1);
debugPrint(violations2);
}
}
The resource bundle message ValidationMessages.properties
javax.validation.constraints.Null.message=must be null
javax.validation.constraints.NotNull.message=must not be null
javax.validation.constraints.AssertTrue.message=must be true
javax.validation.constraints.AssertFalse.message=must be false
javax.validation.constraints.Min.message=must be greater than or equal to {value}
javax.validation.constraints.Max.message=must be less than or equal to {value}
javax.validation.constraints.Size.message=size must be between {min} and {max}
javax.validation.constraints.Digits.message=numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected)
javax.validation.constraints.Past.message=must be a past date
javax.validation.constraints.Future.message=must be a future date
javax.validation.constraints.Pattern.message=must match the following regular expression: {regexp}
References:
JSR 303: Bean Validation
http://jcp.org/en/jsr/detail?id=303
Article comparing JSR 303 Reference Implementation And Spring 2.5 Validation
http://blog.jteam.nl/2009/08/04/bean-validation-integrating-jsr-303-with-spring/
JSR 303 Reference Material
http://people.redhat.com/~ebernard/validation/
JSR 303 Specification Leads Emmanuel Bernard Blog
http://in.relation.to/Bloggers/Emmanuel
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-31
Integrate JSR 303 Bean Validation And ApacheWicket
In my previous blog I was writing about the new promising standard JSR 303 Bean Validation. In this article I will write about JSR 303 Bean Validation and Apache Wicket. Let start with recapitulate the domain object Person and see how we used the Bean Validation annotation to annotate our property constraints.
package se.msc.examples.validation.domain;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
@Entity
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long personId;
@NotNull
@Size(min = 1, max = 250)
@Column(length = 250)
private String givenName;
@NotNull
@Size(min = 1)
@Column(length = 250)
private String surname;
@NotNull
@Pattern(regexp = ".+@.+\\.[a-z]+")
@Column(length = 250)
private String mail;
public Long getPersonId() {
return personId;
}
protected void setPersonId(Long personId) {
this.personId = personId;
}
public String getGivenName() {
return givenName;
}
public void setGivenName(String givenName) {
this.givenName = givenName;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
}
This time I also have added sun's JPA annotation, because this is a domain object and sooner we want the domain objects to be persisted. We also the see that there is an overlap between the Bean Validation annotation and the JPA annotation. My approach to these is to use an open constraint approach for persistence and a narrowing/stricter definition with the Bean Validation for the domain layer. This way enables us to have a more flexible database, DBA would probably argue that this leads to bad data quality, but since we are building in validation directly in our domain object and writing small and easy to run unit test, to test these validation, there are no risk against bad data quality slipping through to the persistence layer. Actually we are protecting bad data to even reach the persistence layer long before, first in the presentation layer, but also we will use the same Bean Validation in the service layer. And all validation using the same code, the Bean Validation annotation, no more inventing the wheel over and over again in the different layers.
So how do we use the Bean Validation with the Apache Wicket? Well, there is no out-of-box integration, so I have written a few helper classes that will do that for us. These helper classes are actually worth using already how ever you will be using Bean Validation or not in your next project, because Apache Wicket is really to low-tech, like Swing, and when writing Apache Wicket classes from ground up requires you to write quite lengthy masses of code, this is not good. So lets start with our helper classes for writing org.apache.wicket.markup.html.form.Form.
package se.msc.examples;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.LoadableDetachableModel;
public class FormBuilder<T> extends Form<T> {
private static final long serialVersionUID = 1L;
public static final String SUBMIT = "submit";
public FormBuilder(final String id, final T modelObject) {
super(id, new CompoundPropertyModel<T>(new LoadableDetachableModel<T>(
modelObject) {
private static final long serialVersionUID = 1L;
protected T load() {
return modelObject;
}
}));
}
public void addTextField(final String propertyName) {
TextField<T> textField = new TextField<T>(propertyName);
textField.add(new BeanValidator<T>(getModelObject(), propertyName));
add(textField);
}
public void addSubmitButton(final FormButtonListener<T> listener) {
final FormBuilder<T> parent = this;
add(new Button(SUBMIT) {
private static final long serialVersionUID = 1L;
public void onSubmit() {
parent.execSubmit(listener);
}
});
}
public Form<T> create() {
return this;
}
public void execSubmit(final FormButtonListener<T> listener) {
listener.onSubmit(getModelObject());
}
}
package se.msc.examples;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import org.apache.log4j.Logger;
import org.apache.wicket.validation.INullAcceptingValidator;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.ValidationError;
public class BeanValidator<T> implements INullAcceptingValidator<T> {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(BeanValidator.class);
private final Class<T> beanClass;
private final String propertyName;
@SuppressWarnings("unchecked")
public BeanValidator(final T beanObject, final String propertyName) {
this.beanClass = (Class<T>) beanObject.getClass();
this.propertyName = propertyName;
}
@Override
public void validate(IValidatable<T> validatable) {
log.info("validate... " + validatable.getValue());
ReflectionUtil<T> util = new ReflectionUtil<T>();
T beanObject = util.createInstance(beanClass);
util.setPropertyValue(beanObject, propertyName, validatable.getValue());
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<T>> violations = validator.validateProperty(beanObject, propertyName);
for (ConstraintViolation<T> violation : violations) {
String propertyPath = violation.getPropertyPath().toString();
String message = violation.getMessage();
log.error("invalid value for: '" + propertyPath + "': " + message);
ValidationError validationError = new ValidationError();
validationError.setMessage(message);
validatable.error(validationError);
}
}
@Override
public String toString() {
return "[BeanValidator beanObject='" + beanClass + "']";
}
}
Lets now see how we use it in our Apache Wicket controller class.
package se.msc.examples;
import org.apache.log4j.Logger;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import se.msc.examples.validation.domain.Person;
public class PersonEditPage extends WebPage implements FormButtonListener<Person> {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(PersonEditPage.class);
protected static final String FEEDBACK_PANEL = "feedbackPanel";
protected static final String PERSON_FORM = "personForm";
protected static final String GIVEN_NAME = "givenName";
public PersonEditPage(final PageParameters parameters) {
log.info("PersonPage...");
add(new FeedbackPanel(FEEDBACK_PANEL));
add(createForm(new Person()));
}
private Form<Person> createForm(Person person) {
FormBuilder<Person> builder = new FormBuilder<Person>(PERSON_FORM, person);
builder.addTextField(GIVEN_NAME);
builder.addSubmitButton(this);
return builder.create();
}
@Override
public void onSubmit(Person modelObject) {
log.info("onSubmit " + modelObject);
info("Successfully created '" + modelObject.getGivenName() + "'.");
}
}
And the accompanying html file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"
xml:lang="en" lang="en">
<head>
<title>Person Edit Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div id="feedbackPanel" wicket:id="feedbackPanel">Feedback Panel</div>
<form id="personForm" wicket:id="personForm">
<fieldset style="width: 30em">
<legend>Person Edit</legend>
<table border="1" style="width: 100%">
<tr>
<td align="right">Given Name:</td>
<td><input id="givenName" wicket:id="givenName" type="text" style="width: 98%" /></td>
</tr>
<tr>
<td colspan="2" align="right">
<button id="submit" wicket:id="submit" type="submit">Submit</button>
</td>
</tr>
</table>
</fieldset>
</form>
</body>
</html>
Now lets write a simple test case to test our Apache Wicket validation.
package se.msc.examples;
import junit.framework.TestCase;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.util.tester.FormTester;
import org.apache.wicket.util.tester.WicketTester;
public class PersonEditPageTest extends TestCase {
private WicketTester tester;
@Override
public void setUp() throws Exception {
tester = new WicketTester(new WicketApplication());
tester.startPage(PersonEditPage.class);
tester.assertRenderedPage(PersonEditPage.class);
}
public void testLayout() throws Exception {
tester.assertComponent(PersonEditPage.FEEDBACK_PANEL,
FeedbackPanel.class);
tester.assertComponent(PersonEditPage.PERSON_FORM, Form.class);
}
public void testCreate_OK() throws Exception {
FormTester form = tester.newFormTester(PersonEditPage.PERSON_FORM);
form.setValue(PersonEditPage.GIVEN_NAME, "Magnus");
form.submit(FormBuilder.SUBMIT);
tester.assertRenderedPage(PersonEditPage.class);
tester.assertNoErrorMessage();
}
public void testCreate_GIVENNAME_FAIL() throws Exception {
FormTester form = tester.newFormTester(PersonEditPage.PERSON_FORM);
form.setValue(PersonEditPage.GIVEN_NAME, "");
form.submit(FormBuilder.SUBMIT);
tester.assertRenderedPage(PersonEditPage.class);
tester.assertErrorMessages(new String[] { "Field givenName is required." });
form = tester.newFormTester(PersonEditPage.PERSON_FORM);
form.setValue(PersonEditPage.GIVEN_NAME, " ");
form.submit(FormBuilder.SUBMIT);
tester.assertRenderedPage(PersonEditPage.class);
tester.assertErrorMessages(new String[] { "Field givenName is required." });
}
}
by Magnus K Karlsson (magnus.r.karlsson@gmail.com) at 2009-10-31
2009-10-30
Divine Programmer
Why Android will be a big hit
The more I research the Android market and look into Android technologies, the more convinced I am that Android will be the next major computing platform. I view the situation as somewhat similar to 1984, when we had Mac and PC. Mac was a work of art, but a bit closed, and PC was open but rough, and MS-DOS and Windows 1.0 were primitive.
Today we have iPhone, exclusive and masterfully designed, but closed in several ways (much more closed than the Mac ever was). And we have Android, open and available for everyone, with lots of new devices on the way, in different formats and price categories. The big difference compared to 1984 is that Android is not MS-DOS. It is the complete opposite; carefully designed, fun, and open source. People who speculate when Linux will take over the desktop may now have the answer - Android Linux will take over the mobile device market.
Android will be the platform of choice, because it is open for developers. The SDK is free, and serveral new languages and tools are on their way. Simple is a Basic for the Android, developed by Google. The languge seems similar to Visual Basic, and this of course sucks, but I can see the logic here. There are many many Visual Basic programmers, and attracting them to Android is a smart move. There will likely be lots of apps developed, both in-house development at companies and hobby projects. To hobbyists, publising an application on Android Market, might be less of a hazzle compared to hosting and providing support for a web app. Plus, some apps and games a better implemeted as native programs.
Languages like Python, Lua and Perl are running on the Android Scripting Environment. This is a very promising and exiting opportunity for developing mini-applications using small script hacks. There are lots of other efforts going on to port popular languages to Android. Kawa Scheme seems to be a nice choise if you (like me) are fond of the Lisp-family of languages. Scala is also available on Android (some people say Scala is the next big language on the Java platform). Here is a tutorial. Another interesting initiative is App Inventor, a visual programming language for Android developed in Kawa Scheme.
Best of all, my collegue Göran Krampe is looking into porting the Smalltalk dialect Squeak to Android ;-)
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-10-30
2009-10-21
Divine Programmer
My first Android project
I have stared to develop on the Android and my the first project is now on GitHub:
http://github.com/mikaelkindborg/ComiCard
This is the starting point of what might become something similar to HyperCard. It would be really cool to have an easy-to-use autoring tool on Android. I hope Squeak will be ported to Android, then MagicWords would be easy to port.
Meanwhile I experiment with making Java-programming more enjoyable by exploring the design of an internal DSL based on declarative functional Lisp-like style.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-10-21
2009-10-21
PhoneGap
Just found PhoneGap, a JavaScript library for programming Android and iPhone apps in JavaScript. Looks really cool! I'm working on a book about JavaScript game development for children and teenagers (and curious grown-ups!), and PhoneGap could be a good library to use for games on Android and iPhone.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-10-21
2009-10-21
Gwt Smalltalk and Clamato
Gwt Smalltalk runs in the web browser and interacts with the Google Wave protocol. It is a great thing that Smalltalk is avaliable in the browser! Clamato is another Smalltalk that runs in a web browser. And here is an article that discusses languages that compile to JavaScript.
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-10-21
2009-10-21
The Duct Tape Programmer
Just read this article from Joel Spolsky.
Memorable quote:
"Duct tape programmers don’t give a shit what you think about them. They stick to simple basic and easy to use tools and use the extra brainpower that these tools leave them to write more useful features for their customers."
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-10-21
2009-10-21
Scheme on Android
Using Kawa you can author Android apps in Scheme. This looks promising:
(require 'android-defs)I found this example at Per Bothner's blog.
(activity hello
(on-create-view
(let ((view (android.widget.TextView (this))))
(view:setText "Hello World!")
view)))
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-10-21
2009-10-21
Ruby hash map arguments
Ruby is a language with divine qualities, and why the lucky stiff has shown that Ruby programming is a beatiful art.
In Ruby you can pass a hash map to a method using a simplified syntax. The cool GUI-framework Shoes is an example of how this programming technique can be used.
Plain parameter passing
def foo(a, b)Variable number of arguments
puts a, b
end
foo(1, 2)
Here the arguments are passed as an array:
def foo(*args)A mix of the above
puts args[0], args[1]
end
foo(1, 2)
def foo(a, b, *args)Hash map arguments
puts a, b, args[0], args[1]
end
foo(1, 2, 3, 4)
A hash can be passed as parameter (this is somewhat similar to a variable length parameter list, note that the * is not used):
def foo(values)This also works:
puts values[:a], values[:b]
end
foo(:a => 1, :b => 2)
def foo(a, b, values)However, this does NOT work (the hash map parameter must be the last one):
puts a, b, values[:a], values[:b]
end
foo(1, 2, :a => 1, :b => 2)
def foo(values, a, b)But you can always pass the hash map as normal parameter using the proper syntax:
puts a, b, values[:a], values[:b]
end
def foo(values, a, b)Also check out the remarkable book Nobody Knows Shoes by why the lucky stiff.
puts a, b, values[:a], values[:b]
end
foo({:a => 1, :b => 2}, 1, 2)
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-10-21
2009-10-21
Tiny Erlang web server - parallel version
Here is a version of the tiny web server that spawns a new process for each request. This is where Erlang shines. Processes are very lightweight and efficient in Erlang.
% Filename: mserver3.erl
% Tiny webserver that restarts on error.
% Requests are processed in parallel.
% Author: mikael.kindborg@gmail.com
% Date: September 2008
-module(mserver3).
-export([start/0, stop/0, supervisor/0, start_server/0, server/1, process_client_request/2]).
% How to benchmark:
% apache benchmark ab -n 100 -c 10 http://1.1.1.84:4042/hello.html
start() ->
spawn(?MODULE, supervisor, []).
supervisor() ->
io:format("Starting server.~n"),
Pid = spawn(?MODULE, start_server, []),
link(Pid),
process_flag(trap_exit, true),
receive
{'EXIT', Pid, normal} ->
io:format("Server exited normally.~n");
{'EXIT', Pid, stopped} ->
io:format("Server stopped.~n");
{'EXIT', Pid, Reason} ->
io:format("Server exited with code: ~w~n", [Reason]),
timer:sleep(1000),
supervisor();
stop ->
io:format("Stoppning supervisor.~n");
Unknown ->
io:format("Supervisor got an unknown message: ~w~n", [Unknown]),
supervisor()
end.
start_server() ->
{ok, ServerSocket} = gen_tcp:listen(
4042, [binary, {packet, 0}, {active, false}, {reuseaddr, true}]),
on_exit(
self(),
fun (Why) ->
gen_tcp:close(ServerSocket),
io:format("Exiting server, closing ServerSocket, Why = ~w~n", [Why])
end),
server(ServerSocket).
stop() ->
ServerAddress = "localhost",
{ok, Socket} = gen_tcp:connect(ServerAddress, 4042, [binary, {packet, 0}]),
ok = gen_tcp:send(Socket, <<"stop">>),
ok = gen_tcp:close(Socket).
server(ServerSocket) ->
{ok, Socket} = gen_tcp:accept(ServerSocket),
spawn(?MODULE, process_client_request, [Socket, self()]),
server(ServerSocket).
process_client_request(Socket, ServerPid) ->
on_exit(
self(),
fun (Why) ->
gen_tcp:close(Socket)
% io:format("Exiting client request process, closing Socket, Why = ~w~n", [Why])
end),
{ok, BinaryData} = gen_tcp:recv(Socket, 0),
case BinaryData of
<<"stop">> ->
exit(ServerPid, stopped),
io:format("Server stopped~n"),
ok;
<<"GET /stop", _/binary>> ->
ok = gen_tcp:send(Socket, http_reply("Server stopped")),
exit(ServerPid, stopped),
io:format("Server stopped~n"),
ok;
<<"GET /echo", _/binary>> ->
ok = gen_tcp:send(
Socket,
http_reply(binary_to_list(BinaryData)));
<<"GET /", Request/binary>> ->
ok = gen_tcp:send(
Socket,
http_reply(
readfile(
parse_filename(Request))));
_Unknown ->
ok = gen_tcp:send(Socket, http_reply("Unknown request")),
io:format("Unknown request, BinaryData = ~s~n", [BinaryData])
end.
parse_filename(Request) ->
RequestString = binary_to_list(Request),
StopIndex = string:str(RequestString, " HTTP"),
Filename = string:substr(RequestString, 1, StopIndex-1),
Filename.
readfile(Filename) ->
{ok, Binary} = file:read_file(Filename),
binary_to_list(Binary).
http_reply(Data) ->
DataLength = string:len(Data),
list_to_binary(
"HTTP/1.1 200 OK\r\n" ++
"Date: " ++ mdate:date_now_string() ++ "\r\n" ++
"Server: MServer/0.1\r\n" ++
"Last-Modified: " ++ mdate:date_now_string() ++ "\r\n" ++
% Accept-Ranges: bytes
"Content-Length: " ++ integer_to_list(DataLength) ++ "\r\n" ++
"Connection: close\r\n" ++
"Content-Type: text/html; charset=UTF-8\r\n\r\n" ++
Data).
% Create an exit handler, a process that traps exit messages
% from another process. This can be used for a try/catch style
% error handling between processes.
on_exit(Pid, ExitFun) ->
spawn(
fun() ->
process_flag(trap_exit, true),
link(Pid),
receive
{'EXIT', Pid, Why} -> ExitFun(Why)
end
end
).
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-10-21
2009-10-21
Tiny Erlang web server - sequential version
This is a tiny web server written in Erlang. Requests are processed sequentially.
% Filename: mserver2.erl
% Tiny webserver that restarts on error.
% Requests are processed sequentially.
% Author: mikael.kindborg@gmail.com
% Date: September 2008
-module(mserver2).
-export([start/0, stop/0, supervisor/0, start_server/0, server/1]).
% How to benchmark:
% apache benchmark ab -n 100 -c 10 http://1.1.1.84:4042/hello.html
start() ->
spawn(?MODULE, supervisor, []).
supervisor() ->
io:format("Starting server.~n"),
Pid = spawn(?MODULE, start_server, []),
link(Pid),
process_flag(trap_exit, true),
receive
{'EXIT', Pid, normal} ->
io:format("Server exited normally.~n"),
timer:sleep(1000);
{'EXIT', Pid, Reason} ->
io:format("Server exited with code: ~w~n", [Reason]),
timer:sleep(1000),
supervisor();
stop ->
io:format("Stoppning supervisor.~n");
Unknown ->
io:format("Supervisor got an unknown message: ~w~n", [Unknown]),
supervisor()
end.
start_server() ->
{ok, ServerSocket} = gen_tcp:listen(
4042, [binary, {packet, 0}, {active, false}, {reuseaddr, true}]),
on_exit(
self(),
fun (Why) ->
gen_tcp:close(ServerSocket),
io:format("Exiting server, closing ServerSocket, Why = ~w~n", [Why])
end),
server(ServerSocket).
stop() ->
ServerAddress = "localhost",
{ok, Socket} = gen_tcp:connect(ServerAddress, 4042, [binary, {packet, 0}]),
ok = gen_tcp:send(Socket, <<"stop">>),
ok = gen_tcp:close(Socket).
server(ServerSocket) ->
{ok, Socket} = gen_tcp:accept(ServerSocket),
{ok, BinaryData} = gen_tcp:recv(Socket, 0),
case BinaryData of
<<"stop">> ->
ok = gen_tcp:close(Socket),
io:format("Server stopped~n"),
ok;
<<"GET /stop", _/binary>> ->
ok = gen_tcp:send(Socket, http_reply("Server stopped")),
ok = gen_tcp:close(Socket),
io:format("Server stopped~n"),
ok;
<<"GET /echo", _/binary>> ->
ok = gen_tcp:send(
Socket,
http_reply(binary_to_list(BinaryData))),
ok = gen_tcp:close(Socket),
server(ServerSocket);
<<"GET /", Request/binary>> ->
ok = gen_tcp:send(
Socket,
http_reply(
readfile(
parse_filename(Request)))),
ok = gen_tcp:close(Socket),
server(ServerSocket);
_Unknown ->
ok = gen_tcp:send(Socket, http_reply("Unknown request")),
ok = gen_tcp:close(Socket),
io:format("BinaryData = ~s~n", [BinaryData]),
server(ServerSocket)
end.
parse_filename(Request) ->
RequestString = binary_to_list(Request),
StopIndex = string:str(RequestString, " HTTP"),
Filename = string:substr(RequestString, 1, StopIndex-1),
Filename.
readfile(Filename) ->
{ok, Binary} = file:read_file(Filename),
binary_to_list(Binary).
http_reply(Data) ->
DataLength = string:len(Data),
list_to_binary(
"HTTP/1.1 200 OK\r\n" ++
"Date: " ++ mdate:date_now_string() ++ "\r\n" ++
"Server: MServer/0.1\r\n" ++
"Last-Modified: " ++ mdate:date_now_string() ++ "\r\n" ++
% Accept-Ranges: bytes
"Content-Length: " ++ integer_to_list(DataLength) ++ "\r\n" ++
"Connection: close\r\n" ++
"Content-Type: text/html; charset=UTF-8\r\n\r\n" ++
Data).
% Create an exit handler, a process that traps exit messages
% from another process. This can be used for a try/catch style
% error handling between processes.
on_exit(Pid, ExitFun) ->
spawn(
fun() ->
process_flag(trap_exit, true),
link(Pid),
receive
{'EXIT', Pid, Why} -> ExitFun(Why)
end
end
).
by Mikael Kindborg (mikael.kindborg@gmail.com) at 2009-10-21
Last updated: 2010-07-31














