Matt RaibleMatt Raible is a writer with a passion for software. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.
You searched this site for "young russian teenboy model pre teen". 788 entries found.

You can also try this same search on Google.

Edit Screens with JSF

I'm working with JSF this morning and I'm finding one thing particularly annoying. I'm working on a simple master/detail screen and I'm tweaking the detail screen to fit my needs. It's just a <form> with some form elements. I change something, run "ant deploy-web" and hit "refresh" to see my updated page. Since everything in JSF is a post, I get prompted to re-submit the form. Fine, I agree - then I'm returned to the list screen. Argggh - why can't I just view the form again?! This might just be a MyFaces nuance, I'm not sure. Anyone know of a workaround?

Wanna see the bug/feature in action? Go to http://demo.raibledesigns.com/equinox-jsf/userList.html, click on a row - and after the edit screen displays, hit refresh on your browser. In an ideal world, you'd see the form again, but nope - you get the list instead.

Posted in Java at Nov 28 2004, 10:02:25 AM MST 9 Comments

AppFuse Tapestry/JSF Status

There's 3 phases of adding a new web framework to AppFuse. The first phase is integration and configuration. This is the fun part and involves adding JARs and configuring everything so the framework actually works. At the end of this phase, I'm usually pretty enthusiastic about my progress and think I can finish the whole project in a few more days. Then comes the "features" phase, when I start coding AppFuse features with the framework. This part always takes wwaaaaaaayyyy longer than I anticipate. This is the part where I realise previously done things (from other framework implementations) won't work and I have a long road ahead of me. For instance, with Tapestry and JSF, I have to figure out how to do the following: Country drop-down based on locale (currently a JSP tag, so should work with JSF), multi-select checkbox, and placing an asterisk next to required fields.

The asterisk isn't too hard if you do it the "WebWork way" - where you simply specify required="true" on JSP Tag. However, I'd prefer to have it read from the validation engine, so this will probably take some digging on how to do it with JSF/Tapestry. For the country drop-down, I'll probably have to create a Tapestry Component. I believe both frameworks have a multi-select checkbox component. After working with Tapestry's contrib:Table component for a few hours, I miss the Display Tag. The contrib:Table works, but it's a LOT more difficult to configure than the Display Tag. It also blows up if you click the column headings too many times. Also, it doesn't have any exporting features like the Display Tag. Sure, it might not need them, but a lot of folks have come to rely on these and it's a handy feature. Furthermore, another unfortunate thing I found in Tapestry this morning is it doesn't seem to read the locale from the request. So if you change your browser's language, it won't switch the language. You actually have to logout and kill the session to switch the locale. Bummer.

My main problem with the 2nd phase of the project is choosing whether to "do it right" or "get it done". I often start out just trying to get shit done, but end up being a perfectionist and trying to do it right. This phase took a couple of weeks to get through with WebWork. Ugh - I'd rather just get this stuff done, but I don't think it's gonna happen. I think I'll be working on the "features" phase for quite some time. Oh well, at least I'll learn the ins and outs of each framework.

The final "finishing up" phase is one of the best. It's when everything works and I write the installation scripts and tutorials. This is slightly painful b/c there's nothing new to discover, but it's also nice because there's nothing new to learn or get tripped up on.

AppFuse 1.7 estimated release date? I was hoping for the next couple of weeks, but I'd better stick with the end of the year. I'm sure there's going to be a fair amount of banging my head against the wall in the next few weeks.

Posted in Java at Nov 25 2004, 08:52:13 AM MST 1 Comment

The AppFuse Generator

I found the AppFuse Generator project in my comments last night. Richard So seems to have created a nice code-generation tool for AppFuse. It looks like it can create/modify all the files you need to CRUD a database table. I took a brief look at the code and it's all based on Velocity templates, so you should be able to easily tweak things.

This tool does seem to generate the DAOs/Managers - which can lead to more code to maintain. It would be nice if it could be modified to be similar to AppGen where there's a "detailed" version (that generates everything) and a "default" version (which only generates the web tier classes). The default version could use the generic "dao" and "manager" beans. I wonder if this tool supports running/installing the same table more than once? This currently doesn't work too well with AppGen, but shouldn't be too hard to fix.

In reality, I'm pumped that Richard has created this, as well as a project to back it up. I especially like that he's going to try and create an Eclipse Plug-in as part of this project. Nice work Richard!

Posted in Java at Nov 22 2004, 04:39:35 AM MST 8 Comments

Facets of Ruby by Dave Thomas

You can learn Ruby in 4 hours. This talks isn't to learn Ruby, but rather to show facets of Ruby. Ruby has made programming fun again for Dave. It's also made him more productive.

Languages and tools make a difference

Ruby has variables, methods, but no types in methods. When Dave first started using Ruby, he had a strong typing background - and was terrified of Ruby's un-typed feature. He first thought Ruby was a toy language for hobbyists because of the lack of typing. Now, many years later, he really likes the lack of typing and hardly even has bugs relating to typing. He notes that with Java we store most of our data in Collections - and those are all Objects - so Java is essentially un-typed as well. How often do you get ClassCastExceptions? The rooms concensus is not not a whole lot. To make up for the lack of typing, Ruby developers tend to write a lot more unit tests.

ActiveRecord - Ruby O/R Mapping Library

Ruby on Rails - not a single line of XML. Uses intelligent defaults and allows you to override them. The following creates a wrapper around the "ranks" table.

class Rank < ActiveRecord::Base
end

The original author of RoR thinks that every database table should be plural, so singular class names map to plural table names. It's even smart enough to change Person to a "people" database table. Apparently it has a bunch of the singular-to-plural mappings for the English language built-in. The key to Rails is clever defaulting - allow you to write a lot less code, but override if you really need to.

ActiveRecord has many lifecyle hooks (17) that you can override. For example, before_save, before_destroy, validate. For example

def before_save
  self.when_added ||= Time.now
end

I wonder if Rails has any support for transactions and specifying propagation behavior on transactions? I asked Dave this question and it sounds like ActiveRecord has a rich support for transactions - and even wraps the "save" method with a transaction by default.

"Ruby is pretty damn good at web applications"

Simple CGI is a common choice. FastCGI and mod_ruby in Apache are other common choices. There are also a number of different web frameworks for Ruby:

  1. Roll-your-own
  2. Templating systems
    1. erb
    2. Amarita
    3. RDoc templates
  3. Iowa - similar to WebObjects
  4. Ruby on Rails

Ruby on Rails - MVC Framework

Contoller - one method per view. Setup context (a.k.a. the model) for views. Views contain "rhtml" - HTML with embedded Ruby. Lots of helper functions. Can access model data (context) setup by Controller. The name of the method in the Controller determines the name of the view file. A "select" method will dispatch to a "select.rhtml" file. The method name to call in a Controller is determined by the URI - for example, /ranks/view calls the "view" method in the RanksController class. Pretty slick! I like the idea of smart defaults - IMO this should be used a lot more in webapps. I'd love to get away from mapping URLs in Struts, Spring and WebWork.

Rails has built-in support for configurable URLs - so you can change query strings to more slash-type URLs. What about things like client-side validation, success messages and sortable/pageable tables? Do those exist in Rails? I asked Dave and he said said they have good support for success messages with a "flash" concept and the post-to-redirect problem is almost non-existant because most controller invocations are redirects. Client-side validation and sortable/pageable tables don't exist in Rails.

Rails has Needles - and IoC framework similar to Pico. However, there's a fair amount of traffic on the mailing list and a lot of Ruby developers think they just don't need IoC. Dave's suggestion is to use Class Injection.

The largest Ruby application is probably Daves - 55,000 lines or code, couple hundred thousand users. There are entire companies who write all all their applications in Ruby. The founder of Rails wrote it so he could write Basecamp - which is only 4500 lines of code.

Good stuff Dave - and definitely a nice overview of Rails. Will I be digging in an using Rails anytime soon? Not this year, I'm going to have some fun with Tapestry and JSF first. Maybe next year.

Posted in NFJS at Nov 12 2004, 06:39:59 PM MST

Design Patterns Revisited: Taking Advantage of Dynamic Reflective Languages by Stuart Halloway

SmartFactory - one factory for all factories. Allows developers to handle failures rather depending on various factories. Unfortunately, you will have to do Casts. Stuart things that Generics should've never been added and instead we should just have no casts. Instead, the compiler should inject the cast implicitly.

Document d = SmartFactory.getInstance();

Java might be a lot more powerful if we could return a different type from constructors - like Class Clusters in Objective-C. You can get a lot of dynamic features in Java using AspectJ. Java Developers have a lot of responsibility when they start using aspects.

Stuarts talk was 3 hours and I only attended the first half. He's a very good speaker and I enjoyed listening to him more a lot. The basic gist of his talk seemed to be that Java should be more dynamic, and using AspectJ, it can be. I thought he was going to recommend we switch languages - so I was surprised to here him recommend AOP. The last example he gave was how to interrupt a FileInputStream so you could test the condition in a unit test. I can see how this could be quite useful for causing network or database failures and seeing how your application behaves.

Posted in NFJS at Nov 12 2004, 06:38:07 PM MST

[DJUG] Web Services and Geronimo

We're finally getting started at 6:25 and we were supposed to start at 5:50. Good ol' projector issues. This time it was a bent pin.

J2EE 1.4 introduced the first web services component type (SE) and augments EJB specification (2.1) to expose SLSBs as a web service endpoint.

Writing J2EE 1.4 web services ("endpoints")

Two J2EE components to implement a web service:

  • JSE (JAX-RPC Service Endpoint). New component, new deployment descriptor. Looks like a servlet, acts like a servlet. Run's in a web container like a servlet. Isn't a servlet.
  • SLSB. Exposed as web service via deployment descriptors.

JSE is easier because it's (mostly) POJO based. EJB might be preferred if you already have EJBs or you need transaction management. However, the SOAP client calling the EJB web service does not participate in the transaction (at least the spec does not define it).

"Mandatory" transaction attribute not allowed in EJB endpoints because SOAP client can't propagate transaction.

JSEs are similar to servlets:

  • Instances run in the web container
  • follow servlet lifecycle
  • Must have a public no-arg constructor
  • Can add servlet filters just like you do normally

Steps to writing a web service JSE:

    1. Write remote interface (the service endpoint interface) - must extend java.rmi.Remote and throw RemoteException
    2. Write implementation class
    3. WSDL Document
    4. Deployment Descriptors (web.xml and web-services.xml)
    5. Create WAR File

J2EE 5 will allow you to turn any POJO into a web service - no interface needed. Apache Axis can be used to generate the WSDL for you with Ant. You map the implementation class as a servlet, with a servlet-mapping and everything. The difference b/w JSE's and servlets is you can only map one JSE to one URL.

Writing web service clients. Client model is defined by the JAX-PRC 1.1 spec. You can write web service clients using three JAX-RPC techniques:

1. Generated Stub - Easiest. Done at development time. JAX-RPC is invisible to your code. Stub classes hide it. Runtime implementation will be tied to a vendors JAR because vendor tool will generate class based on WSDL.

2. Dynamic Proxy - Most Portable. Done at runtime. Your code asks JAX-RPC factory to create stub at runtime that implements SEI (Service Endpoint Interface).

3. Dynamic Invocation Interface (DII) - No Stub Necessary. Useful for tools - e.g. dynamically retrieve WSDL then show user on a GUI what services are available and allow user to select what should be called. Client sets URL, methods to invoke and required parameters.

Future of J2EE web services. JAX-RPC 2.0 (JSR 224) in the works. The goals of JAX-RPC 2.0 are several:

  • Make writing WS simpler by using metadata and annotations.
  • If you write an endpoint interface, your implementation class won't have to implement it.
  • Remove requirement to define a remote object.
  • Better support for document-centric web services.
  • Integration with JAXB.

Tom's presentation was quite good for his situation. There was a *ton* of technical issues and he had to show his presentation on Chris Huston's Powerbook. This meant no demos since he had JBoss 4.0 and everything else setup on his Windows laptop. After flailing about for the last hour - he admits its time to buy a Mac.

Apache Geronimo

1. Apache Software License
2. Uses other BSD-derived, open source projects
3. Initial manifestation as a J2EE 1.4 application server 4. J2EE 1.4 certified (in-progress)

Started a year ago in September. The main motivator for Geronimo was there was no BSD-derived license for an open-source application server. The GPL license requires you to contribute code back if you customize a product. BSD allows you to do anything, you just have to give credit back to the originator. Sounds like the proper license for AppFuse to me.

The heart of Geronimo (the kernel) knows nothing about J2EE. It's designed to do just about anything you want it to do - it's just a configuration away. Jakarta project at Apache makes up a huge portion of ASF projects. Many of these projects are pieces of the J2EE puzzle. However, there wasn't any glue to hold it all together. Geronimo re-uses a *lot* of existing (best of breed) open source projects.

Geronimo still doesn't support Tomcat. The main reason is because 3 of the Jetty committers are part of the Geronimo team. Jetty was the first component every deployed in Geronimo. According to Bruce, someone is working on integrating Tomcat right now. You'd think this would be pretty easy and only take a couple days to do. Maybe I'm wrong.

Geronimo is NOT another lightweight container, web framework, or AOP framework.

It IS designed for long running servers. Its designed to tolerate partial component failures. System oriented services.

Geronimo Kernel - Fundamental Core

  • Small memory consumption ~ 150KB code
  • Component Registration
  • Component Configuration
  • Integrated Repository
  • Lifecycle Control
  • Dependency Manager

Now Bruce is going on about Maven and how it works. ZZZzzzzz. Maven schmaven. He does have a good point though - it works great for building and managing multiple projects and their dependencies. Geronimo has 30 sub projects - yow.

A lot of concepts and architecture in Geronimo is derived from Maven. Hmmm, I wonder if that means it's slow. ;-)

What are GBeans? They're a J2EE managed component (a JMX MBean), which are basically simple objects plus some metadata. Used to bridge JSR-77 lifecycle requirements. GBean wrappers allow just about anything to be plugged into be plugged into Geronimo. Implement the GBeanLifecyle interface: doStart(), doStop(), and doFail().

Bruce is now showing us the DerbySystemGBean that's used to stop and start GBean w/in Geronimo. Bruce has a lot of good things to say about Derby and thinks it's a much better database than both MySQL and PostgreSQL. That's a pretty strong statement, but since he met with Derby's architect last week, I tend to believe him. I'm assuming since I got AppFuse working with DB2 that using it with Derby would be pretty easy too.

Bruce says there's supposed to be a Geronimo release this week. I thought they were supposed to be done with Geronimo by this year's ApacheCon?

Now we're looking at an XML file that's a GBean configuration file. It looks like Spring is going to get some competition for long class names. And if you thought Spring's XML was verbose - Geronimo puts it to shame! I'm not saying this is a bad thing - it's just an observation.

GBean Archive - A JAR file that contains persisted GBean instances, GBean metadata. The Java classes in the GBean can reside in the JAR or be dependencies in a central repository.

GBean Descriptor - dependencies and configuration are defined in XML.

Repository: Structured collection of JARs. Designed to work in conjunction with Maven (pluggable implementation). Every JAR has a unique group and artifact id. Default repository is local file system, others allow auto-download.

Observation: Bruce's presentation is interesting - he seems to be targeting folks that want to dig into Geronimo and customize it. I think most developers just want to use it and would be more interested in seeing a demo of deploying an app on Geronimo, rather than how to integrate Derby or Jetty into the server. If it's so easy to plugin a component, why hasn't Tomcat been integrated? Maybe it's just me, I want to see it run and deploy apps to it - that's about all I want to do. In most cases, I shouldn't need to customize it. It's nice to know that it's an option though.

Basic Configuration Builder: Deployers are J2EE specific (JSR-88). If you have standards-compliant deployment descriptors - your application should deploy on Geronimo. Rather than calling them deployers, Geronimo uses "Builders". The Builders /deployers create configuration objects containing GBeans. Most complex Builder is J2EE deployer. It implements a JSR-88 deployment specification and accepts JARs, WARs, EARs, and RARs. You can also add in a deployment plan in XML. From this, a Geronimo Configuration ARchive (.car) is created. The nice things about these builder is you can do deploy-time optimizations, before the application is started.

Everything above the System Services and Kernel is hot swappable. You can remove the J2EE Configuration and replace it with something else like Pico or Spring. This means that you'll be able to swap out servlet containers w/o shutting down the server. That's pretty damn cool. If the system services and kernel are stable, and no JVM dumps occur - this means that your Geronimo server could be running forever. Sounds awesome.

High-availability (clustering, etc.) has not been built into Geronimo yet. This is primarily because this is not part of the J2EE spec. Developers are focusing on gaining 1.4 compliance, then they'll start looking at the fancy features.

Wow - good presentation Bruce. I feel like I know more about Geronimo than I ever wanted to know.

As I was getting ready to post the above transcript, I noticed that Geronimo 1.0 M3 was released. According to Bruce's presentation, this is the last release before 1.0. Nice work gents.

Posted in DJUG at Nov 11 2004, 12:36:47 AM MST 3 Comments

[ANN] AppFuse 1.6.1 Released

This release is primarily a bug fix release, but it also contains a slick "AppGen" tool for generating full CRUD (with sample data and tests) from a POJO. AppGen essentially automates everything you do in the tutorials. I still encourage users to read through and do the tutorials in order to learn the code that is being generated. This feature basically reduces the amount of files you need to create/alter for CRUD from 16 to 2. Better yet, rather than generating the DAO and Manager (as well as the tests), it just uses generic methods in the base implementations. This eliminates the need (and hopefully desire) to create so many DAOs and Managers. In most cases, you can simply use the "manager" bean in your Actions/Controllers and call its respective methods. Thanks to Hibernate for making generic CRUD possible with only a handful of methods. Now you should be able to simply concentrate on the web-tier and only modify/create backend classes when you need special behavior.

To upgrade your 1.6 based application, I recommend performing the following steps:

This is how I've always done my AppFuse upgrades for Struts-Resume. It takes a couple of hours, but it's a lot easier than me trying to create an upgrade package. ;-)

I'll be talking about AppFuse this weekend at Denver's NFJS Conference. Next Monday I'll be in Vegas at ApacheCon. I've never done two different talks back-to-back before, let alone at two different conferences. Should be fun.

Posted in Java at Nov 09 2004, 11:53:44 PM MST 24 Comments

Comparing Web Frameworks Presentation

Since Kris let the cat out of the bag, I might as well give you the link to my comparing web frameworks presentation (PDF, 280KB). I also created a page on the Equinox site for this presentation and related materials. In addition to the presentation, this page also has links to the various framework implementation demos. Here they are for your convenience:

Kris notes that I would still choose Struts. I think it should be noted that I would only choose it in combination with AppFuse (which generates ActionForms). Same goes for Spring and WebWork. I've added interceptors and convenience methods that simply make developing with these frameworks faster and easier. I would've chosen WebWork for my current project, but I'd like to see better client-side validation. Spring needs better tag libraries.

I think the choice of what framework to use is a very personal thing. I think the "best" framework for one person might be very different for someone else. For me, I typically do short-term projects with clients - get them up and running with an application, and then head off to the next project. It makes sense for me to create applications that use a popular framework like Struts that they can easily find developers to maintain it. However, the one thing I'm starting to find is that as long as I use AppFuse - there's good documentation on how to do things. So I've already written the "how to develop and extend this app" for future developers of a client's application. This will (hopefully) open the door for me to use any web framework that AppFuse supports.

I think WebWork rocks, but it's similar to JSF in that it doesn't come with everything your need. The good news is it's easy to write interceptors, but IMO there's a few that should be part of the framework. After working with Tapestry and JSF, I can see how component-based frameworks will be the wave of the future. I think as you develop more and more components, the code you write becomes less and less. It's funny that this is one of the goals of AppFuse - incorporate a bunch of tips and tricks for various frameworks to make development easier. By adding support for Tapestry and JSF, hopefully AppFuse will someday become a repository of useful components. Documentation is good - code is better.

I'd probably be more enthusiastic about Tapestry and JSF if I knew more about them. I still have a lot to learn. I've bought the books (Tapestry in Action and Core JSF), I just haven't had time to read them. I think after incorporating these frameworks in AppFuse (hopefully this year), I'll get a better feel for them and how they make development faster and more efficient. My major problem with JSF is that it's being written for the tools vendors and not for the developers. Make it easy for everyone, not just folks that want to use their hammer-like IDE to develop webapps. The major problem I have with the JSF Tools is 1) none of them are free and 2) most of them are tied to a proprietary app server.

Posted in Java at Nov 04 2004, 09:50:21 AM MST 22 Comments

Trails - like Rails, but with Tapestry, Spring and Hibernate

I've been thinking about Rails ever since I wrote a post about it on Monday. The main reason is because of Dion's comment:

Matt - You should follow the lead and do a video of setting up a simple app using AppFuse.

This might sounds like a good idea, but if I did it right now in AppFuse's current state, it'd be a disaster. The reason? Because you have to manually create a whole bunch of classes to do CRUD on a database table. Here's a list of new classes needed for adding a new "person" table.

  • model.Person
  • dao.PersonDAOTest
  • dao.PersonDAO
  • dao.hibernate.PersonDAOHibernate
  • service.PersonManagerTest
  • service.PersonManager
  • service.impl.PersonManagerImpl
  • webapp.action.PersonActionTest
  • webapp.action.PersonAction
  • web/pages/personList.jsp
  • web/pages/personForm.jsp

The last two JSPs can be generated, but that's still a buttload of classes (9) just to CRUD (and test!) a database table. Not too mention all the files you need to edit for Spring and i18n.

  • dao/hibernate/applicationContext-hibernate.xml
  • service/applicationContext-service.xml
  • test/web/web-tests.xml
  • web/WEB-INF/classes/ApplicationResources_en.properties
  • web/WEB-INF/menu-config.xml

Result: to CRUD a database table using AppFuse you have to create 11 new files and modify 5 existing files. 16 files. What a beotch, huh? If I made a video of this - it'd be 20 minutes long! While this might make AppFuse look silly, it's really more of a symptom of the patterns we have in J2EE and how we're supposed to architect our apps. 3 tiers, test-driven, loosely-coupled and internationalized. Of course, if I was focused on fast and efficient, I could do this all with 1 JSP and JSTL's SQL tags. Everyone would slap my hand for not following patterns, but I'm willing to bet it'd work just as well and be just as fast. But I digress.

There have been a fair amount of requests (and some patches submitted) to generate and modify all of the files listed above. For the most part, I've frowned upon adding such a feature because I think if folks can run "ant generate -Dmodel=Person" - they'll end up with a whole bunch of code that they know nothing about. Sure there's the tutorials, but folks will quit reading those. Instead, they'll create a whole slew of POJOs (maybe even using Middlegen) and run "ant generate" on all 50 of them. Poof - now they've got 550 new files to maintain. Talk about a maintenance nightmare. Even worse - a support nightmare for me.

Nevertheless, if I wanted to create a cool video for AppFuse, I'd spend a few days writing this code-generation engine. Then I could show how you could create the data, service and web layer (including UI) in a matter of seconds. It'd be cool and folks would dig it. I'm still considering it, but I'm also leary of the resulting support fiasco. Maybe I could just say "use at your own risk". ;-)

A while back, I saw Erik Hatcher suggest a better solution than code-generation. I can't remember what he called it, but it was something like "meta-data dynamic rendering". The idea is that your application reads the metadata of a table (or POJO) and renders the appropriate UI for it. I loved the idea as soon as I heard it. I've always wanted a way to dynamically render the UI rather than writing HTML. Of course, I still want the ability to edit the templates and HTML since I fancy that sort of stuff. I don't like writing HTML for each row in a form, but I do like tweaking the HTML and CSS to look good.

Earlier this week, I saw the concept in action with Rails and its demo. IMO, something like Rails would never fly in Java because it appears to be tightly coupled to the database and only MySQL, PostgreSQL, and SQLite are supported. The Java community always seems to pride itself on database abstraction, partly due to JDBC and its ability to connect to anything that has a JDBC Driver. Ruby will probably catch up someday, but right now it appears to be looking for something like JDBC.

Then along comes Trails, which made me smile earlier today when I first read about it on the tapestry-dev mailing list.

I've been working on a project called Trails that uses Tapestry quite heavily and I thought it time to start soliciting feedback. Trails is a domain driven development framework that uses Tapestry, Spring, and Hibernate. Trails is very much in it's infancy, but the current version is functional and should give people a rough idea where I am heading. It's my first real forray into Tapesty and I have really found Tapestry a joy to work with.

Trails is very much like Rails, except that it doesn't talk directly to a database table. Instead, it talks to your domain objects that you mark up with XDoclet/Hibernate tags. To test it out, I dropped a User.java file into the org.trails.demo package, marked it up with XDoclet and deployed. It didn't work at first because the .hbm.xml files are explicitly listed in Spring's applicationContext.xml. I changed the "sessionFactory" bean to use the following and wammo - success! I could list and CRUD the table that my User object was mapped to.

  <property name="mappingDirectoryLocations">
    <list>
      <value>classpath:</value>
    </list>
  </property>

Trails is very cool, and I'd love to incorporate it into AppFuse or Equinox. Does an LGPL license allow me to do this? The one problem I can see with adding it is that it's specific to Tapestry and Hibernate, which doesn't always suite folks. I think developers might be willing to change because this solution will vastly improve their development productivity, but who knows. I think the best solution would be to offer this option in AppFuse/Equinox, but also offer the current manual and code-generation options. The holy grail would be the ability to plug in iBATIS or JDO instead of Hibernate. In addition, using Struts, Spring, WebWork or JSF instead of Tapestry would have folks clammering to use this stuff.

Mad props to David Heinemeier Hansson and Chris Nelson - you guys are developing awesome software.

Posted in Java at Oct 29 2004, 01:50:30 AM MDT 22 Comments

Fun with Log4J and JBoss

I've had the pleasure of working with JBoss (3.2.5) and an AppFuse-based application for the past week. It was fairly easy to setup thanks to Rick Hightower's instructions. AppFuse uses commons logging (like many of its open-source dependencies), but uses log4j to control what gets printed to where. By default, it changes Hibernate and Spring to use WARN and the application classes to use DEBUG. For most containers, this works great. Drop in the WAR, or package it in an EAR and voila - your logging statements show up in the console. Not so with JBoss. Spring and Hibernate use INFO and I can't get any debug statements to show from my classes.

I shouda known this would be a pain since Rick wrote "Setting up logging is a pain in JBoss. Don't mess with the console log... it misbehaves. Create a file logger and tail it.". Is this the best practice for logging with Log4J in JBoss?

You'd think printing to the console would be easy. This wiki page even makes it look easy: change your log4j.properties to log4j.xml and add a <class-loading> snippet to your jboss-web.xml. Unfortunately, I get this nice error message:

00:21:17,593 WARN  [DeploymentInfo] Only the root deployment can set the loader repository, ingoring
 config=LoaderRepositoryConfig(repositoryName: log4j.config:loader=appfuse.war, repository
ClassName: org.jboss.mx.loading.HeirarchicalLoaderRepository3, configParserClassName: org.jboss.mx.l
oading.HeirarchicalLoaderRepository3ConfigParser, repositoryConfig: java2ParentDelegation=false)

Any ideas are appreciated - it seems wrong that I have to write to file just to tail it so I get the same console behavior I get with other servers.

Posted in Java at Oct 29 2004, 12:12:15 AM MDT 7 Comments