# Enterprise Software Development with Java

## The Java EE 6 Example - Enhance Security with Galleria - Part 5

08:38 Wednesday, March 28, 2012 Posted by
The previous posts (Part1 | Part 2 | Part 3 | Part 4) about the Galleria example guided you through the basics and the initial deployment to both GlassFish and WebLogic. From today on I try to add some enterprise grade features to it as I have seen them requested a lot in my own projects. I know Vineet is also going to add more features over time and I hope this is not going to be too confusing for the readers. But let's see how this works out and which of my features get adopted by Vineet and which not :). Let me know if there is anything special you would like to see added!

Session Fixation
The hottest topic for Enterprise Java applications out there is security. And because it has so many different aspects I decided to start with a very simply but often required feature: Session Fixation prevention. This isn't very Java or JSF specific but a general problem for web based applications.  Session fixation arises when session IDs are easy to discover or guess. The main method of attack is when the session ID is present in the URL or any other part of the response. An attacker could capture a session and then embed the link in their page, tricking a user into visiting it and becoming part of their session. Then when the user authenticates the session is authenticated. Using Cookies only gives a certain security here because the are most often also set via a method which implies confidentiality lose. Most application servers generate a new session ID with the first request. After this is authenticated it is re-used further on. The only way to prevent this is to issue a new, random session after a successful  authentication request.
This is easy to do in general. Go to the galleria-jsf project and find the info.galleria.view.user.Authenticator bean. Add the following lines to the beginning of the authenticate() method:
String result = null;
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();

// Session Fixation Prevention
HttpSession session = (HttpSession) externalContext.getSession(false);

if (logger.isDebugEnabled()) {
logger.debug("Session before authentication request: " + session.getId());
}

session.invalidate();
session = (HttpSession) externalContext.getSession(true);

if (logger.isDebugEnabled()) {
logger.debug("Session after authentication request: " + session.getId());
}

That was it. Very easy change for the first time touching the code-base. Switching to debug level FINE for package info.galleria should reveal the magic in the logfile:
[#|2012-03-27T17:17:25.298+0200|FINE|glassfish3.1.2|info.galleria.view.user.Authenticator|_ThreadID=27;_ThreadName=Thread-4;ClassName=info.galleria.view.user.Authenticator;MethodName=authenticate;|Session before authentication request: 33b1205d7ad740631978ed211bce|#]


As expected we changed the http session during the authentication request. You can also check this with a browser add-on of your choice (in this case "Edit This Cookie"):

And the Galleria application got a bit securer by doing this. If you want to learn more about Session Fixation give the OWASP page a read.

The next requirement is a bit more complex. I have seen this a couple of times and even if it is inconvenient for the user it could be necessary for security reasons. As you might have guessed, there isn't a single switch for that. You have to hold a map of sessions and check if a user is already logged in or not. It should be checked during the login-process and a meaningful error message should be displayed.
There are some tricky parts in that. First one is, that you need a way to store all your user and HttpSession information for the application. And second one is, that you need a someone to look after it. Let's start with the latest.
You are in need of the famous Singleton here. A single place to store the relevant HttpSession information. First thought would be to use the .getExternalContext().getApplicationMap(). This could work. The login restriction we are placing here has some side-effects. Imagine a user loged-in and crashing his/her browser without doing a logout before. He/she would end up with not being able to login again until some cleanup or application restart happens. So it is crucial to also have access to it in a HttpSessionListener. Given the fact, that the JSF ExternalContext is the ServletContext we are safe here.
Before proceeding one more word about clustering. We are going to build a non-clusterable construct here. According to the servlet specification, context attributes are local to the JVM in which they were created. So you will lose protection if you run this in a clustered environment because you can have a session on every single node of the cluster. Making this cluster safe would mean to use either the database, an ejb component or a distributed cache.

Go to info.galleria.view.util and create a new final class with the name SessionConcierge. It needs methods for adding and removing a session. And we obviously need something to handle the application map. Starting with the addSession method which will be called from the info.galleria.view.user.Authenticator managed bean later on:
 public static boolean addSession(HttpSession session) {
String account = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();
String sessionId = session.getId();
if (account != null && !getApplicationMap(session).containsKey(account)) {
getApplicationMap(session).put(account, sessionId);
if (logger.isDebugEnabled()) {
logger.debug("Added Session with ID {} for user {}", sessionId, account);
}
return true;
} else {
logger.error("Cannot add sessionId, because current logged in account is NULL or session already assigned!");
return false;
}
}


This basically checks if we have a loged-in user here and if the user already has a session assigned. If there is a user and he does not have a session in use already we are going to add the current session to the application map under the account as a key. Next a bit remove logic:
 public static void removeSession(HttpSession session) {
String sessionId = session.getId();
String account = getKeyByValue(getApplicationMap(session), sessionId);
if (account != null) {
getApplicationMap(session).remove(account);
if (logger.isDebugEnabled()) {
logger.debug("Removed Session with ID {} for user {}", sessionId, account);
}
}
}

This is a bit more tricky. You noticed, that I use the account as a key for binding the session in the map. So I have to trick around a bit to invert the map and find a key by a value. This little magic happens here:
    private static <T, E> T getKeyByValue(Map<T, E> map, E value) {
for (Entry<T, E> entry : map.entrySet()) {
if (value.equals(entry.getValue())) {
return entry.getKey();
}
}
return null;
}

Done. One thing is missing. The getApplicationMap(HttpSession session) method. This isn't very magic. It simply tries to figure out if we need to get it via the FacesContext or the ServletContext. Look at the SessionConcierge source if you are curious. Final thing to do is to add the SessionConcierge to the Authenticator. Add this code into the try{request.login()} (I added the first two lines for your orientation:
 request.login(userId, new String(password));
result = "/private/HomePage.xhtml?faces-redirect=true";

// save sessionId to disable multiple sessions per user
request.logout();
logger.error("User {} allready logged in with another session", userId);
FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, Messages.getString(
}

If the addition of the HttpSession via the SessionConcierge isn't successful, the user is loged-out immediately and a FacesMessage is added. Remember to add this to the galleria-jsf\src\main\resources\resources messages.properties and it's translations. And don't forget to add the
SessionConcierge.removeSession(session);

to public String logout(). Fine. That's all, isn't it? At least it is working for now. But we still have to address those crashing browser issue. If someone isn't doing a logout via the application, the session times out or the browser crashes you will not be able to login again until the application is restarted. That is weird and unintended. Some mechanism for cleaning up is needed. What about a HttpSessionListener? That sounds great! Add it to info.galleria.listeners and call it SessionExpirationListener.
    @Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();

SessionConcierge.removeSession(session);

if (logger.isDebugEnabled()) {
logger.debug("Session with ID {} destroyed", session.getId());
}
}

Fine. That should be working now. Go ahead and give it a try. Open two different browsers and try to login with both. Only one will let you access the application. The second should respond with the error message you put into the messages.properties. Please note, that this isn't a multiple window prevention. You are still free to open as many windows per HttpSession as you like.
One small addition: If you rely heavily on the HttpSessionListener cleanup you should make sure to have a right lifetime for it. It is configured via the product specific web-app deployment descriptor (e.g. weblogic.xml or glassfish-web.xml). I recommend to set it to a reasonable low value (e.g. 30 minutes or less) to not let the users wait for too long. Here is how this would look like for Glassfish (glassfish-web.xml):

<session-config>
<session-properties>
<property name="timeoutSeconds" value="1800" />
</session-properties>
</session-config>

and for WebLogic (weblogic.xml)
  <session-descriptor>
<timeout-secs>180</timeout-secs>
</session-descriptor>


## The Heroes of Java: Ola Bini

13:14 Monday, March 26, 2012 Posted by
Time to catch up with my "Heroes of Java" interview series. The 14the part is dedicated to Ola Bini. The London JUG connection made this interview possible (Thanks Martijn) because I sadly never met Ola in person until today.

Ola Bini
 (C) ThoughtWorks (Source: flickr.com)
works as a language geek for ThoughtWorks in Chicago. He is one of the JRuby core developers and have been involved in JRuby development since 2006. He has written a book called Practical JRuby on Rails Projects for APress, and coauthered Using JRuby for the Pragmatic Programmers, talked at numerous conferences, and contributed to a large amount of open source projects. He is also a member of the JSR292 Expert Group.

General Part
Who are you?
I'm a Swedish programming language geek living in Chicago!

Well, it says "Computational Meta-linguist" on my business cards. =)

Absolutely. I work as a consultant for ThoughtWorks and there are many really good things about it.

Do you speak foreign languages? Which ones?
Swedish. Although strictly, I guess English is the foreign language for me, since Swedish is my mother tongue.

How long is your daily "bootstrap" process?
Well. 0 or infinity. I do it continuously with other things.

You have a twitter handle? Why?
@olabini why not? =)

Whom are you following in general?
Mostly contacts or interesting people in the computing industry.

Do you have a personal "policy" for twitter?
Not really.

We are encouraged to build our personal brands, and using Twitter is definitely a part of that.

Work
What's your daily development setup? (OS/IDE/VC/other Tools)
Mac OS X, Emacs, Terminal (with ZSh). Everything else is incidental.

Which is the tool providing most productivity to your work?
Emacs, without a doubt.

Your prefered way of interacting with co-workers?
Pair programming.

I use the iOS Reminders app for a lot of things, and I use Emacs
org-mode for most things.

If you could make a wish for a job at your favorite company: What would that be?
I already work for my favorite company!

Java
You're programming in Java. Why?
I'm programming in many languages - I do Java because it's a pragmatic choice in many regards. The power of the JVM is really the reason I use Java.

What's least fun with Java?
How verbose and limited the language is.

If you could change one thing with Java, what would that be?
I would like to stop it from changing completely - I want Oracle to do a non-backwards compatible Java-like language instead.

What's your personal favorite in dynamic languages?
Lisp.

Which programming technique has moved you forwards most and why?
That's really hard to say. I don't actually know.

What was the biggest project you've ever worked on?
In terms of people or lines of code? I worked on a team with about 25
Ruby developers for a while. In terms of largest in LOCs, that varies a
lot from language to language, so it's hard to make comparisons.

Which was the worst programming mistake you did?
There are so many to choose from! Most of my mistakes during my career
has actually been social and political rather than technical.

## I'm speaking at DOAG Development Conference 2012, 14th of June in Bonn, Germany

12:05 Thursday, March 22, 2012 Posted by
For the first time ever, DOAG e.V. is organizing a conference for the exchange of experiences for software developers. On 14 June 2012, the Maritim Hotel Bonn hosts the German Oracle development scene. Be there and dive deep into the software development using tools and technologies from Oracle!

The conference covers the following four tracks: "PL/SQL and Apex", "Java and Open Source", "Forms, Reports, ADF, BI-Publisher", "BPM and Softwarearchitecture".
Find the complete conference program as PDF online.

I am going to give a session in the Java and Open Source track. It will be from 12:00 - 12:45 and covers the latest developments in Java EE 7 and has the title "Entwickeln für die Wolken" (Development for the Clouds).

Find out more about it and register online on the DOAG e.V. website.

UPDATE 10.06.
I will NOT make it! I have trouble with customer appointments and can't join you guys. Sorry for that.

## Jfokus 2012 - Recording of my Talk on Parleys!

09:15 Wednesday, March 21, 2012 Posted by
A short follow up on this year's Jfokus in Stockholm. The first recordings finally went live on Parleys and mine is also contained. So, if you missed this awesome conference you now have a chance to view the recorded sessions from the bigger rooms. Done by @Stephan007 and team! Thanks a lot for the hard work! It turns out to be awesome! Enjoy the sessions!

## Why I think the EC is wrong about JSR 357 and innovation

13:55 Tuesday, March 20, 2012 Posted by
As of yesterday the newly proposed JSR 357 (Social Media API) was declined by the JCP Executive Committee for SE/EE. With eight clear "NO" votes, two abstain, five "YES" and one not voted member this is a clear result.

If you are examining the voting comments, you see two obvious reasons for this to happen. One is the scope of the proposed JSR which "is far too wide" (IBM) and the second is "it's a bit too early to start standardizing on social" (Twitter). While the first has some additional aspects around having to specify relevant domain objects (which is very similar to what the Java Identity API, JSR 351 will have to solve) the second one is surprising.

When should Standardization happen?
Have you ever thought about standardization? When exactly should it happen? And why? First of all you have to look into what standards provide. For a German like me it feels normal to look at what German DIN institute has to say about this:
"Standardization is a strategic instrument for economic success. By becoming involved in standards work, businesses can gain a competitive lead through timely access to information and knowledge. They can use this to their own advantage, reducing the risks and costs involved in R & D as well as greatly reducing transaction costs."
(Source: din.de)
Further on the relation to the field of innovation is expressed as follows:
"Standards serve as a knowledge base and catalyst for innovation. [...] Standards help researchers in various ways: They lay down terminology in new technological areas, set quality and safety norms at an early stage of development, and introduce the necessary standardized, compatible interfaces. [...] Carrying out standardization at an early phase of development helps establish high tech innovations on the market."
(Source: din.de)
This expresses what I have seen in the wild a lot. Take a look at what happened with HTML, WebSockets or NoSQL. Or compare some open source projects. If you start putting a lot effort into something you have a high interest in spreading the word. Even if it only is a small spin off and you don't have too much common sense you start putting your thoughts and code into a sandbox or at least a wiki. To me standardization is the key to innovation because it simply is a short term which means nothing else than "put all players at a table together".

Documenting the status quo?
This is exactly the opposite of what the EC members had to say about the JSR 357. Reading through the lengthy comment section gives you the impression, that there should be standards if some kind of solution is mature enough to be used by a majority already. In other words: We wait for the unofficial reference implementation which drove enough companies into a vendor-lock-in situation (closed- or open-source) and start standardizing afterwards. If you followed the JCP long enough you might have seen this before. Doesn't it sound like Seam 2/Spring for CDI or Guice for JSR 330? I for myself am not sure if this is the right way to go with the JCP in general. If it is common sense to only adopt what is already out there the JCP will fall behind recent developments and trends even faster than it already did in the past. And it always will follow some kind of documenting the status quo approach. Is that, why we need all the "big names" in the JCP? Because having them agreeing to a standards guarantees for their adoption? I don't think it was meant that way.
I would love to call on the EC members to accept their commitment for developing the Java ecosystem and take this more seriously in the future.

Other Aspects
Let's finish this little angry excursion with the still open issues with 357. Yes. It finally is too broadly scoped. The spec leads have accepted this before and addressed it with a direct communication with the EC members.
"... the scope of the JSR primarily is Connecting to Social Media Services and Providers, so similar to the first JSON JSR one could see it as Java Social Media Client API"
(Source: Goldman Sachs & Co voting comments, jcp.org)
This obviously should have been more clear upfront and the spec leads and the designated EG should have taken some action to address those issues earlier.
Further on it might be a bit risky to rely on things that don't exist yet in the standard. Namely REST client API and JSON processing. But this shouldn't have been a major issue and it happened before to other JSRs.

Bottom Line
It was obviously too early for this JSR. At least for the JCP as it is today. And it showed very clearly what it takes to successfully pass a review ballot. You need a hell lot of support among the EC to move stuff forward. As of today the combination of simply technical voting members like the LJC and the political voting members like SAP and IBM leads to a very easy and fast rejection of a JSR. Maybe it would be a good idea to think about different review ballots for technical and business impacts and define different constraints on JSRs if they are rejected by one or the other ballot. A JSR which was rejected by a business ballot could still be formed and have an active EG which could start developing on it's standard. All under the wings of the JCP. This is exactly what it should be to me. A community process. Not a documentation tool.

## The Java EE 6 Example - Testing Galleria - Part 4

10:34 Tuesday, March 20, 2012 Posted by
Time to move on with Vineet's Java EE 6 Galleria Example. After some introduction, a basic getting started guide on GlassFish and the WebLogic 12c deployment it finally is time to dive into testing. I skipped this part in the earlier posts because of two reasons. The first one obviously was that I wanted to write a separate post about it. The second one was that there was work to do to get this up and running on latest GlassFish 3.1.2. Vineet and team did a great job releasing Arquillian GlassFish Remote Container CR3 a few days back which now also covers GlassFish 3.1.2. Time to get you started with testing the Galleria Example.

What you are going to test
The Galleria was build to achieve comprehensive test coverage through the use of both unit and integration tests, written in JUnit 4. The unit and integration tests for EJBs and the domain model rely on the EJB 3.1 container API. The integration tests for the presentation layer relies on the Arquillian project and its Drone extension (for execution of Selenium tests).
Please make sure to update to the latest sources from the Galleria Project because Vineet updated the Arquillian GlassFish container to CR3 and the Selenium stuff to support latest FireFox browser.

Unit-Testing the Domain Layer
The tests for the domain layer fall into five separate categories. The first three (Bean Verification tests, Mutual Registration verification tests, Tests for the Constructor, equals and hashcode methods) cover the basic needs for nearly any JPA based application. If you take a walk down the galleria-ejb\src\test sources you can see them covered in the info.galleria.domain package. Every domain object is covered by a suite class which includes all three kinds of unit tests.
Lets start with looking at the Bean Verification tests. The behavior associated with the getters and setters in the properties of JavaBeans are fairly easy to verify. All one needs to do, is to invoke the setter first, then the getter, and verify whether the instance returned by the getter is equal to the instance passed to the setter. The project uses the BeanVerifier class (under the src/tests/java root of the galleria-ejb module) for this. The AlbumBeanVerifier test simply is a parameterized test which tests every single property. The only exception in this case is the coverPhoto property which has a special behavior beyond the simple JavaBean pattern.
Next on the list are the tests for the constructor, equals and hashcode methods. Constructors for the domain entities are tested by merely creating new instances of the classes, while asserting the validity of the properties that would be set by the constructor. The equals and hashcode methods are verified via the use of the EqualsVerifier class from the EqualsVerifier project.
The last category of the more basic tests are the mutual registration (PDF) verification tests. You simply want to check if modifications to the relationships between the entities, actually result in changes to both the parent and the child properties. See the comprehensive wiki page for more details about the implementation. All these are executed during the unit-testing phase and are covered by **/*Suite.java classes.
In addition to the basic tests you also find one-off tests written for specific cases where the basic test-models are insufficient or unsuitable. In such instances, the one-off tests verify such behavior through hand-written assertions. You find them in **/*Tests.java classes in the same package.
The domain layer tests finish with the JPA repository tests. Each of the *RepositoryTest.java classes test the CRUD behavior of the handled domain objects. The common AbstractRepositoryTest handles the test data and resets the database after every test-run. The database creation itself is handled by the maven-dbdeploy-plugin. Looking at the pom.xml you can see, that it is bound to two Maven lifecycle phases (process-test-resources and pre-integration-test) which makes sure it gets called twice. First time before the unit-tests and second before the integration testing (compare below).
All those unit-tests are executed with surefire. If you issue a mvn test on the galleria-ejb project you can see a total of 138 tests passing. These are the four **/*Suite tests, the four **/*RepositoryTests and two additional tests. If you briefly look at the console output you see, that this is all happening in a Java SE environment. No container tests have been done until now.

Integration Testing the Domain Layer
So this really only covered the basics which everybody should do and probably knows. Doing integration testing is another story. This is done by the **/*IntegrationSuite tests. The name intentionally does not use the default naming conventions in order to prevent them from running during Maven's unit-testing phase. To hook into the integration-test phases of Maven the Galleria example makes use of the Maven Failsafe Plugin.  You can find the integration test Suite in the info.galleria.service.ejb package. The AbstractIntegrationTest takes care about handling the test data (comparable what the AbstractRepositoryTest) did for the unit-tests. The Suite contains a *ServiceIntegrationTest for every domain object. You can walk through the single tests in every *IntegrationTest and get a feeling for what is happening here. The ServicesIntegrationSuite takes care of starting and stopping the EJBContainer by using the AbstractIntegrationTest.startup();. This method is comparably unspectacular and simple:
logger.info("Starting the embedded container.");
Map<String, Object> props = new HashMap<String, Object>();
props.put("org.glassfish.ejb.embedded.glassfish.installation.root",
"./glassfish-integrationtest-install/glassfish");
container = EJBContainer.createEJBContainer(props);
context = container.getContext();

The most important point here is, that the embeddable EJBContainer is configured via an existing GlassFish domain which can be found directly in the galleria-ejb\glassfish-integrationtest-install folder. If you look at the glassfish\domains\domain1\config\domain.xml you can see, that all the configuration is already done for you. But where does the deployment come from? This is easy to answer. By default the  embeddable EJBContainer searches your classpath for ejb-jar jarfiles or folders and deploys them. If you want to see a little bit more verbose output from the EJBContainer you have to provide a customlogging.properties file in src/test/resources and add some simple lines to it:
handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.ConsoleHandler.level=FINEST
#add some more packages if you need them
info.galleria.service.ejb.level=FINE

<systemPropertyVariables>
<java.util.logging.config.file>\${basedir}/src/test/resources/customlogging.properties</java.util.logging.config.file>
</systemPropertyVariables>

The integration tests should finish successfully and maven should print something comparable to the following:
Tests run: 49, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 61.726 sec

Notice, that the integration tests take significantly longer than the normal unit-tests. This is no surprise at all and you should make sure to only execute them when needed so you are not slowed down with your development.

Integration Testing the Presentation Layer
The domain layer is covered with tests. What is missing is the presentation layer. You can find the presentation layer tests in the galleria-jsf project. Start with examining the pom.xml. You find a couple of new dependencies here. Namely Arquillian, Selenium and Drone.

First some configuration again. Scroll down to the profile section you can see a integration-test profile which makes use of the maven-glassfish-plugin and controls a container which is configured with a couple of properties. Add the definition  to the properties section on the top of the pom:
<galleria.glassfish.testDomain.user>admin</galleria.glassfish.testDomain.user>
<galleria.glassfish.testDomain.glassfishDirectory>D:/glassfish-3.1.2-b22/glassfish3/glassfish/</galleria.glassfish.testDomain.glassfishDirectory>
<galleria.glassfish.testDomain.domainName>test-domain</galleria.glassfish.testDomain.domainName>
<galleria.glassfish.testDomain.httpPort>10080</galleria.glassfish.testDomain.httpPort>
<galleria.glassfish.testDomain.httpsPort>10081</galleria.glassfish.testDomain.httpsPort>

You can copy this from the development profile of the galleria-ejb project as described in part 2. You also should already have the domain in place. Next down to the maven-surefire-plugin you can see, that it follows the same conventions that the galleria-ejb project has. But looking at the test-classes you can see, that there isn't a single unit-test here. So you can directly move on to the maven-failsafe-plugin which handles the integration tests. There is one single AllPagesIntegrationTest which covers the complete testing. Let's go there.
It is an Arquillian Testcase which is executed as a client against a remote instance. Beside the definition of the deployment (@Deployment) you also again see a couple of setUp and tearDown methods which do some initialization and destruction. One thing has to be handled separately. You also see a writeCoverageData() method in there which obviously connects to some kind of Socket and reads data from it. This is the JaCoCo (Java Code Coverage Library) hook which can produce a coverage data set of the tests. To make this work you will have to download the package and extract it to a place of you choice. Next go to your GlassFish test-domain\config\domain.xml and open it. Find the server-config - java-config and add the following there:
<jvm-options>-javaagent:D:\path\to\jacoco-0.5.6.201201232323\lib\jacocoagent.jar=output=tcpserver</jvm-options>

This enables the coverage agent for GlassFish. All configuration done now. Back to NetBeans, select the integration-test profile (in NetBeans you can do this by selecting the entry from the dropdown box next the the little hammer in the icon area or by using -Pintegration-test as a maven command line switch. The console output tells you, that the GlassFish domain is started and the info.galleria.view.AllPagesIntegrationTest is running. Be warned, a FireFox instance is popping up during this run and the Arquillian Drone extension is driving your Selenium Tests.
Seeing a browser remote controlled in this way looks and feels weird if you haven't seen this before. If everything works you should now see this in the console output:
Tests run: 30, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 138.014 sec


If you are using another locale than en for your browser you may have completely failed tests. So there is additional need to configure Drone to support it. Drone allows you to specify a Firefox profile via arquillian.xml. You can create a Firefox profile that is configure to send accept-language headers with en/en-US as the value.
To create a new profile, start Firefox Profile manager with the following command (you might need to close all running instances): firefox -profilemanager (on Windows you need to execute the command "d:\complete\path\to\firefox.exe" -profilemanager) in a cmd shell. Remember the location on the disc where this profile is created - you'll need it later. To configure the created profile, in Firefox, go to Options (menu) -> Content (tab) -> Languages (fieldset) -> Choose to add the English language (and move it top, as the preferred one). Now navigate the galleria-jsf\src\test\resources\arquillian.xml, you can then add a property:
<extension qualifier="webdriver">
<property name="implementationClass">org.openqa.selenium.firefox.FirefoxDriver</property>
<property name="firefoxProfile">location of the Firefox profile for English</property>
</extension>

All done now. You should be able to run the complete clean and build process now without any test failing. A big "green bar" :)

## Updated Oracle WebLogic Server 12.1.1.0 distribution

11:22 Monday, March 19, 2012 Posted by
Sources told me that as of Friday last week you have an updated version of WebLogic Server 12c on OTN. This is still at 12.1.1.0 but has been repackaged to include some additional patches and is delivered as a "pre-patched" distribution. For x86 based 64bit systems the Oracle support site lists 19 single patches are available.
Anyway, the preferred approach is to use the updated WebLogic Server 12.1.1 distribution. If you obtain the updated product distribution for WebLogic Server 12.1.1 after March 16, 2012, the patches are included. If you obtained a product distribution for WebLogic Server 12.1.1 prior to March 16, 2012, and you do not wish to re-install with the updated WebLogic Server distribution, you can obtain the patches from My Oracle Support.

Mainly four areas have been corrected with the patches. You now have a bunch of JDK 7 certification patches some Contexts and Dependency Injection patches the Deployment performance optimization patches and last but not least the Developer experience patch which only applies to the developer-only distribution.

The details describing this are provided in updated product documentation, notably:
- What's New documentation
- Updated Release Notes

## The Java EE 6 Example - Running Galleria on WebLogic 12 - Part 3

12:52 Wednesday, March 14, 2012 Posted by
You probably followed me with the last Java EE 6 Galleria example posts. The first one was the basic introduction. The second one was about running it on latest GlassFish. Someone of the RedHat guys mentioned, that we should look into bringing this example off from GlassFish. Great ;) Thanks for the nice idea. That is exactly what we are going to do today. I am going to bring the Galleria example to latest WebLogic 12c.

Preparation
Get yourself in the mood for some configuration. You already have the latest NetBeans 7.1 installed and you are going to download the WebLogic 12c ZIP distribution in a second. After you have downloaded the wls1211_dev.zip put it to a location of choice and unzip it. From now on we are going to call this folder the %MW_HOME% folder. Open a command line and setup %JAVA_HOME%, %JAVA_VENDOR% and %MW_HOME% variables in it:
set JAVA_HOME=D:\jdk1.7.0_04
set MW_HOME=D:\temp\wls12zip
set JAVA_VENDOR=Sun

After you have done this one final step is to run the installation configuration script configure.cmd in the MW_HOME directory. This is a one time thing to do.

Next the most tricky part. We need a JDBC realm like the one we configured for GlassFish. First difference here is, that we don't actually create a new realm but add an authentication mechanism to the available one. There is a nasty limitation with WebLogic. You can configure as many security realms as you like, but only one can be active at a given time. This stopped myself for a while until I got the tip from Michel Schildmeijer (thanks, btw!). Navigate to "Security Realms" and select "myrealm" from the table. Switch to the Providers tab. Select "New" above the table of the Authentication Providers. Enter "GalleriaAuthenticator" as the name and select "SQLAuthenticator" from the dropdow-box as a type. Click ok. Select the GalleriaAuthenticator and set the Control Flag: SUFFICIENT and save. After that switch to the "Provider Specific" tab. Enter the following:
Data Source Name: GalleriaPool
SQL Get Users Password: SELECT PASSWORD FROM USERS WHERE USERID = ?
SQL Set User Password: UPDATE USERS SET PASSWORD = ? WHERE USERID = ?
SQL User Exists: SELECT USERID FROM USERS WHERE USERID = ?
SQL List Users: SELECT USERID FROM USERS WHERE USERID LIKE ?
SQL Create User: INSERT INTO USERS VALUES ( ? , ? )
SQL Remove User: DELETE FROM USERS WHERE USERID = ?
SQL List Groups: SELECT GROUPID FROM GROUPS WHERE GROUPID LIKE ?
SQL Group Exists: SELECT GROUPID  FROM GROUPS WHERE GROUPID  = ?
SQL Create Group: INSERT INTO GROUPS VALUES ( ? )
SQL Remove Group: DELETE FROM GROUPS WHERE GROUPID  = ?
SQL Is Member: SELECT USERID FROM USERS_GROUPS WHERE GROUPID  = ? AND USERID = ?
SQL List Member Groups: SELECT GROUPID  FROM USERS_GROUPS WHERE USERID  = ?
SQL List Group Members: SELECT USERID FROM USERS_GROUPS WHERE GROUPID = ? AND USERID LIKE ?
SQL Remove Group Memberships: DELETE FROM USERS_GROUPS WHERE GROUPID = ? OR GROUPID = ?
SQL Add Member To Group: INSERT INTO USERS_GROUPS VALUES( ?, ?)
SQL Remove Member From Group: DELETE FROM USERS_GROUPS WHERE GROUPID = ? AND USERID = ?
SQL Remove Group Member: DELETE FROM USERS_GROUPS WHERE GROUPID = ?
Descriptions Supported: unchecked

Save your changes. and go back to the "Providers" tab. Click on the "Reorder" button and push the GalleriaAuthenticator to the top of the list. Click "ok", when done and stop your WebLogic instance. You are free to restart it at any time.

Java EE is portable. Right. And you should be able to run the same deployment without any changes on the WebLogic 12c. That is theory. In practice you will have to touch the deployment. Because WebLogic has some issues with Hibernate. And it is a lot more crotchety when it comes to deployments than GlassFish is. First of all you have to create a "galleria-ear\src\main\application\META-INF" folder. Put a blank weblogic-application.xml there and put the following code in it:

<?xml version='1.0' encoding='UTF-8'?>
<weblogic-application xmlns="http://xmlns.oracle.com/weblogic/weblogic-application" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-application http://xmlns.oracle.com/weblogic/weblogic-application/1.4/weblogic-application.xsd">
<prefer-application-packages>
<package-name>antlr.*</package-name>
</prefer-application-packages>
</weblogic-application>


That tells WebLogic to prefer the application packaged libraries over those already present in the server. Let's go ahead. We need to add the Hibernate dependencies to the ear. With GlassFish we skipped that step, because we installed the Hibernate package with the server. Here we go. Open the galleria-ear pom.xml and add the following to the dependencies section:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>

<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.1.0.CR2</version>
</dependency>

You also need to look at the maven-ear-plugin and add the following to the <configuration>:
<defaultLibBundleDir>lib</defaultLibBundleDir>

And if you are there already, remove the commons-codec jarModule. It doesn't hurt, but it get's packaged into the ear/lib folder, so you can skip it.
Next navigate to the galleria-jsf project and open the web.xml. The <login-config> is incomplete and should look like this:
    <login-config>
<auth-method>FORM</auth-method>
</login-config>
<security-role>
<description>All registered Users belong to this Group</description>
<role-name>RegisteredUsers</role-name>
</security-role>


You need to define the possible roles, too otherwise the WebLogic security stuff will start to complain.
Add a blank weblogic.xml to the galleria-jsf\src\main\webapp\WEB-INF folder and add the following lines to it:
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
<security-role-assignment>
<role-name>RegisteredUsers</role-name>
<principal-name>RegisteredUsers</principal-name>
</security-role-assignment>
<session-descriptor>
<timeout-secs>3600</timeout-secs>
<invalidation-interval-secs>60</invalidation-interval-secs>
<url-rewriting-enabled>false</url-rewriting-enabled>
</session-descriptor>
</weblogic-web-app>


We are mapping the web.xml role to a WebLogic role here. You could have skipped this, but I like it this way so you don't get confused. The session-descriptor element is taking care of the JSESSION cookie name. If you wouldn't change it, you would get into trouble with signed in users to the admin console.
Move on the the galleria-ejb project. Create a blank weblogic-ejb-jar.xml in the "galleria-ejb\src\main\resources\META-INF" folder. Put the following code in it:

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-ejb-jar xmlns="http://xmlns.oracle.com/weblogic/weblogic-ejb-jar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-ejb-jar http://xmlns.oracle.com/weblogic/weblogic-ejb-jar/1.0/weblogic-ejb-jar.xsd">
<security-role-assignment>
<role-name>RegisteredUsers</role-name>
<principal-name>RegisteredUsers</principal-name>
</security-role-assignment>
</weblogic-ejb-jar>


Comparable to the web.xml/weblogic.xml this also tells WebLogic how to map the ejb-jar.xml security roles to WebLogic roles. Fine, open the persistence.xml and add the following lines:
 <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform" />

The first one explicitly selects the Derby dialect for Hibernate. The second one tells Hibernate where and how to look for the transactions. All done. Now you should be able to build the project again and deploy it. Use the admin console or NetBeans to deploy it. Thanks for taking the time to follow this lengthy post. I hope it was helpful!

Want to know what it takes to get the unit and integration tests up and running? Read on!

## The Java EE 6 Example - Running Galleria on GlassFish 3.1.2 - Part 2

08:07 Tuesday, March 13, 2012 Posted by
You hopefully have seen my last post about Vineet's DDD Java EE 6 example. If not, take a look. It introduces you to the overall example and might be helpful with this and the following posts. Today we are going to setup the example as it is directly with latest GlassFish 3.1.2, Hibernate and Derby.

Preparation
Get yourself in the mood for some configuration. Grep the latest NetBeans 7.1 (the Java EE edition already includes the needed GlassFish 3.1.2) and install it. I also assume you have a decent Java SDK 7 (6 would do the job, too) in place somewhere. Depending on the development strategy you also need a Mercurial Client and Maven. At least Maven is also included in NetBeans, so ... I mean ... why make your life harder than it already is? ;)

Environments
Some few more words about the environments. This example was setup for supporting different environments. Starting with the plain "development" environment you also need to configure your "test" and last but not least the "production" environment. All of the different environments are handled by maven profiles, so you might have to configure a bit during the following minutes.

Create the Database instances
First thing to do is to decide where to put all your stuff. The examples use derby out of the box and therefore you should either have the Java DB installed (part of the JDK) or use the GlassFish derby instance which is pre-configured with NetBeans. Let's make it harder here and assume we use the Java DB installation that comes with your JDK. Go ahead, open a CMD prompt and navigate to your %JAVA_HOME% folder and further down the db folder/bin. Execute the "startNetWorkServer" script and watch out for the derby instance to start. Now open another CMD prompt also navigate to the db/bin folder and execute the "ij" script. This should come up with a prompt " ij>. Now enter the following connect string:
connect 'jdbc:derby://localhost:1527/GALLERIATEST;create=true';


This command connects you to the derby instance and creates a GALLERIATEST database if it doesn't already exist. The Galleria example uses a handy little tool called dbdeploy as a database change management tool. It let's you do incremental updates to the physical database model which get tracked in a changelog table. (More about this later in the series). You have to create the changelog table:
CREATE TABLE changelog (
change_number DECIMAL(22,0) NOT NULL,
complete_dt TIMESTAMP NOT NULL,
applied_by VARCHAR(100) NOT NULL,
description VARCHAR(500) NOT NULL
);

ALTER TABLE changelog ADD CONSTRAINT Pkchangelog PRIMARY KEY (change_number);

You can redo the steps for any other instance you need (production, etc.) by simply changing the database name in the connect statement. And don't forget to create the changelog table in every instance.
And if you don't like this approach. Fire up NetBeans, switch to the services tab, select "New Connection" and add a new Java DB Network Connection with host:localhost, port:1527 and Database: GALLERIATEST;create=true. Set both user and password to "APP" and click "Test Connection". Select APP as the schema for your new DB. And you are done!

Create the GlassFish domain
We are running this from latest GlassFish. First thing to do now is to create a new domain. navigate to your GlassFish installation directory and goto glassfish3/bin and execute the following:
asadmin create-domain --portbase 10000 --nopassword test-domain

This creates a new test-domain for you. Now navigate to that domain folder ("glassfish3/glassfish/domains/test-domain") and open the config/domain.xml file.
We are now going to add the created derby database as a connection pool to you newly created GlassFish domain. Navigate to the <resources> element and add the following connection pool and jdbc-resource under the last closing  </jdbc-connection-pool> element:

 <jdbc-connection-pool driver-classname="" datasource-classname="org.apache.derby.jdbc.ClientDataSource40" res-type="javax.sql.DataSource" description="" name="GalleriaPool" ping="true">
<property name="User" value="APP"></property>
<property name="DatabaseName" value="GALLERIATEST"></property>
<property name="RetrieveMessageText" value="true"></property>
<property name="ServerName" value="localhost"></property>
<property name="Ssl" value="off"></property>
<property name="SecurityMechanism" value="4"></property>
<property name="TraceFileAppend" value="false"></property>
<property name="TraceLevel" value="-1"></property>
<property name="PortNumber" value="1527"></property>
</jdbc-connection-pool>

Now find the : <config name="server-config"> element and inside it look for the last  <resource-ref entry. Add the following line there:
  <resource-ref ref="jdbc/galleriaDS"></resource-ref>

One last thing to do until we are ready to fire up our instance. We need to add the JDBC Realm for the Galleria example. again, find the <config name="server-config"> and inside it, look for a </auth-realm>. Under this, put the following:
  <auth-realm classname="com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm" name="GalleriaRealm">
<property name="jaas-context" value="jdbcRealm"></property>
<property name="encoding" value="Hex"></property>
<property name="group-table" value="USERS_GROUPS"></property>
<property name="charset" value="UTF-8"></property>
<property name="user-table" value="USERS"></property>
<property name="group-name-column" value="GROUPID"></property>
<property name="digest-algorithm" value="SHA-512"></property>
<property name="user-name-column" value="USERID"></property>
</auth-realm>

Be sure not to put the new realm under the default-config. This will not work. Fine. Let's get the sources :)

Getting the Source and opening it in NetBeans
Vineet is hosting the Galleria example on bitbucket.org. So, you have to go there and visit the java-ee-6-galleria project. There are three ways you can bring the sources to your local HDD. Either via the hg command line:
hg clone https://bitbucket.org/VineetReynolds/java-ee-6-galleria

or via the website download (upper right "get sources") or directly via NetBeans. You need a Mercurial client for your OS for the first and the third option. I am using TortoiseHg for Windows. You should have this installed and configured with NetBeans before doing the following. Lets try the last alternative here. Select "Team > Clone Other". Enter the Repository URL and leave user/password empty. Click "next" two times (we don't need to change default paths ;)) and select a parent directory to put the stuff in. Click "Finish" and let the Mercurial client do the work. You are asked to open the found projects after it finished. This should look similar to the picture on the right. If you run into connection troubles make sure to update your proxy settings accordingly.
If you try to build the project you will run into trouble. It is still missing some configuration which we are going to do next.

Next is to add some stuff to the Maven pom.xml of the galleria-ejb project. Open it and scroll down to the <profiles> section. You find two (sonar and production). We are going to add a development profile by adding the following lines to it (make sure to adjust the GlassFish paths to your environment):
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<galleria.derby.testInstance.jdbcUrl>jdbc:derby://localhost:1527/GALLERIATEST</galleria.derby.testInstance.jdbcUrl>
<galleria.derby.testInstance.user>APP</galleria.derby.testInstance.user>
<galleria.glassfish.testDomain.glassfishDirectory>D:/glassfish-3.1.2-b22/glassfish3/glassfish/</galleria.glassfish.testDomain.glassfishDirectory>
<galleria.glassfish.testDomain.domainName>test-domain</galleria.glassfish.testDomain.domainName>
<galleria.glassfish.testDomain.httpPort>10080</galleria.glassfish.testDomain.httpPort>
<galleria.glassfish.testDomain.httpsPort>10081</galleria.glassfish.testDomain.httpsPort>
</properties>
</profile>

Ok. As you can see a couple of stuff is defined here. And the profile is activated by default. That's it. For now.

Testing the ejb-Galleria Project
Lets try to run the testcases in the ejb-Galleria project.  Right click it and issue a  "clean and build".Follow the console output to see what is actually going on. We are going to investigate this a little bit further with one of the next posts. Today we are only doing this to make sure, you have everything setup the right way. It should finish with:
Tests run: 49, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

That is a "Green-Bar" :-) Congratulations!

Build and Deploy the Project
Now go to NetBeans "Tools > Options > Miscellaneous > Maven" and check the box that says: "Skip Tests for any build executions not directly related to testing". Return to the main window and right click the Galleria project and make a clean and build there.
Reactor Summary:

Galleria ................................. SUCCESS [0.431s]
galleria-ejb ............................. SUCCESS [5.302s]
galleria-jsf ............................. SUCCESS [4.486s]
Galleria EAR ............................. SUCCESS [1.308s]
------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------
Total time: 11.842s


Fine. Now lets fire up the GlassFish domain. Switch to your GlassFish installation and find the glassfish3/bin folder. Open a command line prompt there and run:
asadmin start-domain test-domain

You can see the domain starting up. Now open a browser and navigate to http://localhost:10048/. After a few seconds this is going to show you the admin console of your GlassFish server. Now you need to install Hibernate. Select the "Update Tool" (bottom left) and switch to the "Available Add-Ons" tab. Select "hibernate" and click install (top right). Stop the server after you installed it and restart it with the command above. Open the admin console again and click on "Applications". Click the little "deploy" button on top and browse for the "java-ee-6-galleria/galleria-ear/target/galleria-ear-0.0.1-SNAPSHOT.ear". Click on "OK" (top right). You are done after a few seconds. Now switch to http://localhost:10080/Galleria/ and you will see the welcome screen. Congratulations. You setup the Galleria example on GlassFish! Sign up, Login and play with the application a bit!

The next parts in the series will dive you into the details of the application. I am going to cover the tests and overall concepts. And we are also going to change both JPA provider and database in a future post.

Want to know what it takes to get it up and running on latest WebLogic 12c ? Read on!

## The Java EE 6 Example - Galleria - Part 1

12:33 Monday, March 12, 2012 Posted by
Have you ever been wondering where to find some good end-to-end examples build with Java EE 6? I have. Most of the stuff you find on the net is very basic and doesn't solve the real world problems. This is true for the Java EE 6 tutorial. All the other stuff, like most of what Adam Bien publishes are a very tight scoped examples which also doesn't point you to a more complete solution.
So, I was very pleased to stumble over a more complex example done by Vineet Reynolds. It's called "Java EE 6 Galleria" and you can download the source code from bitbucket. Vineet is a software engineer contributing to the Arquillian project; more specifically, he contributed bugs fixes and worked on a few feature requests for Arquillian Core, and the GlassFish, WebLogic and Tomcat integrations for Arquillian. This is where I first came across his name. And following the Arquillian guys and him a little closer directly send me to this example. A big thanks to Vineet for a helping hand during my first tries to get this up and running. Follow him if you like on twitter @VineetReynolds.
Here is a brief explanation about it's background and this is also kicking of a series about running it in different settings and pointing you to a few more details under the hood. This is the basic introduction.
There is more to discover: Read about running it on GlassFish, running it on WebLogic, testing it, enhanced security and about dealing gracefully with exceptions.

The high level description of the project is the following: The Java EE 6-Galleria is a demo application demonstrating the use of JSF 2.0 and JPA 2.0 in a Java EE project using Domain Driven Design. It was written to serve as a showpiece for domain driven design in Java EE 6. The domain model of the application is not anemic, and is constituted of JPA entities. The entities are then used in session EJBs that act as the application layer. JSF facelets are used in the presentation tier, using Mojarra and PrimeFaces. The project seeks to achieve comprehensive coverage through the use of both unit and integration tests, written in JUnit 4. The unit and integration tests for EJBs and the domain model rely on the EJB 3.1 container API. The integration tests for the presentation layer relies on the Arquillian project and its Drone extension (for execution of Selenium tests).

Domain driven design using Java EE 6
DDD as an architectural approach, is feasible in Java EE 6. This is primarily due to the changes made in EJB 3.x and in the introduction of JPA. The improvements made in the EJB 3.x and JPA specifications allow for a domain and application layer to be modeled in Java EE 6 using DDD. The basic idea here is to design an application ensuring that persistence services are injected into the application layer, and used to access/persist the entities within a transactional context established by the application layer.

Domain Layer
The application contains four domain entities for now - User, Group, Album and Photo which are the same as the JPA entities in the logical data model.

Repository Layer
On top of the logical data model you can find four repositories - UserRepository, GroupRepository, AlbumRepository and PhotoRepository. Each for one of the four domain entities. Even if the DDD requires that you only have repositories for an aggregated root, and not for all domain entities it is designed this way to allow the application layer to access the Album and Photo domain entities without having to navigate Albums and Photos via the UserRepository. The repositories are Stateless Session Beans with a no-interface view and are constructed using the Generic CRUD Service pattern published by Adam Bien.

Application layer
The application layer exposes services to be consumed by the presentation layer. It is also responsible for transaction management, while also serving as a fault barrier for the below layer(s). The application layer co-ordinates with the domain repositories and the domain objects to fulfill the desired objectives of the exposed services. In a way, this layer is the equivalent to a service layer in traditional applications. The application layer exposes it's services through the UserService, GroupService, AlbumService and PhotoService interfaces and is also responsible for validating the providing domain objects from the above layers, before co-ordinating actions among objects in the domain layer. This is done via JSR-303 constraints on the domain objects.

How it looks like
And this is, how this example looks like if you are running it on latest GlassFish 3.1.2. Curious to set this up yourself? Wait for the next post or give it a try yourself ;)

The second part guides you through the setup on GlassFish. Read on!
If you are interested in running this on latest WebLogic 12. Read the third part!

## Reviewing: Java SE Tutorials now available as eBook

12:29 Monday, March 5, 2012 Posted by
The news has been out since a few days. You now have the option to get all the Java SE tutorials as eBooks on either your iPad, Nook or eReader (capable of reading ePub files) or the Kindle (reading .mobi files).
All this happened with the March 2nd, 2012 release and you can directly download all the eBook files from otn.oracle.com after you accepted the Java SE Tutorial License Agreement. A total of 20 parts can be downloaded separately with a total of roughly 20.5 MB in the .mobi format. Ok. Let's have a look at how this works out on a Kindle.
As you can see, the separate downloads appear as separate books on your Kindle. This feels like an easy way to jump right where you need to go. Compared to The Java Tutorials website the overall order is screwed up. So, you need to know which one to look at first, or know the order in which you are willing to walk through. But anyway, if you are used to navigating the Kindle you have a quick and easy way of finding the content you need. I find it quite comfortable to read in general. A lot of this feeling is caused by the Kindle. It is very light, has a good contrast and I can put it in the back pocket of my jeans if I am traveling. So this is my new always with me gadget. Even if I am a very late follower on this, I really appreciate the fact that I have tons of books with me wherever I am.
Now lets look at the contents. Especially the source code. To be honest, I find it very readable. Even the images and charts are very clear.(Compare pictures of my Kindle below).

The only thing you probably will miss is the fact, that you can't copy and past the stuff from your kindle to your computer :) Everything else is very nice and I really like the way, the tutorials have been reworked for eBook-Readers in general.

## Agile Software Development with SCRUM

11:00 Monday, March 5, 2012 Posted by
One of the few posts for the German audience of my blog. Last week it happened to be, that I had the honor of giving a webcast/webinar about how we use SCRUM in our daily work. This was a session done together with Dr. Stephan Frohnhoff (member of the board of directors at the msg systems ag).