- A short introduction to using the open source project Jericho to parse HTML. Jericho includes text extraction from HTML markup, rendering, formatting and compacting HTML.
- A nice list of both strategic and technical factors you should consider when making decisions about integration in the blogpost EAI: when tools can help.
- The BBC used interesting semantic technologies on their soccer Worldcup 2010 website. See the architecture below:
- Pretty basic article on using DateFormat in a multi-threading environment. Tricky because they are not synchronized. You should definitely also consider Joda Time and the new Date and Time APIs for Java 7 (JSR-310).
- An explanation of how Sonar feedback metrics can be integrated into the code/test/commit/build cycle for a quality feedback loop.
The best articles and links to interesting posts for technical team leaders building sophisticated websites, applications and mobile apps. Think about: software architecture, hardware architecture, design, programming, frameworks, scalability, performance, quality assurance, security, resolving issues, fixing bugs and Android.
Sunday, July 25, 2010
Best of this Week Summary 19 July - 25 July 2010
Sunday, July 18, 2010
Best of this Week Summary 28 June - 18 July 2010
- How Google App Engine does session affinity explained. In short: as long as the requests from the client are within minutes (it seems) of each other, the requests will get send to the same node. If the time between two requests is longer, it might get sent to another node, potentially causing a noticable delay. A solution to prevent this is to send a 'ping' every minute from the client.
- Three Wicket unittesting tips.
- The CERT (Oracle) Secure Coding Standards for Java: "rules and recommended practices for secure programming in the Java Platform Standard Edition 6 environment. This is a work-in-progress and they actively seek your feedback and involvement in making this effort a success."
- Twitter was having problems deploying new versions of their site to thousands of servers. With a solution built on top of BitTornado (a modified version of Bittorrent), they were able to reduce deployment time from 40 minutes to 12 seconds! The solution named Murder (Python + Ruby) is available as open source.
Wednesday, July 7, 2010
Android performance tips
All videos and slides from sessions during Google's I/O conference last May 2010 are available here.
I watched The world of ListView and Writing zippy Android apps. Below are the items that were most interesting to me. They are all Android performance related.
The world of ListView
In general: don't try to outsmart the ListView by building your own caching, nor depend in any way on the order of getView(position) getting called.
Writing zippy Android apps
Zippy means non-janky which means sluggish, slow etc.
I watched The world of ListView and Writing zippy Android apps. Below are the items that were most interesting to me. They are all Android performance related.
The world of ListView
- 9:15: A View in Android costs about one or 2K of RAM
- 16:55: Call notifyDataSetChanged() (from the UI thread) when something in your adapter has changed.
- 18:27: getItemViewType() is used to make sure convertView is of the correct type in getView().
- 19:06: Make sure getViewTypeCount never changes. Note that it doesn't hurt performance if you always return say 10 even if you only have 2 different view types returned by getItemViewType().
- 30:13: Shows how to create a custom list selector in xml.
- 40:40: android:smoothScrollbar to prevent scrollbar changing size. Especially useful for listviews with items of which height can differ greatly
- 41:00: Use fill_parent instead of wrap_content in a ListView
- 53:10: If refreshing the whole screen via notifyDataSetChanged() is too much of a performance hit, you can try to get the visible position and use getChildAt() to figure out what view to update. Example code for that is here.
- 53:50: Use inflate(item, parent, false) to prevent relative layout attributes being ignored in a listview.
In general: don't try to outsmart the ListView by building your own caching, nor depend in any way on the order of getView(position) getting called.
Writing zippy Android apps
Zippy means non-janky which means sluggish, slow etc.
- 08:00: example apk of how not to do things/see how stuff performs. Includes small Perl sqllite wrapper script to see how much is being read from sqlite
- 15:00: read/writes I/O on emulator is a lot faster than on a real device
- 19:00: An AsyncTask can get killed before it finishes, e.g if the user hits the Home key. If it's important that the task finishes, use IntentService.
- 24:15: Profiling/tracing apps 'adb shell am profile ...' with the TraceView tool.
- 47:00: handling rotation when you don't want to reload your heavy objects: usegetLastNonConfigurationInstance() and onRetainNonConfigurationInstance(). See the Android reference for more info.
- 51:00: Think about using files instead of sqlite (if you have limited structured data for example)
Sunday, July 4, 2010
Lessons learned Wicket + Spring + Hibernate + Mod4J project
At a recent project we used the following tools & frameworks:
Below are a couple of lessons learned which I remembered to write down:
Wicket
JUnit
Mod4J
- Java JDK 6
- Wicket 1.4.8
- Spring 2.5
- Hibernate 3.2.5
- Mod4J 1.2.1
- Tomcat 6
- Oracle XE 10g
- Maven 2
- Eclipse Galileo
- JUnit 4.8.1
- DbUnit 2.4.7
- SVN
- OpenSSO
- Subclipse SVN plugin
- Eclipse IAM (Integration for Apache Maven)
- JIRA
- Continuum Continuous Integration
Below are a couple of lessons learned which I remembered to write down:
Wicket
- In a ModalWindow you'd probably want to use a AjaxSubmitLink, not a SubmitLink, if you want to use modalWindow.setWindowClosedCallback(). See here for explanation.
- ajaxrequesttarget.addComponent: addComponent name might be a bit confusing for beginners. It means "add the component to the list of components be re-rendered/refreshed".
- An AjaxSubmitLink doesn't update the model when setDefaultFormProcessing() is set to false. Not totally illogical, but you still might run it to it when you don't expect it.
- Here are tips to validate related fields. (In the original the example code is missing.)
- AjaxSubmitLink: if you get a "Component-targetted feedback message was left unrendered. This could be because you are missing a FeedbackPanel on the page" warning in your Tomcat server console, it seems you have to tell in the onError() of the AjaxSubmitLink which feedback panel(s) you want to have updated.
You get the warning even when you have feedback panels higher up in the tree of the (Base)Page. An example to update those panels could be:
Component infoFeedback = getPage().get("infoPanel");
target.addComponent(infoFeedback);
Component warnFeedback = getPage().get("warningPanel");
target.addComponent(warnFeedback);
Component errorFeedback = getPage().get("errorPanel");
target.addComponent(errorFeedback);
This solution was inspired by these posts: post1, post2, post3, post4. - To show/hide any HTML markup block dynamically, just wrap it with a WebMarkupContainer. In the code create that wrapper and make it visible or not depending on your requirements:
boolean makeVisible = false;
WebMarkupContainer blockContainer = new WebMarkupContainer("blockWrapper");
blockContainer.setVisible(makeVisible);
add(blockContainer); - Sometimes you might get a popup when using a ModalWinow that says "Reloading this page will cause modal window to disappear" when you don't expect it. Check the logs/console, you might just got an exception in your app (after which Wicket tries to redirect to the error page, which causes the popup to show; at least that's my reasoning).
JUnit
- If JUnit can't find the Spring context.xml in the resources directory, then you have to add the resources dir to your Build path
Mod4J
- Does not really support LazyLoading so not very efficient for large "graphs" of data/dependencies. In those cases you could decide to skip the DTO layer and directly access the domain model.
- The Maven plugin IAM in Eclipse can be turned off for the Mod4J models project in Eclipse, otherwise it runs twice: once by Mod4J features, once by Maven (plugin).