This is why I have been so quiet...the Tizra Publisher platform has evolved immensely during the last couple of months...which of course means a pretty busy time...and fun for that matter...And we are now posting a video tour of Tizra Publisher...
Been too long since I last wrote here. Tizra has been pretty busy picking up a ton of enthusiasm from customers and prospects (see Tizra Blog). That means, of course, a pretty busy time... :-)
I recently had to do a complete reinstall of my development environment. My laptop went dead and I had to get a new one...so that leads to the typical "absolutely essential" lists...today I reinstalled all my Firefox Add-ons. The good thing about reinstalls is that you cut the fat accumulated throughout the years and the absolute musts get installed first. Here is my list of absolute musts (in no particular order):
Selenium IDE: if you're doing any kind of serious development, you want to have a good test coverage. Selenium is a really cool tool to allow you to build automated UI and system integration testing. Selenium IDE makes your life *a whole lot easier* (although not dead-simple). You still have to tweak a lot of the generated code but hey, it's a really great start. And if you have not seen Selenium yet, you have to go take a look. It is not necessarily simple to get into but well worth it!
User Agent Switcher: really nice for that kind of testing that involves user agent detection...you can even "roll your own" agent identification for test purposes.
Web Developer: a really essential set of tools for web development. CSS inspection, changing, DOM information, source viewing, browser resizing, you name it, it's probably here.
Live HTTP Headers: a nice tool to let you see the header flow from and into your browser. Sometimes essential for analysis of behavior.
Firebug: you can't say you do web development and not know about Firebug. Simply brilliant. If you have not seen it yet, tell no one about that and go check it out for yourself.
This is what happens when you join in a single "package" an artist and a techie...Marcelino Martins had already assembled a pretty cool site filled with really impressive pictures (see here). With Brazil Pictures, Marcelino joins his photographic artistic talent to his techie talent...he has already developed some pretty cool packages like Treeview...Now he's been playing the Google APIs, XML, Ajax...the result is the really interesting Brazil Pictures. And take a look at his implementation notes for a very interesting read.
I am pretty excited to see the first set of AgilePDF sites go live...we (Tizra) are indeed live at this point. You can now see the results of this effort at the following sites.
Francisco Assis Rosa's Publications. Now, would I not be eating my own dog food ? I honestly find the system pretty cool and am publicly using it to store and offer my publications online. Privately I keep a copy of the system on an internal network where I keep all my favorite tech reading. It is really handy to be able to search through the full collection of my favorite texts and get relevant results *to the page*....nice.
eat.shop guides. Some pretty cool eating and shopping guides...smartly written, gorgeously presented.
Rate It Green. Live access digital edition to "Green Building 101".
Why do I feel so excited about this ?
These customers were able to hop on online without any significant investment. We are talking days instead of months between agreement and go live (and that with full design customization!), we're talking about revenue from online selling in the first couple of days. Yup, they did not have to wait six months to see a dollar, or even more to get their money back from the site building investment.
The technology set used in this system is a pretty exciting technology allowing us to take advantage of a lot that's good out there...
I could see a nice use for personal users like me that have some content that want to distribute online. Either free or for sale...you name it.
As far as system features go, these are some of the items that make me believe AgilePDF is cool:
End-user page-at-time PDF rendering, allowing for getting back web usability that was taken back by the placement of unwieldy PDFs online (50Mb PDF downloads to read *one* page anyone? Make that over slow connections ?).
Full text search over the content of the site/sub-site/single document with results returned at the page level (again, instead of result pointing at full PDF).
Full fledged configurable access control over your content.
Full ecommerce configurability. Whoever owns the site can create their own products (including products resulting from combinations of pages from different documents in the site), create their own selling offers and just put it out for the test. We allow hooking up to PayPal and Authorize.Net right now but as requests come in we will be expanding the list of payment fulfillers.
Full site design configurability. We offer some out-of-the-box designs you can use but you can change all the look of your site by dragging and dropping site blocks around your pages...and if you really want to go crazy on your design, just upload your CSS and you can do what you want (just compare Francisco Assis Rosa's Publications to Rate It Green to eat.shop guides!).
Full site structure configurability. Via the administration web interface you can create sub-sites based on filtering of meta data in your documents. When I said "full site design configurability" in the previous item I really meant it, you can even have these sub-sites look completely different from the main site and/or other sub-sites.
Google crawling, analytics and adsense integration...speaks for itself! ;-)
And...you can always drop me a line if you wish to use something like this...
This is just our first release...we are and will continue to work on this...
Like Dan commented on the Unit Testing Struts 2.0 (Part 2) post, Struts 2.0 has changed it's API enough to make my previous code not work on latest version. So, in response to his comment, here is what I am using right now. Credit where it's due, the setup code is the one that The Arsenalist pointed out on his blog post Unit Testing Struts 2 Actions wired with Spring using JUnit. Again, credit where it's due...my thanks go to "The Arsenalist" for posting his solution.
/** * Class for easier support of Struts related * testing. Takes care of all the configuration details * that allow test classes to create beans (Spring), * actions (Struts), intercepted actions (Struts). * Class is singleton to minimize hit of initializing * Struts and related infrastructure (e.g. Hibernate). * * Adapted from code from "The Arsenalist" (http://arsenalist.com/), * see http://arsenalist.com/2007/06/18/unit-testing-struts-2-actions-spring-junit/ */ public class StrutsTestCaseSupport {
/** * Singleton access */ public static synchronized StrutsTestCaseSupport getInstance() throws Exception { if ( _theInstance == null ) { _theInstance = new StrutsTestCaseSupport(); } return _theInstance; }
/** * Class constructor, take care of Struts initializations */ private StrutsTestCaseSupport () throws Exception { String[] config = new String[] { "/WEB-INF/applicationContext.xml" };
// Link the servlet context and the Spring context servletContext = new MockServletContext(new FileSystemResourceLoader()); XmlWebApplicationContext appContext = new XmlWebApplicationContext(); appContext.setServletContext(servletContext); appContext.setConfigLocations(config); appContext.refresh(); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, appContext);
// Use spring as the object factory for Struts StrutsSpringObjectFactory ssf = new StrutsSpringObjectFactory(null, null, servletContext); ssf.setApplicationContext(appContext); StrutsSpringObjectFactory.setObjectFactory(ssf);
// Dispatcher is the guy that actually handles all requests. Pass in // an empty Map as the parameters but if you want to change stuff like // what config files to read, you need to specify them here // (see Dispatcher's source code) dispatcher = new Dispatcher(servletContext, new HashMap()); dispatcher.init(); Dispatcher.setInstance(dispatcher); }
/** * create a bean from the object factory (all wired up from Spring) * * @param beanName the name of the bean to get from the object factory * @param extraContent any extra content information to pass along to the bean building * process * @return the object factory created bean * @throws Exception on processing, configuration errors, test failure */ public Object createBean ( String beanName, Map
Like mentioned in previous postings, using this class is pretty straightforward, within your test you just do for beans:
Here we go again, it's that time of the year where good things are about to happen. September is marked by two major events: the release of Halo 3 ;-) and the return of the No Fluff Just Stuff conference (now called the New England Software Symposium). I have written about this even before but it does not hurt to repeat it...this is a really impressive conference and a must if you live around the Boston area. It takes place during a Friday afternoon and over the weekend. This is actually a great decision since it simplifies a lot the "need to be out of work" argument with your bosses. Sure it takes over your weekend but, if you're in this business you are most probably hooked enough to this stuff for this not to be a problem. The attendance to this event is capped at around 250 which is another great feature since it does allow you to be in those rooms listening to the presentations in a much close environment. You get to interact with the presenters both during the talks and during the breaks by mingling in lunch tables or just approaching them directly. The topics are amazing and, like I mentioned before (see here), the really annoying part of the even is choosing which sessions to go to. The price for the event is really a find...pretty affordable even if, like me, you do not get your company to sponsor you and pay out of your own pocket.
This fall, the Boston even takes place on the 14th (PM), 15th and 16th of September in Framingham, Massachusetts. For all the details, check out the event site.
I got my place already booked, what are you waiting for ?
In the hope that this adds to the list of solutions out there that can actually help people... If you are having keyboard mapping issues when trying to connect via vncviewer to a machine running vncserver on Ubuntu Feisty (7.04) with gnome, try this:
I have recently got the opportunity to get my hands on a copy of Vista Ultimate at MS employee prices. I jumped at the opportunity and, as soon as I ensured all my crucial apps actually ran on Vista (VMWare Workstation in particular), proceeded to install it on my laptop. I spend my working hours (and others for that matter) using this laptop so, although I surely did not get to explore all the niceties of Vista, I got the daily use experience of running it. The first impression was the "Wow" that MS advertises so much. It is indeed an eye-candy-filled OS. It looks awesome and all the UI interactions have been tuned to please the eye, Windows Aero is indeed really enticing. But...the niceties of a new UI only last so much...My daily work is spent mostly on another OS environment. All my work is done on Linux and I had been used to depend on VMWare Workstation to be able to get the best of both worlds and jump around as needed. My experience with XP and VMWare Workstation had been impeccable and I could not recommend it more...Then came Vista...oh well...Suddenly my Pentium 4 3.4Ghz with Hyperthreading, 2Gb RAM started grinding to a halt. Although a year old now, this is not (I believe) a run-of-the-mill laptop...A laptop with these specs should be able to handle this OS plus the apps that I needed to run on top of it! My frustration grew when looking at memory usage on Vista...Just starting up brought me to 600Mb usage, with VMWare I was up to 1.6Gb...this on a 2Gb RAM machine...And I started looking through the nice UI and thinking seriously that I could not work daily with this...The initial "Wow" turned into "Wow, this is unbearable!". So, after some serious consideration I decided it was time to byte the bullet and wipe out my system and replace it by something more snappy that actually made good use of my hardware...Ubuntu 7.04 to the rescue! Ok, I am not religious about the OS war and am one of the people who tries to take advantage of whatever each has to offer so, being the gamer that I am, I left Vista on a dual boot setup alongside Ubuntu (I still have hopes of playing Halo 2 on Vista someday to get my achievements! ). Now I am running Linux as a first OS...my life became a lot less stressing...and I can still run Windows XP or Win 2K on a VMWare Workstation virtual host for all the testing I need to do...The best of both worlds I would say...
With this Windows Vista we are bound to see a new need to get new hardware where once what you had was just fine...and, to be honest, without any real *day to day* real important enhancements that I can see (again, I stress the *day to day*... you might do cool and important things on Vista but I'm betting these are completely irrelevant for the common user).
But I believe Ubuntu 7.04 (and Linux in general) is still not there as well...I had to jump through some serious loops to get my Wireless card and my sound card to work on my laptop...It has evolved immensely no doubts. I still remember the old Linux installations of the early nineties where you really had to be courageous and curious to even try it. But good as it is this is hardly mass user ready...
In response to a comment made to Unit Testing Struts 2.0, here is the updated, complete code for Struts 2.0 testing. Hope this is useful. Have questions ? Want to discuss any of this ? Just drop me a line...Read on, includes support class code, small snippets for creation of Spring beans, Struts 2.0 actions, Struts 2.0 action proxies.
/** * Class for easier support of Struts related * testing. Takes care of all the configuration details * that allow test classes to create beans (Spring), * actions (Struts), intercepted actions (Struts). * Class is singleton to minimize hit of initializing * Struts and related infrastructure (e.g. Hibernate). * * @author Francisco Assis Rosa */ public class StrutsTestCaseSupport {
/** * Singleton variable */ public static StrutsTestCaseSupport _theInstance;
/** * Singleton access */ public static synchronized StrutsTestCaseSupport getInstance() { if ( _theInstance == null ) { _theInstance = new StrutsTestCaseSupport(); } return _theInstance; }
/** * Application context class (encapsulation of applicationContext.xml) */ ConfigurableWebApplicationContext _applicationContext;
/** * Configuration Manager object, to allow for encapusulation of struts.xml, * creation of actions and their proxied counterparts, creation of * servlet context from this application context */ ConfigurationManager _configurationManager;
/** * Class constructor, take care of Struts initializations */ private StrutsTestCaseSupport () {
// create the struts+spring integrated object factory // set spring autowiring by name for spring object factory Settings.set(StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE,"name"); StrutsSpringObjectFactory objectFactory = new StrutsSpringObjectFactory();
// set system object facory ObjectFactory.setObjectFactory(objectFactory);
// set action proxy factory ActionProxyFactory.setFactory(new StrutsActionProxyFactory());
// create a web application context instance (for spring configuration) _applicationContext = new XmlWebApplicationContext();
// get ahold of a servlet context to use in the creation of the application context ServletContext servletContext = createOneServletContext(_applicationContext); // complete application context initialization, pass in servlet // context and config file location, force reading of config (via refresh) _applicationContext.setServletContext(servletContext); _applicationContext.setConfigLocations(new String[] {"WEB-INF/applicationContext.xml"}); _applicationContext.refresh();
// initialize the object factory with the mock servlet context, application context objectFactory.init(servletContext); objectFactory.setApplicationContext(_applicationContext);
// add a default dispatcher to the system Dispatcher du = new Dispatcher(servletContext); Dispatcher.setInstance(du);
// pass over to the configuration manager location where struts-default.xml, // struts-plugin.xml and struts.xml can be found, force reading all _configurationManager = new ConfigurationManager(); _configurationManager.addConfigurationProvider( new StrutsXmlConfigurationProvider("struts-default.xml", false)); _configurationManager.addConfigurationProvider( new StrutsXmlConfigurationProvider("struts-plugin.xml", false)); _configurationManager.addConfigurationProvider( new StrutsXmlConfigurationProvider("struts.xml", false)); _configurationManager.reload(); }
/** * create a servlet context useable for a specific action * * @param applicationContext the application context to use in the servlet context * @return the created servlet context */ protected ServletContext createOneServletContext (ConfigurableWebApplicationContext applicationContext) { // create a servlet context for this action, use FileSystemResourceLoader for // context to find configuration files ServletContext servletContext = (ServletContext) new MockServletContext(new FileSystemResourceLoader());
// initialize freemarker manager config parameter to null (let FreemarkerManager figure // out configuration location out of ServletContext) Settings.set(StrutsConstants.STRUTS_I18N_ENCODING, "UTF-8"); servletContext.setAttribute(FreemarkerManager.CONFIG_SERVLET_CONTEXT_KEY,null);
// hand over application context to servlet context servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, applicationContext);
return servletContext; }
/** * Build one action context for an accessmethod and an access url * * @param serverName the hostname that the request will need to hook up to * @param accessMethod http method to use (e.g. 'get', 'post', 'put', etc) * @param accessUrl the url to access * @return the map for the action's context * @throws Exception on processing, configuration errors, test failure */ public Map buildActionContext ( String serverName, String accessMethod, String accessUrl, Map requestParamMap ) throws Exception { // get ahold of a brand new servlet context ServletContext servletContext = createOneServletContext(_applicationContext);
// create fake request and response objects MockHttpServletRequest request = new MockHttpServletRequest(servletContext,accessMethod,accessUrl); MockHttpServletResponse response = new MockHttpServletResponse();
// set request server name request.setServerName(serverName);
// add context, request and response to an action context map Map actionContext = new HashMap(); actionContext.put(StrutsStatics.SERVLET_CONTEXT,servletContext); actionContext.put(StrutsStatics.HTTP_REQUEST,request); actionContext.put(StrutsStatics.HTTP_RESPONSE,response); actionContext.put(ActionContext.DEV_MODE,new Boolean(false)); // add request parameters to action context Map actionContextParams = new HashMap(); for ( String oneParamName : requestParamMap.keySet() ) { String[] paramValue = new String[1]; paramValue[0] = requestParamMap.get(oneParamName); actionContextParams.put(oneParamName,paramValue); } actionContext.put(ActionContext.PARAMETERS,actionContextParams);
return actionContext; }
/** * create a bean from the object factory (all wired up from Spring) * * @param beanName the name of the bean to get from the object factory * @param extraContent any extra content information to pass along to the bean building * process * @return the object factory created bean * @throws Exception on processing, configuration errors, test failure */ public Object createBean ( String beanName, Map extraContext ) throws Exception { return ObjectFactory.getObjectFactory().buildBean(beanName,extraContext); }
/** * create an action proxied by it's interceptor stack * * @param actionName the name/id for the action * @param actionNameSpace the namespace for the action * @param actionContext the action context for creating the proxy (created from buildActionContext) * @return the proxyed action * @throws Exception on processing, configuration errors, test failure */ public ActionProxy createActionProxy ( String actionName, String actionNamespace, Map actionContext) throws Exception { return createActionProxy(actionName,actionNamespace,actionContext,new HashMap()); }
/** * create an action proxied by it's interceptor stack * * @param actionName the name/id for the action * @param actionNameSpace the namespace for the action * @param actionContext the action context for creating the proxy (created from buildActionContext) * @param sessionMap the request/invocation session map (for http session map mocking) * @return the proxyed action * @throws Exception on processing, configuration errors, test failure */ public ActionProxy createActionProxy ( String actionName, String actionNamespace, Map actionContext, Map sessionMap ) throws Exception { ActionProxy actionProxy = ActionProxyFactory.getFactory().createActionProxy(_configurationManager.getConfiguration(),actionNamespace,actionName,actionContext);
// set the session map in the action proxy's invocation actionProxy.getInvocation().getInvocationContext().setSession(sessionMap);
return actionProxy; }
/** * create an action object, bypass all it's stacks. Have it properly injected * according to configurations. * * @param actionName the name/id for the action * @param actionNameSpace the namespace for the action * @param actionContext the action context for creating the proxy (created from buildActionContext) * @return the properly injected action * @throws Exception on processing, configuration errors, test failure */ public Object createAction ( String actionName, String actionNamespace, Map actionContext ) throws Exception { // get ahold of the action's configuration via the XWorkConfigRetriever class ActionConfig actionConfig = _configurationManager.getConfiguration().getRuntimeConfiguration().getActionConfig(actionNamespace,actionName);
// create one instance of the action to test using the object factory, pass in action config and context return ObjectFactory.getObjectFactory().buildAction(actionName, actionNamespace, actionConfig, actionContext); }
Or to do a full fledged Struts 2.0 action proxy test:
// create action for ActionSearchTest Map requestParameters = new HashMap(); requestParameters.put("searchMode","quick"); requestParameters.put("searchText","Testing"); Map actionContext = StrutsTestCaseSupport.getInstance().buildActionContext("struts.assisrosa.com","get","/search/results",requestParameters);
// create the proxy for the action, this encapsulates all // the interception stack up to the real action ActionProxy proxy = StrutsTestCaseSupport.getInstance().createActionProxy("results","/search",actionContext);
// let the full stack run String result = proxy.execute();
// confirm result, any exception thrown will cause test to fail assert result.equals("success");
Or a Struts 2.0 action test (no proxy in front of it):
Continuous integration is a practice introduced by Extreme Programming (XP) that brings in the idea that developers should check in their code often and that their work should be continuously integrated and tested to ensure that no error goes unnoticed (see article by Martin Fowler). The practice is tightly integrated with the concepts of source control, unit testing and automated building as these are the privileged means of bringing the code together and running tests on it. Continuous integration (CI) not only works nicely but does enforces some pretty important habits to developers.
Developers working on a CI project will be required to use source control for their code. Sounds like a basic tool for any development project but I've seen too many projects where source control is completely absent...CI simply requires it...nice.
Developers working on a CI project will be rewarded by putting in place as many unit tests as possible. How ? By seeing that less errors will sneak by because of the existence of this safety net of testing. It is pretty cool to see that you avoid putting mistakes into production because of this first line of defense. Better our CI screaming at us than our clients right ?
Developers working on a CI project get used to the concept of automated building and the concept of building from scratch. Again, often have I seen in the past cases where code that is not rebuilt regularly from scratch becomes too entangled in dependencies that prevent it from building from a clean slate.
All these make for pretty strong points in favor of CI. And it is not that hard to put it in place...There is a significant amount of tools that joined together make for a great CI platform. Just look around. A winning combination for me, developing in Java, has been:
Cruise Control. A CI framework that glues together all the components to provide a pretty decent CI setup. From HTML reporting to email notification of success failures of builds, this is a pretty cool tool to use.
Subversion. A version control system that addresses a lot of the typical weak spots of other version control systems (e.g. CVS).
Ant. An automated build tool for Java. I doubt anyone working in Java never heard of Ant.
TestNG. A really cool testing framework for Java. Check it out...
All of the above are free tools that you can get and play with, together they make up for a pretty strong CI.
CI takes a step ahead when talking about Continuous Database Integration (CDBI). Paul Duvall at Test Early has been doing some pretty interesting presentations on it. It does bring a new level of testing to your database-driven apps. One which enforces the cooperation between developers and database administrators and builds a structure that ensures that you can deploy your application at any point in time. If you ever seen a project where to redeploy in a new system you have to go chasing for the DB schema required to deploy a clean system, you know the kind of sorrows CDBI can save you from.
I simply *guarantee you* that if you ever start using CI, you will not want to work again without it.
The title does sound presumptuous but after reading it you can only agree that if there is any Javascript book worth reading, this is it. David Flanagan does a most excellent work of introducing the Javascript language and of exploring all the kinks and nice features that you can take from it.
Having known Javascript for sometime I could not avoid being wowed in some chapters by some cool features that I really did not know existed in the language.
This 5th edition is well worth it even if you read previous editions. I did have a previous version and found that this new edition brings a significant amount of new content worth spending your budget in.
The book is well structure dividing it's presentation in core javascript and client-side javascript. Something I really liked seeing.
The core Javascript section presents pretty successfully crucial aspects of the language like closures and prototyping (among many others)...Even if you already know Javascript you should give it a try...I'm almost sure you will learn something from it.
The client-side Javascript is where this book gets even more of its value... from a fantastic CSS reference chapter (I do not believe you need much more than this to get you rolling with CSS), to even handling, DOM navigation, XML handling and scripting with Java, Flash, charting with Javascript and CSS (way cool). A really interesting read.
Like I said before, if you're out to get just one (or your first) Javascript book, I believe this is it! An interesting and absolutely essential read for any web developer these days.
If you have to deal with any DNS configuration or want to do some analysis on any other existing DNS, DNSstuff.com might just do the trick for you...Including analysis such as DNS reporting (pretty useful since it can point out any errors you might have in your DNS entries), spam database lookups, DNS record retrieval, among many others, this is a time-saver and a great find. Another tool for my tool belt.
Revision: since I put up this post, DNSstuff is no longer free. A shame since this was a way cool and useful service.
Unit testing is now (or should be) an established step of the development process in any project. If you're not writing unit tests, you are pretty much leaving yourself ready to commit errors over and over again. Granted there is a category of testing other than unit testing that can be put in place to give you that safety net (see WebTst ;-) ) but unit testing has it's well deserved place in the must do list.
Testing however will only happen, let's face it, if it becomes dead easy (or close to that) for developers to write tests. Crunch time has the tendency to make developers drop their testing efforts and if putting them up is in any way hard or cumbersome, it will not happen.
So I started looking at simplifying unit testing for Struts 2.0 (recently merged from WebWork). This is, IMHO, a pretty smart and elegant web framework (topic for another post maybe) that if you have not seen, should take a look at. I am using TestNG for my testing framework (again, a topic for another post maybe, again a pretty smart framework). One of the selling points of WebWork and Struts 2.0 was the idea that testing your actions should be pretty simple due to the nature of the framework. Dependency injection would be a good step to achieve simplicity in testing and allow you to detach yourself from the need of a servlet container to run your tests.
And so I dived into trying to add unit testing to my Struts 2.0 actions. Here is what I would like to do ideally to test my actions purely:
and to test my actions with the interceptor chain in front of them, something which I believe should be pretty important to test in the context of Struts 2.0:
ActionProxy myActionProxy = getActionProxy("myActionUrl"); String result = myActionProxy.execute();
I would then like to do testing on results coming out for execution of the actions. Both testing on result strings and testing on HTML returned in the case of the action proxy where we can get access to the fully processed response. Ideally I would like to make it as simple as above, could make it a bit more involved in some cases...but it should always be dead-easy to write a test. So the answer (to me) is a support class to help with writing unit tests. Ready for code dump ? Here it goes, snipped in the non-relevant aspects. Class implements the singleton pattern and relevant methods for Struts testing are:
/** * Class constructor, take care of Struts initializations */ private StrutsTestCaseSupport () {
// create the struts+spring integrated object factory // set spring autowiring by name for spring object factory Settings.set(StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE,"name"); StrutsSpringObjectFactory objectFactory = new StrutsSpringObjectFactory();
// set system object facory ObjectFactory.setObjectFactory(objectFactory);
// set action proxy factory ActionProxyFactory.setFactory(new StrutsActionProxyFactory());
// create a web application context instance (for spring configuration) _applicationContext = new XmlWebApplicationContext();
// get ahold of a servlet context to use in the creation of the application context ServletContext servletContext = createOneServletContext(_applicationContext);
// complete application context initialization, pass in servlet // context and config file location, force reading of config (via refresh) _applicationContext.setServletContext(servletContext); _applicationContext.setConfigLocations(new String[] {"WEB-INF/applicationContext.xml"}); _applicationContext.refresh();
// initialize the object factory with the mock servlet context, application context objectFactory.init(servletContext); objectFactory.setApplicationContext(_applicationContext);
// add a default dispatcher to the system Dispatcher du = new Dispatcher(servletContext); Dispatcher.setInstance(du);
// pass over to the configuration manager location where struts-default.xml, // struts-plugin.xml and struts.xml can be found, force reading all _configurationManager = new ConfigurationManager(); _configurationManager.addConfigurationProvider( new StrutsXmlConfigurationProvider("struts-default.xml", false)); _configurationManager.addConfigurationProvider( new StrutsXmlConfigurationProvider("struts-plugin.xml", false)); _configurationManager.addConfigurationProvider( new StrutsXmlConfigurationProvider("struts.xml", false)); _configurationManager.reload(); }
/** * create a servlet context useable for a specific action * * @param applicationContext the application context to use in the servlet context * @returns the created servlet context */ protected ServletContext createOneServletContext (ConfigurableWebApplicationContext applicationContext) { // create a servlet context for this action, use FileSystemResourceLoader for // context to find configuration files ServletContext servletContext = (ServletContext) new MockServletContext(new FileSystemResourceLoader());
// initialize freemarker manager config parameter to null (let FreemarkerManager figure // out configuration location out of ServletContext) Settings.set(StrutsConstants.STRUTS_I18N_ENCODING, "UTF-8"); servletContext.setAttribute(FreemarkerManager.CONFIG_SERVLET_CONTEXT_KEY,null);
// hand over application context to servlet context servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, applicationContext);
return servletContext; }
/** * Build one action context for an accessmethod and an access url * * @param serverName the hostname that the request will need to hook up to * @param accessMethod http method to use (e.g. 'get', 'post', 'put', etc) * @param accessUrl the url to access * @returns the map for the action's context */ public Map buildActionContext ( String serverName, String accessMethod, String accessUrl, Map requestParamMap ) { // get ahold of a brand new servlet context ServletContext servletContext = createOneServletContext(_applicationContext);
// create fake request and response objects MockHttpServletRequest request = new MockHttpServletRequest(servletContext,accessMethod,accessUrl); MockHttpServletResponse response = new MockHttpServletResponse();
// set request server name request.setServerName(serverName);
// add context, request and response to an action context map Map actionContext = new HashMap(); actionContext.put(StrutsStatics.SERVLET_CONTEXT,servletContext); actionContext.put(StrutsStatics.HTTP_REQUEST,request); actionContext.put(StrutsStatics.HTTP_RESPONSE,response); actionContext.put(ActionContext.PARAMETERS,new HashMap()); actionContext.put(ActionContext.DEV_MODE,new Boolean(true));
return actionContext; }
/** * create a bean from the object factory (all wired up from Spring) * * @param beanName the name of the bean to get from the object factory * @param extraContent any extra content information to pass along to the bean building * process * @returns the object factory created bean */ public Object createBean ( String beanName, Map extraContext ) throws Exception { return ObjectFactory.getObjectFactory().buildBean(beanName,extraContext); }
/** * create an action proxied by it's interceptor stack * * @param actionName the name/id for the action * @param actionNameSpace the namespace for the action * @param actionContext the action context for creating the proxy (created from buildActionContext) * @returns the proxyed action */ public ActionProxy createActionProxy ( String actionName, String actionNamespace, Map actionContext) throws Exception { return createActionProxy(actionName,actionNamespace,actionContext,new HashMap()); }
/** * create an action proxied by it's interceptor stack * * @param actionName the name/id for the action * @param actionNameSpace the namespace for the action * @param actionContext the action context for creating the proxy (created from buildActionContext) * @param sessionMap the request/invocation session map (for http session map mocking) * @returns the proxyed action */ public ActionProxy createActionProxy ( String actionName, String actionNamespace, Map actionContext, Map sessionMap ) throws Exception { ActionProxy actionProxy = ActionProxyFactory.getFactory().createActionProxy(_configurationManager.getConfiguration(),actionNamespace,actionName,actionContext);
// set the session map in the action proxy's invocation actionProxy.getInvocation().getInvocationContext().setSession(sessionMap);
return actionProxy; }
/** * create an action object, bypass all it's stacks. Have it properly injected * according to configurations. * * @param actionName the name/id for the action * @param actionNameSpace the namespace for the action * @param actionContext the action context for creating the proxy (created from buildActionContext) * @returns the properly injected action */ public Object createAction ( String actionName, String actionNamespace, Map actionContext ) throws Exception { // get ahold of the action's configuration via the XWorkConfigRetriever class ActionConfig actionConfig = _configurationManager.getConfiguration().getRuntimeConfiguration().getActionConfig(actionNamespace,actionName);
// create one instance of the action to test using the object factory, pass in action config and context return ObjectFactory.getObjectFactory().buildAction(actionName, actionNamespace, actionConfig, actionContext); }
With this support class, I can now write my tests:
// create action context for my action, feed // into the action context all request parameters Map requestParameters = new HashMap(); requestParameters.put("param1","param1-value"); requestParameters.put("param2","param2-value"); Map actionContext = StrutsTestCaseSupport.getInstance().buildActionContext("my.hostname.com","get","/myActionNamespace/myActionName",requestParameters);
// create the proxy for the action, this encapsulates all // the interception stack up to the real action ActionProxy proxy = StrutsTestCaseSupport.getInstance().createActionProxy("myActionName","myActionNameSpace",actionContext); // if needed be, get ahold of particular action underlying proxy and // inject parameters as required
// let the full stack run String result = proxy.execute();
// confirm result assert result.equals("myTestResponseString");
// look into mock HttpServletResponse, do whatever // tests I need to do: returned HTML, returned headers, // cookies, etc... String responseXml = ((MockHttpServletResponse)actionContext.get(StrutsStatics.HTTP_RESPONSE)).getContentAsString(); assert responseXml.indexOf("success") != -1;
Or test unproxyed actions directly:
// create action for my action Map requestParameters = new HashMap(); requestParameters.put("param1","param1-value"); requestParameters.put("param2","param2-value"); Map actionContext = StrutsTestCaseSupport.getInstance().buildActionContext("my.hostname.com","get","/myActionNamespace/myActionName",requestParameters);
// create the proxy for the action, this encapsulates all // the interception stack up to the real action Action myAction = StrutsTestCaseSupport.getInstance().createAction("myActionName","myActionNameSpace",actionContext); // if needed be, get ahold of particular action underlying proxy and // inject parameters as required
// let the full stack run String result = myAction.execute();
// confirm result assert result.equals("myTestResponseString");
So testing became *a lot* simpler to me...my support class deals with all infrastructure hooking up and my test is simplified...and more tests get written... ;-)
Last year I dove into the iPod addiction...Maybe not very typically, I really did not get into it because of music but because of technical podcasts. Music I can do in a number of other ways but the amount of technical podcasts that are out there for free is just overwhelming and it can be a fantastic source for free training and technical news feed. I have not regretted diving into it yet and am currently in a iPodaholic state. This is a fantastic way to make your commute useful and pleasurable. Ironically I now think my commute is just too short (got me an iTrip FM transmitter to hook it up to my car radio). :-) Podcast shows are getting more and more interesting and show durations are getting longer with deeper more involved content coming in. To any developer these days I say that listening to podcasts is now an essential way to keep up to date, in addition to book reading, playing with cool stuff after-hours, magazines and blogs (and I wonder where time goes!?!!?). I should also be saying that podcasting is not only about technical podcasts.....there is pretty much a podcast for any thing you might think of.
Anyway, these are the must-have-on-my-iPod podcasts:
The Java Posse: in my opinion, the best podcast out there on Java development. These guys do news info update, analysis of tools, overall software development discussions. Absolutely top of my list.
Software as She Developed: pretty interesting podcast on software development. The author Michael Mahemoff is the author of the Ajax Design Patterns book so you can expect this podcast to bring in a good amount of that experience.
Audible Ajax: name says all, a really good podcast on Ajax.
Software Engineering Radio: good presentations on software engineering in general. Covering topics like agile development, SOA, development processes, etc.
Javapolis: one of the best Java conferences around. You can find podcast feeds for some of the presentations in here. A free way to "be" at the conference.
TalkCrunch: a really interesting podcast on web 2.0 companies.
Venture Voice: talks and discussions on entrepreneurship.
If you have not tried the podcasting listening experience I would say you need to try it! You can try it before you buy your player just by getting iTunes for instance...
And...if you have any other interesting tech podcast please drop me a line! I want more! :-)
Tizra's blog is now alive! In there you should hope to find the Tizra's team ramblings on the web publishing world...technical hints, development process observations, geekly comments and cool notes on what is going on. The blog is alive at http://tizra.blogspot.com/. I will be splitting some of my blogging time between this blog and the new Tizra blog, but putting on the new blog some more focus on what we are doing at Tizra and practices that worked there. Check it out!
Wikis should now hold, I believe, a crucial place in every development team's utility belt. Information sharing, knowledge transmission, they all represent fundamental aspects of the development process within a team. There are a ton of wikis out there (e.g. see JSPWiki for instance) that provide the full features that will allow for this information knowledge base repository to be implemented.
Now, sometimes wouldn't it be nice to have a small personal wiki to jot your thoughts, todo lists, tips and tricks ? Something that you probably would not want to store on a shared wiki. TiddlyWiki gives you just that. For starters it is pretty impressive the ease in which you can start doing something with it....You just download a single html file (loaded with javascript functionality) drop it into a directory on your disk and access it via a browser. That's it. no more installation steps/tools/servers required! You're up-and-running ready to start writing. How cool is that ? And bringing features like tagging, RSS this brings an even more useful experience to the mix.
Yet another tool in my tool belt (will probably need a new belt sometime soon...mine is getting too crowded...;-) ).
Damn you Jay Zimmerman for making my life so hard during the No Fluff Just Stuff conference days ;-). For two and a half days you made me go through the excruciating pain of having to choose one presentation for each time slot...I mean...you could have put boring, uninteresting sessions in there to make my life easier but nooooooo...you had to give us a choice of absolutely fascinating topics presented by brilliant speakers. And pretty much at all time slots ? Come on....I came back refreshed and enthusiastic from the presentations, exhausted from the selection process.
Now seriously (in case you have not picked up *yet* that I'm joking), the No Fluff Just Stuff conference was simply fantastic. The organization, and Jay Zimmerman in particular, did a fantastic job of putting this together. The place was pretty well setup, the materials were really good and organized, the topics impressive (I would have gone to all of them could I clone myself!), the speaker list really overwhelming. You would get to hear the presentations in decently sized rooms (not huge theater like places like other conferences), you would get to interact with the speakers (in and out of the sessions) to ask questions and just exchange ideas. And there were even nice goodies raffled among the audience (I was not one of the lucky ones to get a prize but hey, that was not what I went there for ... obviously still trying to rationalize! ;-) )
In short...count me in for the next one! This is a hidden gem of a conference!
And, if you could not make it, you can still get the No Fluff Just Stuff Anthology from any shelf of any good tech bookstore (or amazon if you also consider virtual shelves for that matter).
Now we're cooking! Last week I upgraded my Blogger blogs to the new Blogger Beta...This new beta adds a couple of new features that I consider to be crucial for a useful and rich blog.
You are now able to add tags to my blog entries (have you checked my right navigation bar since then ? ;-) ) thus effectively achieving category grouping of these entries.
You can now create private blogs. And why would I want that you may ask ? For small teams it is often useful to have a repository of shared information and/or comments. While for some things the use of a Wiki (see Wikipedia entry for Wiki) fits the bill of storing and sharing knowledge, for others the use of a blog can be more appropriate (not impossible to do via a Wiki, just a bit more awkward). Recent news of interest, cool interesting things out there, these all fall more into the info better usable in a blog.
It provides a drag-and-drop interface for blog template management, provides an enhanced set of blogger tags for simpler layout management.
It provides an enhanced user interface for some of the blog's visual components, take a look for instance at the new archive navigation tree, pretty cool.
At this point I will have to boast a bit and put in my shameless plug...;-)
<shamelessPlug>
If you like what you see in terms of control of the appearance of your blog, you should *really* see what we are doing at Tizra...We are building a web tool for pdf content publishers, the AgilePDF product, that gives the admin user total control over all aspects of their site including presentation, content management, search, access control, creation and selling of admin defined products. The layout definition component in particular is a component that currently really overwhelms what the Blogger page editor is offering, if you liked that one, you should see ours! ;-) It offer the means to change the presentation of the site by providing a pretty nifty drag-and-drop interface for site structuring definition and CSS definition interface.
The Publishing experience makes use of currently available rich client technologies thus eliminating the typical "Push and Pray" experience of a good number of publisher applications out there making it possible for people to *actually know* what is going on when interacting with the system.
At the end of the day, a nice looking (actually as nice as you might want to make it! ;-) we offer nice looking canned solutions that might get you started towards a nice looking site but you are free to do whatever you want with it, including make it look ugly if for nothing else to make a statement! :-) ), site is out there with your content properly presented, giving you a nice web-like experience to content that usually is not very web-friendly.
</shamelessPlug>
If Blogger was already a nice tool for bloggers and small companies, it becomes even more so after these nice enhancements. I'll keep drilling through the new beta...blogging...
If you are looking for some computer science talks/presentations, Research Channel is a nice gathering place for a whole number of interesting presentations on a number of different topics (and other non CS related topics for that matter). The University of Washington Computer Science and Engineering site also presents a pretty cool list of colloquiums available for public viewing. Spanning a whole slew of CS subjects, from Distributed Storage Systems to Google's Linux Cluster, the list is just too big to reproduce here....
All in all a pretty cool resource for getting to learn a bit more....Fair warning: you could be in there for some serious time...;-)
The No Fluff Just Stuff Symposium has been doing the rounds for sometime now...This is an excellent event for Java developers, architects, testers, etc... It usually displays an impressive list of presentations covering a good range of Java and/or Software Development topics and usually brings some pretty interesting names of the Java development community for the presentations. The symposium goes around the country so there is a good chance you might get one close to you...If you have not heard about it, check it out at the No Fluff Just Stuff site.
My registration to the Boston NFJS symposium Sep. 29 - Oct. 1 2006 is already in...See you there! :-)