I have been trying to get to grips with Struts 2 recently. Lesson one: very little of your Struts 1 knowledge will carry over. Lesson two: documentation is skimpy and much less coherent that Struts 1.
My first experience was an hour and a half of bafflement until I saw that I had put the config file (called struts.xml now to avoid clashing with the original framework I suppose) under the web application initialisation folder instead of the root of the classpath (i.e. under WEB_INF rather than WEB_INF/classes). Because Struts 2 is all about the defaults I could not see any issue with what I was deploying until I realised that my application would generate the same error message (Action not in namespace) whether my xml config was valid or not.
This is a problem with XML-driven configuration in general but is also a specific defaulting issue. If the framework is defaulting it should say so rather than just silently defaulting everything. The alternative is to explicitly say what packages are being loaded from config but I think not finding a config file is more likely to be an error situation, after all what application is going to be deployed in the default state if you cannot interact with it? Even if the config file is empty you are still expecting there to be one…
Like most web frameworks the learning curve on Struts 2 is initially smooth as you put together Hello World before hitting a vertical climb when you want to do anything serious. Struts 2 relies a lot on injection via marker interfaces and interceptors in stacks; none of which really map to the Struts 1 world.
The goal of Struts 2 is to have a POJO based framework that is more unit-testable and less linked to the Servlet spec. I think it is successful in this and it is what has kept me perserving with the framework. However to do so it has made a lot of things very abstract and in terms of testing there is has been some headscratching as again a lot of Struts 1 testing strategies (which focus on mocking the various objects) do not really apply.
For example when trying to test whether an Action was correctly setting something in the Session Context I was stumped for a while and ended up using Action Context (something that the documentation on the web described as preferred and depreciated in different sources).
This solution didn’t sit well; after a bit of rethinking I finally got to the point where I decided to implement the SessionAware interface (which provides a Map parameterised setSession method) which worked when deployed but failed unit testing because I couldn’t figure out how to access the value of the session on the exit of the Action’s execute method.
The answer is easy, trivial almost but reflects the different way of thinking the new methodology requires. Since the injection engine will add the Session Context attribute map what goes into the setSession method is actually the container’s Session bound variables. Therefore when unit testing you just create a suitable map (Struts 2 doesn’t seem Generics aware but I presume the type is <String, ? extends Object>) pass it to the action via setSession but then retain a reference and test the content of the Map after the execute method of the Action has been called. It is easy but it is not easy to start thinking like this after Struts 1.