Monday, 16 June 2008

What is Loose Coupling?

I see many people throwing the term "loose coupling" around without understanding it. Many use the term without reference. Worse, there seems to be a sophomoric misinterpretation of it which can be summarized as "tight coupling is always bad".

Despite the fact that speak about loose coupling, there are precious few good descriptions of exactly what it is. Fortunately, Wikipedia (as of the writing of this blog) gets the definition right, defining loose coupling as "an approach where integration interfaces are developed with minimal assumptions between the sending/receiving parties, thus reducing the risk that a change in one application/module will force a change in another application/module". The words I emphasize are "minimal" and "risk". The word minimal cannot be replaced with "no". Also, loose coupling is is about mitigating risks of change, and you must not gloss over this. Even Wikipedia could explain these points more.

To really understand loose coupling, we must first acknowledge that as designers, we are essentially gambling on the types of changes our system will be asked to adapt to in the future. We form a hypothesis about cost and likelihood of changes to various design elements, and we split them into two classes: stable or fluid. We expect that the stable elements are unlikely enough to change over time that as an economics question we're better off assuming they won't, while the fluid elements we draw the opposite conclusion. Sometimes designers make these hypothesis explicitly, while others make them implicitly. Different designers can look at the same problem and draw different hypotheses about change, as predicting future requirements is not an exact science. Once we write code based on our hypothesis, we often say that the fluid elements are implementation details, while the stable elements are part of the design contract or interface.

Here's my definition of "loose coupling". Concrete integrated elements are "loosely coupled" with respect to a hypothesis about the risks of change, when the stable elements under the hypothesis are relied on by the interface design contracts, so that the hypothesized changeable elements are expressed only in the implementation details. We typically introduce tight coupling of stable elements purposefully so as to tolerate specific kinds of fluidity among the implementation details. The notion that tight coupling is always bad, is nonsense. Tight coupling to a few things that won't change is generally good.

To illustrate our definitions, let's consider an example. What does coding to interfaces in Java achieve? We introduce an interface so that we can switch out the implementation behavior. We are relying on the methods of the interface and their arguments and return types not changing. If we expect to actually have multiple implementations, this is clearly a good idea. If we never get a second implementation, we just engaged in over engineering, as we spent time creating two artifacts (the interface and it's lone implementation) for a benefit that never materialized.

Consider another example: when we use a SOAP web service interface, we couple to the HTTP protocal and XML standards, the SOAP and WSDL standards and schemas, as well as a homegrown XML Schema for our domain, and the operations and faults defined in the WSDL. In return, for all this tight coupling, we can remove any dependence on any platform or language specific constructs, let alone any specific implementation classes. It's usually a pretty good bet that things like HTTP, XML, SOAP, and WSDL change very little over time, though I look forward to WSDL 2.0. It's predecessor was a little over-engineered, offering too much flexibility at the expense of complexity.

Every time we create a solution, we gamble. Over time, our change hypothesis is repeatedly tested as our code is maintained and implements new requirements. We can compared, with the benefit of hindsight, the kinds of changes we've actually performed with how we predicted. There are four possibilities...

  • predicted change, observed change. Good.
  • predicted change, observed stable. This is the "over-engineering" mistake
  • predicted stable, observed stable. Good.
  • predicted stable, observed change. This is the "tight coupling" mistake.
There are costs associated with each mistake, and when you place your bets you have to weigh the likelihood and the expense of the above possibilities. The cost of having to make changes across tightly coupled elements are well known. The change is invasive, it may take a lot of work to determine everything in the dependency chain, it's easy to miss dependencies, it's harder to assure quality, and deployment are harder, etc... . On the other hand, the costs of over-engineering are bad too: code bloat, complexity, slower development, etc... .

Let's examine ordinary class encapsulation using the approach of this article. Encapsulation is a loose coupling technique applied to class design in an object oriented language. Classes define a public contract to their collaborators via their publicly declared methods. Regardless of whether the class implements a formal interface or is directly called by client code, the method arguments and return types will be depended upon. In fact, using an interface INCREASES the coupling to these, as the interface itself, all of it's implementations, and any client who called one of these methods (which is a larger set because of the abstraction) all must be modified if the method signature changes. We should weigh the odds and impacts and choose to expose methods with arguments and return types where your hypothesis is they are stable. So if we expect to always have Customers who have names that are Strings, by all means have customer.getName() return a String. On the other hand, if this might change, introduce a CustomerName object and/or interface to encapsulate the implementation details of names and expose this rather than String. Is this approach always better? No, it depends on your assessment of the future, and you simply can't make universally sweeping statements that one is better than the other.

As I mentioned, different designers can look at the same problem and assess the risks differently. There are two styles that seem to emerge, and which camp you are in seems to depend on how you weigh the pain of complexity against the pain of refactoring. Some people will not introduce loose coupling until it's clear there is a need for changes to implementation details. These people say things like "the simplest thing that works" and "you aren't going to need it". Others take their best guess based on the available knowledge and their experience and place their bets, sometimes introducing abstractions early. I liken these to the different styles of poker player: some people play tight and some play loose. Neither is "correct" in any objective sense. We've all seen bad examples of taking either too far: the guy who uses several design patterns to avoid relying on the fact that customer.name is a String, or the guy who simply refuses to code to interfaces and has methods that return HashMap instead of Map and so on. Either extreme can be bad. Hopefully now that we understand what loose coupling really is, the reader won't make either mistake.

Technorati Tags:

Posted by spout at 1:03 AM in stuff about java

Monday, 18 February 2008

Hibernate Interceptor Gotchas

I'm trying to implement a Hibernate Interceptor to track user edits to an entity. I call this an EditInterceptor and it is similar to the AuditInterceptor that many people have described. I found implementing a Hibernate Interceptor in practice to have many "gotchas". These include:

Problem 1: Doing work in onSave() you discover the database id may not have been created yet (as the SQL insert hasn't occurred yet). Similarly, onFlushDirty() and onDelete() occur before the database has actually changed.
Solution: Process items in onFlush() using Interceptor instance collections to pass them from onSave(), onFlushDirty(), and/or onDelete().

Problem 2: You cannot modify objects in the session you are working with while it is flushing.
Solution: Create a second session in postFlush using the same jdbc connection.

Problem 3: When implementing the solution to #2, you discover that session.connection() is deprecated, but that no alternative has been provided yet. Note that the Hibernate team doesn't practice proper use of deprecation here, as pointed out in the comments to HHH-2603
Solution: Use it anyway, and add @SuppressWarnings("deprecation"). Note that cloning a session from the same jdbc connection this way is safe, even if there are problems with using session.connection() to do ad hoc jdbc mischief.

Problem 4: You're using Spring's Hibernate support and realize the Interceptor instance collections from Problem 1 aren't thread safe.
Solution: Wrap them in a thread local. See this example.

Problem 5: Your updates are getting processed multiple times and you realize onFlushDirty is called multiple times, and read the javadocs and discover flush() doesn't always conclude with SQL syncronization to the database and that onFlushDirty() is still called in these cases.
Solution: Use a Set to collect changed entities and be sure to initialize this set in afterTransactionBegin().

Problem 6: You realize that in onFlushDirty, because of mulitple flushes as described above, that previousState and currentState are changing from call to call as you hit different points where hibernate automatically flushes. You need the true original state and the true final state.
Solution: Use a ThreadLocal map that associates an entity with the first previousState seen for it. Clear this map when a transaction starts and after you flush. Clear the updates in preFlush() and as usual process them in postFlush(), but when you calculate the update in onFlushDirty() do it relative to the originalState from the map, instead of previousState, which is only used to seed the map if it doesn't have a value for the entity.

Technorati Tags:

Posted by spout at 11:15 PM in stuff about java

Saturday, 26 January 2008

Pros and Cons of Ant, Maven, Gant

I've been thinking about java build tools again. My projects have always ended up using ant and wondering about Maven. There's certainly some innovative ideas in Maven, but there's also some things that scare me. It's funny that Maven's reliance on "convention over configuration" easily predates the Ruby on Rails fad, but the latter gets all the credit for inventing it. There's a reason for that. Anyway, the new kid on the block is Gant, and the way that it's being used in Grails seems really interesting. Gant is a marriage of groovy with ant, which addresses some of the things that frustrate me about ant. Grails adds usability via the RoR style of simple, standard command line syntax. OK, so here's my pros and cons of Ant, Maven2, and Gant.

First I take a look at the old workhorse...

    Ant
  • Pros
    • Everybody knows it
    • Everybody supports it. Ant tasks exist for everything.
    • Extensible. Writing macros and tasks yourself is easy.
    • Flexible, properties configuration
    • Well documented, even by 3rd party tools
    • Low tech and hackable: no hidden magic or voodoo.
    • Path structures and wildcards are simple, yet powerful
  • Cons
    • Everybody know it, including people who shouldn't touch a build. Ever.
    • No standards - few conventions and idioms. Everybody does it different.
    • Everybody does it different, even from their previous project.
    • XML does not facilitate reuse.
    • Limited expressiveness. I have to use ant-contrib to say "if"!?!?! or for <ac:propertycopy name="username" from="db.${db.server}.username">
    • XML Sprawl. As XML goes, not that verbose, but nothing is by convention

Then it's chief rival, and the more ambitious alternative...

    Maven 2
  • Pros
    • Standardized build lifecycle
    • Drop-in reuse of build tools
    • Dependency management
    • Internal repositories facilitate enterprise code sharing
    • Archetype concept allows speed starting project by flavor
  • Cons
    • Hierarchical projects clash with Eclipse (Bug 35973 is 3rd overall with 144 votes today.)
    • Extending isn't simple. mojo, schmojo.
    • Many mundane tasks are truly cumbersome.
    • Archetypes are a great idea ruined by horrible syntax. This is why grails doesn't use Maven.
    • Brittle builds. Some say broken by design. I attended a talk once by a maven project guy. His demo didn't work.
    • Repository metadata quality. This is Matt Raible's #1 Complaint. Maintaining transitive dependencies is hard and brittle.
    • Verbose XML syntax in POMs
    • Plugin avialability lags behind Ant
    • Endless downloading of jars. Go to lunch while maven "downloads the internet".
Finally, the newcomer with respect for its elders...
    Gant, Groovy, and/or Grails
  • Pros
    • Ultra-expressiveness of groovy. No more wrestling to do mundane things
    • No more programming in XML.
    • Smooth adoption path: first use ant's groovy task, then AntBuilder in groovy, then Gant, then wrap in a grail-like runner and scaffolding
    • Grails scaffolding is simple, powerful, and immediately useful.
    • Leverage the ubiquity of 3rd party ant tasks. Steal the best part of Rails but backed by ant's mountain of 3rd party tasks
    • Build logic expressed in groovy classes should facilitate reuse
  • Cons
    • Very young technology
    • Groovy is just starting to penetrate the masses. Gant still largely unknown.
    • Ok, I admit the only grails-like runner is Grails for now
    • Documentation is poor. Really poor.
    • Tooling is weak. IDE's don't support Gant or Grails style lauchers
    • No standard build lifecycle if you use ant+groovy or gant without grails
Posted by spout at 2:11 AM in stuff about java

Sunday, 28 October 2007

Reflections on the Colorado Software Summit 2007

I just returned from my third visit to the Colorado Software Summit. 2007 was another great year. This conference is unlike any other: it's just a bunch of developers talking shop. There are other conferences that try to do this, but this one seems to have the best speaker quality by far. I always have a strange feeling when I come back from this conference: it's sort of humbling to in an intimate setting with so many heavy hitters, yet it's sort of emboldening to have so much knowledge poured into your head in one week.

The opening keynote was a "big picture" talk by John Soyring of IBM. I really don't think I can summarize it without writing a whole blog on it other than to say: there are big social forces that require changes to our computing and programming models. The main keynote was given by Simon Phipps of Sun. He's the guy that lead the effort to GPL java, so he's on my "you rock" list. His main point: open source is going beyond main stream to the dominant paradigm. Like it or not, this means legal challenges. Patents and trademark issues matter now and we'd better learn better ways to deal with them.

A big topic this year was REST. I went to three talks on this, which reminds me that I need to finish my blog series on this. It seems that several people believe that REST is or will be the basis of "Web Services 2.0" (as Scott Davis put it). I was really hoping to understand the implications of REST's Uniform Interface better, and I certainly made progress, but I'm still struggling with translating the technical differences between it and than the SOAP approach (which I think I fully understand) into useful advice on what the architectural pros and cons are. Since I'm on record in this blog as saying that service contracts are the big problem that has to be solved for REST to take first chair from SOAP inside the enterprise, I was keen to here talk of these solutions. Most speakers acknowledged that there is more interest in this lately and talked about WSDL 2.0 or WADL. I also got a new idea that I need to consider more deeply: using ATOM for data and embed schema information within it. This is sort of a half-contract: it's uniform behavior on custom objects. I kind of like the idea of a "standard contract" on behavior.

Dan Pritchett, aka "the eBay guy" gave several talks. His talks all concerned challenges that eBay faced as it tried to scale. It's interesting to know that eBay runs on Java and Oracle, with the Java using Tomcat running servlets. eBay's search is comparable in magnitude to Google's (they may even answer more searches). Their search infrastructure is really interesting: they message their data in a "rows and columns" grid with data partitioning and replication, and the replication crosses data centers. They use different indexes for different use cases. Changes are messaged to each node and applied locally by a custom search engine indexer. Dan said they had to go to this model over the centralized index building because the latency and bandwidth involved in pushing index out with all the updates they do was a killer.

I consider mastery of a subject to mean knowing when to sacrifice the sacred cows, and Dan's discussions on ACID vs BASE transactions really impressed me. Since we were all little kids, we've been told that the quintessential example of two-phase commit (e.g. using XA) is transferring money from one account to another in a different database. eBay basically rejected this as unworkable at scale and came up with a rigorous way to meet their needs without it.

I went to a couple talks on messaging technologies. For JMS, ActiveMQ really seems like a no brainer for best-of-breed. It has beautiful Spring integration, features galore including many for HA environments, and lots of flexibility. I just wish I could get one of the STOMP clients to work from python. I still have a couple more to try. I was also impressed by AMQP, which will likely bring us platform independent fully featured messaging. I hope the JMS vendors take note and play ball with it. Gregor Hohpe gave a great look at some coding patterns for event driven programming. He has this way of making you feel like it's obviously dumb that we aren't all using messaging and event driven architectures as the norm.

Progress in the XML technologies is slow, but steady, and a couple sessions hit on this. XQuery is looking quite useful as a way to turn XPath 2.0 into a query language. XSLT 2.0 also harnesses XPath 2.0 and may be a little more grokable. I think I have had to restudy XSLT 1.0 at least five times as it just doesn't "stick" in my brain due to it's unnatural programming model. I'm very optimistic that XSLT 2.0 improves this. Noel Bergman gave a really good overview of the state of SOAP standards and the progress of the WS-I interoperability efforts. He also gave one of the talks on REST, which is probably not a coincidence.

In the "that's just cool" category: both grails and google gears look like good technologies to learn more about. One thing that grails uses that I'm really enamored with is gant. I've been dabbling with mixing in groovy to our build at work and gant takes this one step farther and turns it upside down: you mix in ant ot your groovy build scripts. I've tried twice to drink the Maven kool-aid (but couldn't swallow it), but now I think I'm going interested in with the other direction. Gears is most often viewed as an offline client tool, but I see it as having more impact as rich browser side caching.

Matt Raible gave his updated talk comparing web frameworks. He had some criteria for when to use different classes of frameworks and based on those, I think the project I'm on now at work chose well to go with GWT. Matt made two really useful observations: First, with the rise of high quality javascript libraries (e.g. Ext, YUI, Scriptaculous) it becomes easier to switch web frameworks while keeping view layer skills (and look and feel) intact. Second, your team will get a bigger productivity increase by shutting off email, canceling meetings, and using better computing resources than it will by changing to the next great web framework of the day.

Some of the other cool topics I learned a little more about: Eclipse plugin writing and grid computing. It looks like it's easier to develop an eclipse plugin than it is to think of something that needs an Eclipse plugin.

I'm also already sold that groovy is important, but I picked up some power user examples of groovy. Eric Schreiner did an awesome example of the groovy XML builder where he took a map of item/value pairs and produced an SVG chart in a rediculously small amount of code.

As always, I love this conference as a way to "scan the horizon" for frameworks, toolkits, and solutions that I hadn't heard of before or need to "bump up" my interest level on. Here's my list of "cool things to check out":

  • Apache Mina, a high performance and high scalability network applications framework
  • Apache Camel, a rule based routing and mediation engine. Sort of "EIP in a box".
  • Esper, an event stream processing tool in the Complex Event Processing category.
  • Gridgain open source grid toolkit with a cool example on distributed unit testing
  • Some AMQP implementations: QPID (in java) and RabbitMQ in Erlang
  • EclpseLink: Hibernate may not be the best JPA implementation
  • eXist, an open source native XML database, with XQuery support.
  • GANT the groovy/ant build system, as seen in Grails like RAILS but based on java/spring/hibernate
  • YSlow a firebug plugin that analyses web pages for performance best practices

Technorati Tags:

Posted by spout at 1:24 AM in stuff about java

Sunday, 23 September 2007

Rails, the 15 minutes is Almost Up. Meet Erlang.

I just bought the latest book on Erlang from the pragmatic progammers. If you haven't heard, Erlang is a functional programming language that has some unique architectural constraints that make it work really well with parallelism and concurrency. Erlang is "hot". This post isn't about Erlang, other than to note that it's what concludes the hype phase that has made Ruby on Rails the darling of fanboys everywhere and an annoyance to the rest of us. This means Ruby and Rails are going to have to stop riding on the wave of excitement by being the latest new thing and are going to have to start impressing people who have already heard about it, tried it, and unlike the fanboys, thought "nya -- needs some work, I'll check back in a few years".

You gets a lot of attention when you mouth off the way the rails zealots have. You get a lot of attention for a while, that is, until then everybody gets tired of you, exposes your flaws, and waits to see how you do fixing them in a climate of criticism. One of the reasons I still like and use java, despite its problems, verbosity, and all that, is that when valid criticisms are leveled against java, the people in the java community don't make excuses, they slowly quietly address the problems. That's a sign of maturity, and Ruby and Rails need to get it or they aren't going to be talked about in five years.

In terms of the Gartner Hype Cycle, Ruby and Rails are nearing the end of the "Peak of Inflated Expectations" and are moving into the "Trough of Disillusionment". For evidence, here's an article by a PHP guy who switched back. That is NOT supposed to happen.

My experience with Ruby is that I read the pick-axe book four or five years ago, before Rails, played with it, liked it, and added a few other books too. I liked ruby's syntax - very efficient for the original writer. I had my doubts about using it in team settings with code maintained over years. I've used Ruby to solve production problems in business settings on several occasions. I never considered adopting Ruby as my "main" language, for reasons I'll expound on below.

Then Rails appeared. Frankly, Rails ruined my enjoyment of Ruby because it attracted so many fanboys and zealots. The folks were making outrageous and ridiculous claims and were so arrogant about how Ruby would be the Java killer. These folks jumped the shark this week, with the posting of Top 10 Reasons Why Java Sucks Ass. Thank you Obie, for being so absurd that no one can deny how absurd the hype around Rails has been.

Now that the industry has played with Ruby and Rails seriously, the problems of Ruby and Rails have become well known. They are:

  • No high quality app server
  • No language specification.
  • Custom runtime VM that isn't supported by any well resourced organization
  • Open source is not a substitute for open standards at the language or runtime engine level.
  • You can quickly write code than nobody can understand, and several years later, people have done exactly that
  • Duck typing doesn't save code, as it requires more unit tests or occasionally blows up on you
  • Mixins aren't so great: A class's state and behavior specification shouldn't depend on its runtime history. I shouldn't need unit tests to verify my class can do what I think it's supposed to do - the unit tests waste more time than I save. Java's new static imports are a much better solution.
  • Total lack of high quality enterprise features: transaction support is weak, SOAP support is weak, messaging is weak, caching solutions are weak, directory integration is weak, clustering is weak, multithreading is weak, etc...
  • What do I do in the real world where my database already exists with 8 years of data in it and I can't design my schema to match the Rails opinions of what's best?
  • Dynamic typing and Mixins make it nearly impossible to have tool assisted refactoring and good code completion. They are appropriate for small tasks with a low reuse quotient for 3rd party code (aka non-enterprise development).
  • Opinionated software is great, if you are a follower-the-leader type who doesn't want to think about what's really best to solve your problem.
  • Overuse of DSL's and embedding DSL's in regular code basically assure difficulty in maintenance. Your DSL's aren't as obvoius as you think. The reason everybody hates XML in java is not because it's XML (they don't complain about XHTML or RSS do they?) it's because they are really DSL's, but at least with editor support.
  • Ruby is unbelievably slow. Slow. Slow. Slow. Don't say it doesn't matter because the database is slower, because it does matter. Ruby is like 6-7 times slower than Java. 2-3 times slower than Python and Perl.
  • Reliability and scalability are crummy
The funniest thing about the above list is that the Ruby app servers are so bad that what's going to end up happening is that the Java app servers will bolt on JRuby support and Rails will simply be absorbed into the borg that is Java. If you run Glassfish, Rails is just another java library! That's really, really funny. Nya-Nya to the "java sucks" fanboys! Once they go away, I might actually take up Ruby again -- if the Ruby community shows some interest in solving some of the problems above. Not all of them -- just show me you can listen.

It turns out that it was easier for Java to bolt on the few innovations that Ruby offered than for Ruby to absorb the many innovations that Java has offered over the years. I think the end result of Ruby is that it killed perl, and forced PHP developers to improve their sophistication (see the article from the guy who switched back to PHP). Unfortunately, it stunted the growth of enterprise language solutions in Python. Python is a lot more maintainable than Ruby, by the way. Ruby's effect on Java has been positive. The concepts of reasonable conventions are being used more. Groovy is looking good (better than Ruby except for being even slower). Most of all, Ruby has forced Java framework makers to think about simplicity, and they have. Ruby is helping make REST more mainstream. REST has a fanboy problem too, but with a lot of work could become a viable alternative to SOA. The final benefit of Ruby is that JDK 7 will finally bring closures to Java.

Speaking of closures... That's why I'm reading a book on Erlang. Ruby touts closures as their biggest strength, but if you buy into that, you should be using functional programming languages. Erlang (and Haskell and all the FP languages) are better for the purity of their closures than Ruby. Erlang gets other things right that Ruby struggles with. Ruby threading is a mess. Erlang gets this deeply and emphatically right (even Java should take note). Unlike Ruby, which falters as it tries to move up to enterprise settings, Erlang as been used for 10 years in carrier grade telecommunications applications with many 9's of reliability. Erlang is Rock solid. As in: bet your company on the fact that your apps won't be down EVER.

Do I think Erlang will take over? No. People are starting to expose it's flaws too. But this isn't as fun as doing so for Ruby, because it's origins in telecom make it immune to false euphoria. But, grid computing and multi-core processing are moving IT towards Erlang's strength. Erlang's unique insistence on non-reassignable variables allow it to deliver fault tolerance, concurrency, and parallelism that give it something that will not be easy to bolt on to Java. While functional programming can be added to Java. Though Scala is looking really interesting at bring FP to the JVM and it's performance doesn't disappoint like Ruby/Groovy, Erlang's inherent concurrency cannot be casually added the way many of the Rails innovations could be, and this means Erlang will have a suite spot that cannot be assimilated into the borg.

But this article is not really about Erlang. Erlang is here as a foil, and for it's cultural impact: the biggest feature that Erlang offers at this moment is that it will bring to a close the Rails 15 minutes of fame. Every time some Rails fanboy starts peddling their hype, the approved thing to do is to respond with Erlang. There is nothing sweeter than dropping the credible innuendo that hype is transient and fleeting and is almost over.

And because Erlang is old school telecom stuff, it will come without the fanboy culture. There something really refreshing about the the fact that it's a telecom industry's solution. After Ruby on Rails, it's hip and trendy to be stodgy and uncool, and Erlang fits the bill. Unsexy is sexy. God bless Erlang.

Technorati Tags:

Posted by spout at 11:29 AM in stuff about java

Tuesday, 14 August 2007

Excluding Unfixables from Eclipse Problem View

I find myself using Eclipse for most of my development now. I still bounce back and forth to a text editor (I love jEdit) for writing xml and an interactive scripting language environment, but for java projects the Eclipse tool stack is really valueable.

The problem view in particular is extremely useful, it will show you errors and warnings throughout the project, and with one click take you right to the line where the problem is. I try very hard to refer to this a lot and all errors and all warnings that it surfaces. Warnings is a little hard, and sometimes this means doing things like putting in @SuppressWarnings("unchecked") when mixing generics and pre-generics code. I also clean up my imports (CTRL-O) a lot more. The reason I'm so aggressive with these is that if I keep the list short then new things that pop onto it are much more visible, which helps me prevent them from becoming bigger problems.

One thing that makes this difficult is generated code, or imported 3rd party files. For a long time, I couldn't figure out how to exclude files or directories from the scope of problem detection and validation. It turns out this is extremely easy and can be refined all the way down to the file level.

You do this by using working sets. The trick is to define a similar working set for problem detection scope to the one you typically use under "Select Working Set". Do this via Window->Working Sets->Edit, or any other way to access working sets. You will leave most things from your selected working set in the problem detection working set, except for the few things you want to exclude. Then in the problem view, click "configure the filters to be applied to this view", and then click the select button under the "on working set:" radio button. You can then change to your problem detection scope working set and voila, unfixable things can be excluded by keeping them out of the working set.

Technorati Tags:

Posted by spout at 1:04 PM in stuff about java

Sunday, 5 August 2007

Java Timezone Wrong on Fedora

How's this for annoying:
bash$ groovy -e "println new java.util.Date()"
Mon Aug 06 01:40:33 EDT 2007

bash$ date
Mon Aug  6 00:40:35 CDT 2007

bash$ /usr/sbin/zdump /etc/localtime
/etc/localtime  Mon Aug  6 00:41:45 2007 CDT

bash$ cat /etc/timezone
America/Chicago
This is on Fedora. Java seems to have decided I'm on the east coast, and stubbornly refuses to look at any of the many sources where it could determine that I'm in the central timezone.

To save you some trouble, here's the solution:

bash$ export TZ="US/Central"
bash$ groovy -e "println new java.util.Date()"
Mon Aug 06 00:49:02 CDT 2007
To make this automatic, I added the export TZ line to /etc/profile.d/java.sh , which is where I set my JAVA_HOME, ANT_HOME, GROOVY_HOME and so on.

Technorati Tags:

Posted by spout at 7:48 PM in stuff about java

Monday, 30 July 2007

mod_proxy_ajp: Simpler than mod_jk

I happened to look in my /etc/httpd/conf/conf.d directory, and there by default is a file proxy_ajp.conf . Hmmm, what is this? Well it appears to be a simpler way of mapping a piece of the apache URL space onto tomcat's AJP connector. Instead of the previous posting, I reconfigured apache using proxy_ajp.conf like so:

LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
ProxyPass /blog/ ajp://localhost:8009/blojsom/blog/spout/

<VirtualHost blog.bwtaylor.com:80>
    ProxyPass /blojsom ajp://localhost:8009/blojsom
    ProxyPass / ajp://localhost:8009/blojsom/blog/spout/  
</VirtualHost>
I also went in to blojsom and changed the url properties accordingly. Note that stuff like CSS will be found under /blojsom, but the main blog can be hit directly at blog.bwtaylor.com . Or bwtaylor.com/blog . 

 I still think mod_jk is "correct" in a few circumstances where it's fine grained controls might help. Under load, mod_jk is capable of just sending the servlets and JSP to tomcat, while serving the static content itself. However, for something like my blog, letting tomcat handle static doesn't create any problems. The above is pretty darn simple and very easy to understand, so I'm going with that.

Technorati Tags:

Posted by spout at 9:35 PM in stuff about java

Getting mod_jk to work

This blog is now accessible at http://blog.bwtaylor.com . To make this work I did three things:

  1. I added blog.bwtaylor.com to my DNS
  2. I set up mod_jk and configured it to route the virtual host blog.bwtaylor.com to the AJP1.3 connector on port 8009
  3. I added a redirect in index.html at higher levels to go to the blogsom/blog/spout context path

These three steps are all you have to do to have simple apache tomcat integration so that tomcat access that is normally on port 8080 is added to the regular apache URL namespaces. 

The mod_jk setup was pretty easy. After downloading the appropriate mod_jk binary from a mirror like this one and symlinking it to the name mod_jk.so in the apache modules directory, I added this to /etc/httpd/conf/httpd.conf


 LoadModule jk_module modules/mod_jk.so 

Then I created a workers.properties file under /etc/httpd/conf like so:
# List workers
worker.list=tomcatWorker
# Define wrkr
worker.tomcatWorker.port=8009
worker.tomcatWorker.host=localhost
worker.tomcatWorker.type=ajp13
worker.tomcatWorker.cachesize=10
worker.tomcatWorker.cache_timeout=600
worker.tomcatWorker.socket_timeout=300

and finally I finished off the connection by adding mod_jk.conf under /etc/httpd/conf.d for the virtual hosting rules:
JkWorkersFile /etc/httpd/conf/workers.properties

JkShmFile     /var/log/httpd/mod_jk.shm
JkLogFile     /var/log/httpd/mod_jk.log
JkLogLevel    info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

NameVirtualHost *:80
<VirtualHost blog.bwtaylor.com:80>
    DocumentRoot /opt/tomcat/webapps
    ErrorLog /var/log/httpd/mod_jk-error.log
    CustomLog /var/log/httpd/mod_jk-access.log common
    <LocationMatch ".*WEB-INF.*">
        AllowOverride None
        deny from all
    </LocationMatch>
    JkMount /* tomcatWorker
</VirtualHost>

 


Technorati Tags:

Posted by spout at 8:07 PM in stuff about java

Checking out JPackage

It's been a while since the last time I looked at JPackage, so I thought I look back. JPackage provides rpms of common java libraries and frameworks for linux.

I was hoping that since Java has gone GPL (98%) anyway, that JPackage would have an rpm for it. Nope. They don't even have java-1.6 at all yet. And that's my general comment on most of the things they do have... they're old. Spring? no 2.0. Struts? no 2.0. JBoss? 4.0.3 is their latest. Tomcat? no 6.0. Generally, I don't see the point -- I've already got the old packages, I generally want to install newer things. So, sorry, JPackage just isn't helping me.

Technorati Tags:

Posted by spout at 5:05 PM in stuff about java