tag:blogger.com,1999:blog-22624018204446146062023-11-15T08:50:17.122-08:00What else can I not say?...Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-2262401820444614606.post-5775876105006779172009-06-17T12:05:00.000-07:002009-06-17T12:09:44.906-07:00Super Easy Password Generator!Real quick here. I needed to generate a random string for auto generated passwords. So I was thinking that I was going to have to write some stupid block of code to randomly select characters out of an array. <br /><br />However, I stumbled upon org.apache.commons.lang.RandomStringUtils.<br /><br />Then there was this rad method there: RandomStringUtils.random(int len, String chars)<br /><br />example:<br /><br />RandomStringUtils.random(8, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");<br /><br />Exactly what I needed! Thanks Apache Commons for being so RAD!<br /><br />Go write some code!Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-78273479594989565702009-04-16T08:35:00.000-07:002009-04-22T09:43:03.403-07:00RSS - XML == jsonSSI recently attended The Server Side Symposium in Las Vegas and attended a couple of sessions with <a href="http://davisworld.org/">Scott Davis</a> from <a href="http://thirstyhead.com/">Thirst Head</a>. He had a couple of great sessions on Groovy and JSON. I must say that Scott is an amazing presenter, if you ever get a chance to see him speak or need training I would highly recommend this guy. He is highly engaging and exciting to listen to. ( No he didn't ask for the endorsement. I just thought he was pretty rad. ) Anyways, so after attending the session "JSON in the Real World" I started to think about how JSON could make every web developers' life a TON easier. I had recently written some code to parse an RSS feed and thought to myself how annoying and overly complex it is. There is really no reason to deal with parsing XML in JavaScript.<br /><br />So I have been thinking about RSS feeds and how they are used and the hoops that everyone has to jump through just to display them on a web page. Usually this requires some sort of server side process to fetch the feed and then return that to the page that is being rendered. Basically proxying the call to get around browser security issues. Or you have to make the call to fetch the feed when the page is loading. No big deal really. But then you have to parse the XML.<br /><br />Sample RSS 2.0 response:<br /><pre><br /><?xml version="1.0" encoding="UTF-8" ?><br /><rss version="2.0"><br /> <channel><br /> <title>RSS Example</title><br /> <description>This is an example of an RSS feed</description><br /> <link>http://www.domain.com/link.htm</link><br /> <lastBuildDate>Mon, 28 Aug 2006 11:12:55 -0400 </lastBuildDate><br /> <pubDate>Tue, 29 Aug 2006 09:00:00 -0400</pubDate><br /><br /> <item><br /> <title>Item Example</title><br /> <description>This is an example of an Item</description><br /> <link>http://www.domain.com/link.htm</link><br /> <guid>1102345</guid><br /> <pubDate>Tue, 29 Aug 2006 09:00:00 -0400</pubDate><br /> </item><br /><br /> </channel><br /></rss><br /></pre><br /><br />The XML is not difficult to read or understand. It is pretty straight forward as to what is being conveyed. We can all agree on that. But then we have parse this response. Lets look at how ugly this really is. Here is just a snipet from <a href="http://www.xml.com/pub/a/2006/09/13/rss-and-ajax-a-simple-news-reader.html?page=3">XML.com</a>:<br /><pre><br />function RSS2Channel(rssxml)<br />{<br /> /*required string properties*/<br /> this.title;<br /> this.link;<br /> this.description;<br /><br /> /*optional string properties*/<br /> this.language;<br /> this.copyright;<br /> this.managingEditor;<br /> this.webMaster;<br /> this.pubDate;<br /> this.lastBuildDate;<br /> this.generator;<br /> this.docs;<br /> this.ttl;<br /> this.rating;<br /><br /> /*optional object properties*/<br /> this.category;<br /> this.image;<br /><br /> /*array of RSS2Item objects*/<br /> this.items = new Array();<br /><br /> var chanElement = rssxml.getElementsByTagName("channel")[0];<br /> var itemElements = rssxml.getElementsByTagName("item");<br /><br /> for (var i=0; i<itemElements.length; i++)<br /> {<br /> Item = new RSS2Item(itemElements[i]);<br /> this.items.push(Item);<br /> }<br /><br /> var properties = new Array("title", "link", "description", "language", "copyright", "managingEditor", "webMaster", "pubDate", "lastBuildDate", "generator", "docs", "ttl", "rating");<br /> var tmpElement = null;<br /> for (var i=0; i<properties.length; i++)<br /> {<br /> tmpElement = chanElement.getElementsByTagName(properties[i])[0];<br /> if (tmpElement!= null)<br /> eval("this."+properties[i]+"=tmpElement.childNodes[0].nodeValue");<br /> }<br /><br /> this.category = new RSS2Category(chanElement.getElementsByTagName("category")[0]);<br /> this.image = new RSS2Image(chanElement.getElementsByTagName("image")[0]);<br />}<br /></pre><br /><br />While this example is a bit more involved than what we really need to read the example feed that is outlined above, you can see how this simple syndication becomes really annoying. This code isn't even complete, as you can see. Some other objects are being created to deal with different elements. This is all very OO and what not, but look at how complex this gets.<br /><br /><br />So let's take the feed and convert it over to what it might look like in JSON. If you don't know what JSON is I suggest you got check out <a href="http://json.org/">JSON.org</a> and read about it. <br /><br />So we can see below how all of the same elements and values could be displayed in JSON as in the XML format. Pretty simple here and straight forward. <br /><br /><pre><br />{rss: version: "2.0", encoding: "UTF-8"<br /> channel: {<br /> title: "RSS Example",<br /> description: "This is an example of a JSON-S Feed",<br /> link: "http://someurl.com"<br /> lastBuildDate: "Mon, 28 Aug 2006 11:12:55 -0400",<br /> pubDate: "Tue, 29 Aug 2006 09:00:00 -0400",<br /> items: [<br /> {<br /> title: "Item Example",<br /> description: "This is an example item",<br /> guid: "1102345",<br /> pudDate: "Tue, 29 Aug 2006 09:00:00 -0400"<br /> }<br /> ]<br /> }<br />}<br /></pre><br /><br />Let us now look at how you might 'parse' this sort of response.<br /><br /><pre><br /> function parseJSONFeed(jsonFeed) {<br /> var version = jsonFeed.version;<br /> var encoding = jsonFeed.encoding;<br /> var channel = jsonFeed.channel;<br /> var title = channel.title;<br /> var description = channel.description;<br /> ...<br /> var items = channel.items;<br /> for ( i = 0; i < items.length; i++ ) {<br /> items[i].title; //do something with the info here<br /> items[i].description<br /> ...<br /> }<br /> <br /> }<br /></pre><br /><br />Now you can see how some huge undertaking to parse an RSS feed quickly becomes something of the past. Simply replacing the the RSS feed's XML with JSON makes your life much simpler. Now you no longer have to create a parser or all the other associated objects that you may need. Simply access the attributes using 'dot' notation.<br /><br />This all boils down to a proposal to make a new standard of jsonSS. JavaScript Object Notation Simple Syndication.<br /><br /><script type="text/javascript">var dzone_url = 'http://whatelsecaninotsay.blogspot.com/2009/04/rss-xml-jsonss.html';</script><br /><script type="text/javascript">var dzone_title = 'RSS - XML == jsonSS';</script><br /><script type="text/javascript">var dzone_blurb = 'JavaScript Object Notation Simple Syndication.';</script><br /><script type="text/javascript">var dzone_style = '1';</script><br /><script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script>Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com4tag:blogger.com,1999:blog-2262401820444614606.post-16726636869860148052009-01-05T16:04:00.000-08:002009-01-05T16:54:00.491-08:00Eclipse, Shared Heap, and You ( and that guy over there )So I have been thinking about how to incorporate Terracotta into the applications that I work on at my job for a while and so far we have come up with some good ideas as to how to leverage the Distributed Shared Objects ( or DSOs ), but it occurred to me today that there is something really, really cool that could be done with DSOs and Eclipse in a team/pair programming situation.<br /><br />Maybe you see where I am going with this, maybe not. But here it is. Create an Eclipse plug-in or extension that bootstraps the Eclipse editor classes so that we can make them shared objects in the Terracotta shared heap space. <br /><br />I'll let that sink in for a second... <br /><br />Ok, so now all you XP aficionados can take your pair-programming to a new level without the need for fancy pair-programming stations. Have the Eclipse editor classes shared in the heap, so when developer A starts writing code on workstation X, developer B can see the changes in his Eclipse on workstation Y. To start this up, developer A would just need to have the Terracotta server running on workstation X and the developer B would need to point his Eclipse at the Terracotta server running on workstation A. Then kablammo! A shared editing environment for free. <br /><br />A sample of how this works can be seen with the samples that come with Terracotta, specifically the "Shared Graphics Editor" that they ship with the download. In playing around with the graphics editor you can see that as changes are made in instance 1 of the editor they appear in instance 2 which can be running on a separate machine, while the Terracotta server is running on the same box as instance 1.<br /><br />I think I am going to venture into the world of Eclipse plug-ins to see if I can get a working example of this. I want to know what others think of this. Leave a comment and let me know if you would be interested in seeing something like this.<br /><script type="text/javascript">var dzone_url = 'http://whatelsecaninotsay.blogspot.com/2009/01/eclipse-shared-heap-and-you-and-that.html';</script><br /><script type="text/javascript">var dzone_title = 'Eclipse, Shared Heap and You';</script><br /><script type="text/javascript">var dzone_blurb = 'So I have been thinking about how to incorporate Terracotta into the applications that I work on at my job for a while and so far we have come up with some good ideas as to how to leverage the Distributed Shared Objects ( or DSOs ), but it occurred to me today that there is something really, really cool that could be done with DSOs and Eclipse in a team/pair programming situation.';</script><br /><script type="text/javascript">var dzone_style = '1';</script><br /><script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script>Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com3tag:blogger.com,1999:blog-2262401820444614606.post-40561801127380885252008-12-11T10:05:00.000-08:002008-12-29T10:10:44.074-08:00Spring, JMS, Topics, Queues, Templating...I recently had the opportunity to write some software at work that needed the ability to use JMS Message Broker to send asynchronous messages around my cluster and to perform data lookup and aggregation; then publish batches of aggregate data back out to another queue so that another cluster could then take that data and present it to the end user. I found that there was a lot of information out there to get this all started, but nothing too complete. So here is my attempt to take all the information that was out there and aggregate it so that someone else out there looking for this same information doesn't have to spend the hours it took to get all of the pieces together.<br /><br /><b>Summary of Technologies Used</b><hr />JMS - <a href="http://java.sun.com/products/jms/">Java Message Service</a><br />Topic - A distribution mechanism for publishing messages that are delivered to multiple subscribers.<br />Queue - A staging area that contains messages that have been sent and are waiting to be read. As the name queue suggests, the messages are delivered in the order<br />sent. A message is removed from the queue once it has been read.<br />Spring - using 2.5 at time of this article ( of particular interest <a href="http://static.springframework.org/spring/docs/2.5.x/reference/jms.html">JmsTemplate</a> )<br />Tomcat - using Tomcat 6.0<br />JNDI - <a href="http://java.sun.com/products/jndi/">Java Naming and Directory Interface</a><br />ActiveMQ - <a href="http://activemq.apache.org/">Powerful open source Message Broker</a>. Free, Open and easy to tweak and run. Great documentation! Always important.<br />Java - JSE 6 and Servlet Spec 2.4<br /><br /><br /><b>Getting started with ActiveMQ really took just a few minutes.</b><hr /><ol><li>Get the binary distribution from <a href="http://activemq.apache.org/">ActiveMQ on Apache</a>.</li><li>Unzip the binaries to your place of choice.</li><li>cd into the $ACTIVEMQ_HOME/bin and run activemq script.</li><li>then check <a href="http://localhost:8161/admin/">http://localhost:8161/admin/</a> to see that it is running. This is the cool admin console that comes with ActiveMQ. Great!</li><br /></ol>So now that we have our Message Queue Server up and running we can move on to how to use Spring to wire up your application to use the Queue.<br /><br /><b>Creating a Message Producer</b><hr />First we need to have a connection to our super secret JMS Broker. So to get this into our Spring configuration we add the following:<br /><pre style="border: thin solid black; padding: 5px;"><br /><bean id="connectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop"><br /><property name="connectionFactory"><br /> <bean class="org.apache.activemq.ActiveMQConnectionFactory"><br /> <property name="brokerURL" ref="brokerLocation" /><br /> </bean><br /></property><br /></bean><br /><br /></pre><br />brokerLocation is a reference to my JNDI config defined like so in my applicationContext.xml:<br /><pre style="border: thin solid black; padding: 5px;"><br /><jee:jndi-lookup id="brokerLocation" lookup-on-startup="true" jndi-name="jms/brokerLocation" resource-ref="true" cache="true" /><br /><br /></pre><br />Spring's support for JNDI is truly amazing and painless... Definitely check it out. This is literally all you have to do reference JNDI values in your Spring application!<br /><br /><pre style="border: thin solid black; padding: 5px;"><br /><Environment name="jms/brokerLocation" override="false" type="java.lang.String" value="tcp://some.host.at.your.com:61616"/><br /><br /></pre><br />So all this wires up the connection factory to use for, well, connecting to your message broker.<br /><br />The cool thing with this, is that if you decide at some point to change what message broker you were using this is the only thing you would have to change in your application.<br /><br />The next step is to define a name for the queue you want to put messages on. This is what you do. The constructor-arg is the name of the queue that you want to send messages to.<br /><pre style="border: thin solid black; padding: 5px;"><br /><bean id="queueOne" class="org.apache.activemq.command.ActiveMQQueue"><br /><constructor-arg value="QUEUE.ONE" /><br /></bean><br /><br /></pre><br />Then simply define the class that will be used to create the messages to be place on the queue. You need to have a handle on a javax.jmx.Queue and a org.springframework.jms.core.JmsTemplate. The template is then used to send messages to the broker. Below you will see this set up. The produce method is called from an external class with what ever you want to put on the Queue. Here I am passing in 2 String values in and then using a javax.jms.MapMessage to create a message of key/value pairs to be placed on the queue.<br /><pre style="border: thin solid black; padding: 5px;"><br />package com.foo.jms;<br /><br />import javax.jms.ConnectionFactory;<br />import javax.jms.JMSException;<br />import javax.jms.MapMessage;<br />import javax.jms.Message;<br />import javax.jms.Queue;<br />import javax.jms.Session;<br /><br />import org.apache.log4j.Logger;<br />import org.springframework.beans.factory.annotation.Required;<br />import org.springframework.jms.core.JmsTemplate;<br />import org.springframework.jms.core.MessageCreator;<br /><br />public class TestProducer {<br /><br />private Logger logger = Logger.getLogger(TestProducer.class);<br />private JmsTemplate jmsTemplate;<br />private Queue queue;<br /><br /> public void produce(final String foo, final String bar) {<br /> this.jmsTemplate.send(this.queue, new MessageCreator() {<br /> public Message createMessage(Session session) throws JMSException {<br /> MapMessage mm = session.createMapMessage();<br /> mm.setString("foo", foo);<br /> mm.setString("bar", bar);<br /> return mm;<br /> }<br /> });<br /> logger.info("Message sent to message broker");<br /> }<br /><br /> @Required<br /> public void setConnectionFactory(ConnectionFactory connectionFactory) {<br /> this.jmsTemplate = new JmsTemplate(connectionFactory);<br /> }<br /><br /> @Required<br /> public void setQueue(Queue queue) {<br /> this.queue = queue;<br /> }<br />}<br /><br /></pre><br /><br />Here is how we wire up the above class with Spring. You can see that we pass in the connectionFactory that we defined earlier and a reference to the Queue that we also defined above.<br /><br /><pre style="border: thin solid black; padding: 5px;"><br /><bean name="testProducer" class="com.foo.jms.TestProducer"><br /> <property name="connectionFactory" ref="connectionFactory" /><br /> <property name="queue" ref="queueOne" /><br /></bean><br /><br /></pre><br /><br /><b>Creating a Message Consumer</b><hr />This is going to be fairly similar to creating a message producer. So now we define the message listener or consumer; whatever you want to call it.<br /><br /><pre style="border: thin solid black; padding: 5px;"><br /><bean name="fooListener" class="com.foo.jms.FooListener" /><br /><br /></pre><br /><br />This looks a little like WTF?! Right? Yeah I thought so as well. So here is the class com.foo.jms.FooListener:<br /><br /><pre style="border: thin solid black; padding: 5px;"><br />package com.foo.jms;<br /><br />import javax.jms.MapMessage;<br />import javax.jms.Message;<br />import javax.jms.MessageListener;<br /><br />import org.apache.log4j.Logger;<br /><br /><br />public class FooListener implements MessageListener {<br /><br /> private Logger logger = Logger.getLogger(FooListener.class);<br /><br /> @Override<br /> public void onMessage(Message message) {<br /> try {<br /> if (message instanceof MapMessage) {<br /> MapMessage mapMessage = (MapMessage) message;<br /> String foo = mapMessage.getString("foo");<br /> String bar = mapMessage.getString("bar");<br /> //...do something with the data you just got<br /> }<br /> } catch (Exception e) {<br /> logger.error(e);<br /> }<br /> }<br />}<br /><br /></pre><br /><br />The cool thing here is that your Message Listener just has to implement the javax.jms.MessageListener interface and then you wire that class up in Spring and then add this to your beans tag xmlns:jms="http://www.springframework.org/schema/jms" and in the xmlns:context add "http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-2.5.xsd". Also you need to specify the destination which is just the name of the queue that you want to listen for. Like this:<br /><pre style="border: thin solid black; padding: 5px;"><br /><jms:listener-container connection-factory="connectionFactory" cache="none"><br /> <jms:listener destination="QUEUE.ONE" ref="fooListener" /><br /></jms:listener-container><br /><br /></pre><br /><br />Now we are all set to send and receive messages to/from the Message Broker. But how about subscribing to a topic. The reason for doing this is so that all N of your servers in your cluster pick up on the message that gets published to the topic. Here is how we publish messages to the topic queue.<br /><br /><b>Publishing to a Topic</b><hr />First we need to define an instance of a javax.jms.Topic by using the org.apache.activemq.ActiveMQTopic implemementation of the Topic interface.<br /><br /><pre style="border: thin solid black; padding: 5px;"><br /><bean id="topicOne" class="org.apache.activemq.command.ActiveMQTopic"><br /> <constructor-arg value="TOPIC.ONE" /><br /></bean><br /><br /></pre><br /><br />Now that we have the Topic defined we need to pass that to a class that knows how to publish to the topic. Here is the configuration:<br /><br /><pre style="border: thin solid black; padding: 5px;"><br /><bean name="topicPublisher" class="com.foo.jms.TopicPublisher"><br /> <property name="connectionFactory" ref="connectionFactory" /><br /> <property name="topic" ref="topicOne" /><br /></bean><br /><br /></pre><br /><br />Here we are using the same config as defined earlier for the connectionFactory. We just need to pass the reference in along with a reference to the Topic that we just created.<br /><br />Here is what you class will look like:<br /><br /><pre style="border: thin solid black; padding: 5px;"><br />package com.foo.jms;<br /><br />import javax.jms.ConnectionFactory;<br />import javax.jms.JMSException;<br />import javax.jms.Message;<br />import javax.jms.ObjectMessage;<br />import javax.jms.Queue;<br />import javax.jms.Session;<br />import javax.jms.Topic;<br /><br />import org.springframework.beans.factory.annotation.Required;<br />import org.springframework.jms.core.JmsTemplate;<br />import org.springframework.jms.core.MessageCreator;<br /><br />public class TopicPublisher {<br /><br /> private JmsTemplate jmsTemplate;<br /> private Topic topic;<br /><br /> public void produce(final Object object) {<br /> this.jmsTemplate.send(this.topic, new MessageCreator() {<br /> public Message createMessage(Session session) throws JMSException {<br /> ObjectMessage mm = session.createObjectMessage();<br /> mm.setObject(object);<br /> return mm;<br /> }<br /> });<br /> }<br /><br /> @Required<br /> public void setConnectionFactory(ConnectionFactory connectionFactory) {<br /> this.jmsTemplate = new JmsTemplate(connectionFactory);<br /> }<br /><br /> @Required<br /> public void setTopic(Topic topic) {<br /> this.topic = topic;<br /> }<br />}<br /><br /></pre><br /><br />Now this looks pretty much identical to the TestProducer we defined earlier and it is, except the fact that it is using a javax.jms.Topic instead of a javax.jms.Queue. You can push any Serializable object on to the Queue/Topic.<br /><br /><b>Subscribing to a Topic</b><hr />The last portion here is subscribing to this Topic we just created. This is similar to listening to a Queue, the difference here is the destination-type is set to "topic". With this listener defined we are now 'subscribed' to the Topic.<br /><br /><pre style="border: thin solid black; padding: 5px;"><br /><bean name="topicListener" class="com.foo.jms.TopicListener"/><br /><br /><jms:listener-container connection-factory="connectionFactory" cache="none" destination-type="topic"><br /> <jms:listener destination="TOPIC.ONE" ref="topicListener" /><br /></jms:listener-container><br /><br /></pre><br /><br />Here is the code. Same as before pretty much. Implement MessageListener and Spring takes of registering with the Message Broker. When a new message has been published to the topic, this listener will pick it up and automagically call the onMessage method defined below in the TopicListener class.<br /><br /><pre style="border: thin solid black; padding: 5px;"><br />package com.foo.jms;<br /><br />import javax.jms.Message;<br />import javax.jms.MessageListener;<br />import javax.jms.ObjectMessage;<br /><br />import org.apache.log4j.Logger;<br /><br />public class TopicListener implements MessageListener {<br /><br /> private Logger logger = Logger.getLogger(GeoDisplayListener.class);<br /><br /> @Override<br /> public void onMessage(Message message) {<br /> try {<br /> if (message instanceof ObjectMessage) {<br /> ObjectMessage mapMessage = (ObjectMessage) message;<br /> Object obj = mapMessage.getObject();<br /> //... do something with the data here<br /> }<br /> } catch (Exception e) {<br /> logger.error(e);<br /> }<br /> }<br />}<br /><br /></pre><br /><br /><b>Summary</b><hr />So adding JMS support into your Spring-based application is pretty easy and painless. The one thing that you should take note is the difference between a Queue and a Topic. If you don't need multiple machine to get the same message as it is placed on the Message Broker then use a Queue. That is a Queue holds onto a message just long enough for 1 message listener to pick it off. Otherwise, if you have the need to have a message to be picked off by a cluster of machines then use the Topic. With a Topic, the Message Broker knows that it needs to hold onto the message until all subscribers of the Topic get their copy of the message.<br /><br />Hope this was helpful to someone. This was definitely a fun exercise in resume building. ;)<br /><script type="text/javascript">var dzone_url = 'http://whatelsecaninotsay.blogspot.com/2008/12/spring-jms-topics-queues-templating_2519.html';</script><br /><script type="text/javascript">var dzone_title = 'Spring, JMS, Topics, Queues, Templating';</script><br /><script type="text/javascript">var dzone_blurb = 'Configure and use JMS Message Broker with Spring';</script><br /><script type="text/javascript">var dzone_style = '1';</script><br /><script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script>Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com12tag:blogger.com,1999:blog-2262401820444614606.post-3626808703239395102008-12-03T21:12:00.001-08:002008-12-11T10:52:02.300-08:00Spring, Filters and Configuration easier than you think.So I needed to add a filter for some cool stuff in my application.<br /><br />First off I needed to get my filter to play nicely with Spring, so I needed to do the following in my web.xml<br /><pre class=""><br /><filter><br /> <filter-name>myCoolNewFilter</filter-name><br /> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><br /> <init-param><br /> <param-name>targetBeanName</param-name><br /> <param-value><span style="font-weight:bold;">myCoolNewFilterSpringBean</span></param-value><br /> </init-param><br /></filter><br /></pre><br />So then I go ahead and open up my applicationContext.xml file and wire up the bean like normal<br /><br /><bean name="<span style="font-weight: bold;">myCoolNewFilterSpringBean</span>" class="com.mycompany.filter.MyCoolNewFilter" /><br /><br />Notice that the bean name in the app context matches the param-value in the filter config: <span style="font-weight: bold;">myCoolNewFilterSpringBean</span><br /><br />Then instead of trying to do URL patterns for the config of the filter I just tried the following:<br /><pre><br /><filter-mapping><br /> <filter-name><span>myCoolNewFilterSpringBean</span></filter-name><br /> <span style="font-weight: bold;"><servlet-name>dispatcher</servlet-name></span><br /></filter-mapping><br /></pre><br />Which maps this filter to all filter all calls being directed to my dispatcher servlet! No nasty or convoluted URL patterns... Just easily readable servlet names!Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com2tag:blogger.com,1999:blog-2262401820444614606.post-19677594450324331052008-12-03T14:54:00.000-08:002008-12-03T21:42:05.630-08:00Kill your database! Pt. 2Friend of mine beat me to it... check out the post <a href="http://willcode4beer.com/design.jsp?set=kill_your_db">Kill Your Database with Terracotta</a> over at <a href="http://willcode4beer.com/">Will Code 4 Beer</a>.<br /><br />It is an interesting article challenging the idea that we need a database to begin with. There may be an excuse for a database in some cases, but for many applications it is overkill. When you need a super fast, scalable application to hold on to just enough data then Terracotta can store your objects to disk and allow your entire cluster to share state through the shared Heap. It is an interesting read, so go check it out.Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-90045501597997737412008-11-20T16:40:00.001-08:002008-11-20T16:42:46.580-08:00Kill your database!<a href="http://www.terracotta.org/">Share the heap! For free! Across the farm! Yes!</a><br /><br />I am going to put something together over the next couple of weeks that will increase performance, scalability and decrease downtime!<br /><br /><br />And no I do not work for these <a href="http://www.terracotta.org/">guys</a>.Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-37332713583921241992008-10-07T15:27:00.000-07:002008-10-07T15:28:51.778-07:00..."If company culture was checked into CVS, I would be the first to commit." -- what.else October 2008Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-40306169060456206582008-09-20T22:45:00.000-07:002008-12-03T21:24:59.147-08:00Tip of the Day! || /etc/hosts is your friendFrom time to time I find myself having to deal with tracking down the root cause of a bug in production. While this doesn't happen often, it is something that all of us have to deal with. Today I found myself in that very situation, where I needed to try and figure out the root cause of an issue people all over the world are experiencing.<br /><br />After a number of hours it finally occurred to me to fire up my server on my dev machine and then edit my /etc/hosts file. Duh! Route all the requests to the prod server back into my local machine! This worked well in my case since I was dealing with a partner site, which uses web services through a flash client. ( I wrote the web services not the flash ). This was pretty much the best/only way to track down the issue, since we were not seeing anything unusual on the server itself. I could go and experience the partner site as anyone would but then when it came to the issue at hand I needed to simulate a particular situation, which I was able to do. So while this is not ground-breaking ( I know ) it is just something to keep in mind. Had I done this sooner I wouldn't have had to work on the weekend. Oh well...<br /><br /><br />This post brought to you by <a href="http://www.anchorbrewing.com/">Anchor Steam!</a>Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-35795627841232513452008-07-25T14:26:00.000-07:002008-11-12T11:21:42.912-08:00ExternalizationSo I am working on a project at work using Java 6, Spring ( DI and MVC ), ehcache, SOAP(Axis), ibatis, and some other cool stuff. But that is the core of it. Anyways. Early on some decisions were made to make so decisions based on tracking parameters passed in by the client of the web application. So lets say request parameter foo would have known values of a,s,d,f...N and so on. But these were always going to be known. Well, of course this decision by the TEAM has been forgotten and I needed a way to add flexibility to the application configuration so that when new "foo's" are added, the configuration could be updated to handle it.<br /><br />My initial reaction was:<br /><br /><p>"Well, I could have the values/config stored in the database and then just cache them."</p><br /><br />But that solution would require days because I would have to create the tables, get them ok'd by the db ops team, have them put in the different environments( test, integration, stage, and then finally production ). Then on top of that I would have to create some sort of tool to manage the values in the table so that they could be updated as needed. Then I would have to secure the the admin page for the config management. And so on and so forth.<br /><br />Then it occurred to a <a href="http://willcode4beer.com">co-worker</a> and I that we could just externalize the Spring Bean definition and cache it for a set amount of time ( and of course relying on the last good configuration if the new one fails ). The external config for the Spring Bean could then live anywhere ( local file system, or over http on a server somewhere ).<br /><br />This of course was by far the most flexible and convenient way of dealing with the situation. So here is how it works.<br /><br />Step 1: Create Factory.<br /><div style="width: 650px; height: 750px; overflow-x: auto; overflow-y: auto; border:black thin solid;"><br /><pre><br />public class ServiceFactoryFactoryContextLoader<br />implements ApplicationContextAware, IServiceFactoryFactoryContextLoader<br />{<br /> private ApplicationContext parentContext;<br /> private IServiceFactory serviceFactory;<br /> private String location;<br /><br /> public IServiceFactory getServiceFactory() {<br /> String [] configs = new String[]{location};<br /> ApplicationContext applicationCtx = new ClassPathXmlApplicationContext(configs,true, parentContext );<br /> try {<br /> serviceFactory = (IServiceFactory)applicationCtx.getBean("serviceFactory");<br /> } catch (Exception e) {<br /> Logger.getLogger(this.getClass()).error("Uh... Houston we have a problem... Remote Config is not good", e);<br /> }<br /> return serviceFactory;<br /> }<br /><br /> @Override<br /> public void setApplicationContext(ApplicationContext applicationContext)<br /> throws BeansException <br /> {<br /> this.parentContext = applicationContext;<br /> }<br /><br /> public void setLocation(String location) {<br /> this.location = location;<br /> }<br />}<br /></pre><br /></div><br />Step 2: Enter the JNDI config for location of your externalized resource in the applicationContext.xml:<br /><pre><br /><jee:jndi-lookup id="serviceFactoryConfig" startup="true" <br /> name="conf/serviceFactoryConfig" <br /> ref="true" <br /> cache="true"></jee:jndi-lookup><br /></pre><br /><br /><br />Step 3: Wire factory up in applicationContext.xml<br /><br />Set up the ServiceFactoryFactoryContextLoader with the cache proxy of course so that we can cache the retrieval and creation of the object. The property 'location' gets injected with the JNDI config value for the location of the externalized resource. And the cache:proxy allows me t cache any method beginning the 'get'. I am using ehcache for my caching but you can use others if you want/need to.<br /><pre><br /><bean id="serviceFactoryTarget" <br /> class="com.foo.bar.factory.ServiceFactoryFactoryContextLoader"><br /> <property name="location" ref="serviceFactoryConfig" /><br /></bean><br /><cache:proxy id="serviceFactory" refId="serviceFactoryTarget"><br /> <cache:caching methodName="get*" cacheName="serviceFactoryTarget" /><br /></cache:proxy><br /></pre><br /><br /><br />Step 4: Pull the Bean definition out of the applicationContext.xml and into its own config with the Spring beans tag and xmlns declarations.<br /><br /><pre><br /><?xml version="1.0" encoding="UTF-8"?><br /><br /><beans xmlns="http://www.springframework.org/schema/beans" <br /> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xsi:schemaLocation="http://www.springframework.org/schema/beans <br /> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"><br /><br /><bean id="serviceFactory" class="com.foo.bar.service.ServiceFactory"><br /> <property name="lookups"><br /> <map><br /> <entry key="default"><br /> <bean class="com.foo.bar.service.ServiceLookupKey"><br /> <property name="var1" value="foo" /><br /> <property name="var2" value="bar" /><br /> <property name="resourceExt" value="default" /><br /> </bean><br /> </entry><br /> <entry key="bar"><br /> <bean class="com.foo.bar.service.ServiceLookupKey"><br /> <property name="var1" value="baz" /><br /> <property name="var2" value="xyz" /><br /> <property name="resourceExt" value="bar" /><br /> </bean><br /> </entry><br /> </map><br /> </property><br /> </bean><br /></beans><br /></pre><br /><br /><br />And of course you need to define the JNDI values however you want.<br /><br />So now that the application is configured we can launch the application and once the ServiceFactoryFactoryContextLoader.getServiceFactory() is called the app will make a call out to the externalized location to get the config, load it with the parent context ( which in this case is the applicationContext ) and then you can make the call to get the bean in the externalized config from Step 4 ( "serviceFactory" ). And there it is... the externalized config is now set so that I can host the config where ever I want it; on the local file system somewhere or over http on another server.<br /><br /><script type="text/javascript">var dzone_url = 'http://whatelsecaninotsay.blogspot.com/2008/07/externalization.html';</script><br /><script type="text/javascript">var dzone_title = 'Externalization of Configuration';</script><br /><script type="text/javascript">var dzone_blurb = 'Externalize Application Configuration with Spring';</script><br /><script type="text/javascript">var dzone_style = '1';</script><br /><script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script>Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-17119554806739802662008-06-20T10:37:00.000-07:002008-07-30T14:56:56.513-07:00jQuery + JSON == blissSo I have had the need to work with some more javascript, dhtml and ajax user interactions and have found the the amazing library <a href="http://jquery.com/">jQuery</a>. I know this isn't new and tons of people are using it, but I have just recently had a need for something more robust and extensible than prototype and script.aculo.us.<br /><br />I think the coolest thing about jQuery is that people are writing plugins. This is extremely useful when you are just trying to get something done and there is just a plugin you can use that does what you want to do.<br /><br />Simple plugins like the <a href="http://plugins.jquery.com/project/DOMEC">DOM Element Creator</a> plugin are just the sort of things that are amazing. Anything that I can use that just makes DOM manipulation easier is much appreciated. <br /><br />The other thing that is pretty nifty is the <a href="http://ui.jquery.com/">jQuery UI</a> stuff that they have going. Definitely check out the demos, there is some cool stuff, especially the carousel they have for the available demos. Just check it out. Pretty impressive.Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-45000237222652406072008-05-14T14:24:00.000-07:002008-05-14T14:34:42.533-07:00Been a long timeSo its been nearly a year since my last post. I have dealt with Rails, loved it, hated it, and have pretty much moved on. Easy to write an application in no time at all. More stable than some of the other applications deployed at my place of employment ( which have been around far longer than mine ). Mind you it took just 4 months to get the application up and running. However, I know that has nothing to do with Rails, it has to do with the people writing the software.<br /><br />It doesn't really matter what language you use for the the job at hand; if the team of people writing the software don't know what they are doing then your project is doomed from the get-go.<br /><br />I have since moved back into the wonderful world of java and am pretty happy being back. Java is like that girlfriend that you get in arguments with all the time, but still keep coming back. You love her to death, but there is always some sort of nuance that just drives you nuts from time to time. Whether that is poor communication ( documentation ) or just a small incompatibility ( classpath issues and jars not there when you need them - damn you maven! ) that you need to work around sometimes. But at the end of the day you just love the familiarity and the comfort of the one you have come to love. That's java. Plain and simple. Yeah there are a lot of other fish in the sea, and you are tempted by the others swimming by, but java just feels right. Its temperamental, but faithful and stable. The other thing is she has decent friends you can also count on. Sometimes they are there and sometimes they are not, but when you can find them when you need some help, they are there to help (thanks open source community).<br /><br />Anyways. I am back to blogging. Soon there will be info about my new bike and how much it rocks to ride in SF.<br /><br />go write some code!Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-34433463572294825192007-09-12T08:54:00.000-07:002007-09-12T09:01:56.013-07:00Rails Training Cont.So the Rails training that I was in went really well. I think that for anyone who is considering getting into the world of Rails would benefit from a class like this one. However, if you have been using Rails for a little while and have been reading through Agile Web Development with Rails, there will be little benefit from a class like this. Pretty much everything in the first 10 chapters of the book is covered, so if you have gone through that you may not want to take a class like this. On the other hand it was cool to hear from someone who has been using rails for a while to see what tools and plugins they use to work on their projects.<br /><br />For example:<br /><ul><li>ZenTest - awesome continuous integration tool.</li><li>redgreen - some fluff for the output of ZenTest.</li><li>rcov - amazing code coverage tool.<br /></li></ul>These were just some of the things that Brandon talked about that I am already using in my project. I think there is a lot to be said about attending a class. Sometimes its not so much the language or the framework that you really get out of a training class as it is the real world experience and tips from someone who knows what he is talking about.<br /><br /><br />Go write some code!!!Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-12053154257441471192007-09-04T12:46:00.000-07:002008-07-25T16:34:19.777-07:00Rails TrainingSo here is a quick post. I am sitting in a training facility here in SF taking a 4 day Rails training course from <a href="http://www.marakana.com/">Marakana</a> lead by <a href="http://opensoul.org/">Brandon Keepers</a>. Today is day 1 and so far so good. The class is small and the instructor is smart. I think that this is going to be a great class.<br /><br />Today is just an intro to the Rails framework with an overview of Ruby. I am still very impressed with Rails and with this class I hope that I can get my noob questions answered.<br /><br />Go write some code!Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com1tag:blogger.com,1999:blog-2262401820444614606.post-27148845004233208882007-08-24T23:11:00.000-07:002007-08-24T23:25:09.828-07:00Ruby On RailsSo, I have been playing around with Rails for a few weeks now and I must say that this is probably the happiest I have ever been. Writing simple clean code that just makes sense and works is awesome! Models that have the data access in them, awesome! Controllers that just control and map to a view, awesome! I could go on and on and on about how much I love this language. Java is solid, but Rails is easy, fast and simple. I could write about something in particular, but at this point in time there isn't much that I could say that someone else hasn't said.<br /><br />I need to start looking into the unit testing side of things for Rails. I know that there is some info on Ruby unit testing in the pickaxe book and there is some testing info in the agile web dev book ( both from <a href="http://www.pragmaticprogrammer.com/bookshelf/index.html">pragmatic programmers</a> ). These are some of the best books ever. I must say that everything that I have read that has 'David Thomas' on the cover has been just awesome.<br /><br />If there is anyone reading this, which at this point there is no one, feel free to comment on this topic.<br /><br /><br />Also, if you are writing a fB app like everyone else in the world and are using Rails you have to check out <a href="http://rfacebook.rubyforge.org/">rFacebook</a>. Seriously, this makes the whole process of getting up and running, writing a facebook app stupid simple... a couple of lines of code and kablammo! you are off to the races... Start writing the next stupid app that gets bought by some big corporation for millions only because they aren't agile enough to write their own!!!!! Crazy! Seriously!<br /><br /><br />Go write some code... OUT!Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0tag:blogger.com,1999:blog-2262401820444614606.post-61141592311190242022007-07-20T08:52:00.001-07:002007-07-20T09:00:02.361-07:00Ruby On RailsSo last night I finally took the plunge into the world of Ruby on Rails. While I have yet to start writing any code, I did get MySQL, Ruby, and Rails installed. Now I am looking for a good editor for the darn files. I use <a href="http://eclipse.org/">Eclipse</a> for my Java development and am pretty sure that there are some Ruby plugins for it, but it was late and I needed to go to bed.<br /><br />Any how, I finally started this adventure since an old friend of mine runs <a href="http://www.piratespress.com/">Pirates Press</a>, which is a record pressing company, and he is going to need someone to help enhance and maintain his site. So, I am sure that I will be posting about my adventures with Ruby On Rails.<br /><br />I guess I need to visit Amazon and get a book on it... That might be the best thing for now.Ryanhttp://www.blogger.com/profile/07402337690671174910noreply@blogger.com0