Fork me on GitHub

n. Slang a rough lawless young Kuali developer.
[perhaps variant of Houlihan, Irish surname]
kualiganism n

Blog of an rSmart Java Developer. Full of code examples, solutions, best practices, et al.

Wednesday, December 21, 2011

Kuali Parameterized ValueFinder Implementation


Sometimes it is necessary to dynamically build a values finder based on some outside influence (sometimes another values finder). This is how to create a value finder that uses input from another source. I am going to use an example where we want to give a list of available mileages for a user to select from. We only want to show mileages to the user based on the date their travel arrangements are made during. If we don't limit in this way, the number of available mileages to choose from will be infinite and indistinguishable. What we need is a list of mileages based on a date determined by the trip information already in the form. This is how we do that.


1. Create a JstlFunctions class with static methods

getOptionsList is the only public method in the class.

You can see it returns a List because this will eventually be used with a JSP or JSTL tag file which do not support parameterized types. You can see that parameters are passed in as a Map called params. This is used via the addParametersToFinder method here:

2. Create a JSTL TLD

Now that we have our class and our public method that will create our finder for us, we will need some way to invoke it. The best way to do this is by using the static method through a tag. We can create this tag easily with a TLD.

3. Use it in a JSP

In our JSP, we will need to define a Map to add parameters to. You saw earlier that our getOptionsList method takes a Map with parameters in it.

Then, we need to assign some value to the Map:

Above we have assigned ${perDiemExpense.mileageDate} to the queryDate parameter in our Map! Now we just need our dropdown.

Now you can see where getOptionList is actually used. Now we have a dropdown list of mileage rates based on the date of the mileage since mileage rates can vary by date.

Thursday, December 1, 2011

SEVERE: Error listenerStart


I saw on the rice mailinglist recently someone posted a question where essentially, the application dies before a logger can be initialized. Here is the result:
INFO: Deploying web application archive kr-dev.war
log4j:WARN No appenders could be found for logger (org.kuali.rice.core.web.listener.KualiInitializeListener).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See for more info.
Dec 1, 2011 1:35:19 PM org.apache.catalina.core.StandardContext start
SEVERE: Error listenerStart
Dec 1, 2011 1:35:19 PM org.apache.catalina.core.StandardContext start
SEVERE: Context [/kr-dev] startup failed due to previous errors

What has happened here is the listener failed to start. The listener is what starts up the application (in this case, Rice). If Rice does not start, there is no logger to tell you what is wrong. Thus, you get no error. Usually, what causes this is a dependency is not included in tomcat.

So far, I have not seen a case where the problem is caused by anything but a missing library. It is usually the database driver, because that is the only thing not included in the rice war by default. It can possibly be something else though. I have seen KFS not start because of a missing log4j file. Since KFS actually requires the application to deploy additional libraries to the application server before startup, it is the only exceptional case.


Of course, the solution is to make sure your database driver is in the tomcat/lib folder, right? What if that doesn't do the job? What if it's another library? Read on.


Sometimes you need to figure out what library is missing. This is almost never the case. Nearly always it is the database driver that is missing. Almost, right? If this happens and the database driver is loading correctly, then you need to figure out what the problem is. This means consulting the tomcat logger. I am going to assume that you have installed the rice war file in your tomcat installation. The war file is now unpacked and there's a webapp directory somewhere. Within the WEB-INF/classes path of that webapp directory, you can create a with the following contents.
org.apache.catalina.core.ContainerBase.[Catalina].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].handlers = java.util.logging.ConsoleHandler
Why? The reason is that rice uses commons-logging and log4j while tomcat uses java.util.logging. Essentially, separate things. Also, since Kuali did not start, it did not start the logging configuration. What we can do is add a logging configuration that tomcat will pick up and use when it tries to start Rice. That is essentially what we are doing here.

Now try to restart the server. You should see some kind of NoClassDefFoundError somewhere explaining what library you are missing.