BibleGateway.com Verse Of The Day

Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Wednesday, May 23, 2012

OSB Table Poller Issue Setting Status

After building quite a few Oracle Service Bus table pollers, my last project should have been something I could do with my eyes closed. Poll a table looking for certain 'actions', and call a few web services to make that 'action' happen in another enterprise system.

A very simple service flow:
1. JCA table poller adapter, configured for logical delete (change an indicator from one value to another), set up for distributed polling so it will work in a clustered environment. Basically look for records with status of N, switch it to P.
2. Wrap that in a proxy that simply routes to one of several other proxies based on the 'action'. (local transport)
3. Those other proxies call web services based on the values in the original message. On success, the response pipeline will set the status to C. If any of those services fails or returns an error, an error is raised to the proxy's error handler, which sets to the status to E.

That's it, dead simple. If there are no errors, everything works great, record goes to C, we're all good. 

However, if an error is raised on the request pipeline, the status doesn't get changed to E. Using the same service callout that works for C, does not work for E.

I watch my WebLogic logs and my TOAD query at the same time and notice some things:
1. For a success, I see in TOAD the record stays in N status until all the web services have been called. Once the final service returns, it immediately goes to P then C. All good.
2. If an error is raised along the way, or even if I manually try to set the status anywhere on the request pipeline, that call hangs until the transaction timeout occurs, then that update to E fails, as well as the update to P. End result, the record stays in N and gets pulled again, and again, and....

(As an extra red herring to keep me busy, I get a log full of XA transaction type errors, so I spend way too much time working with the DBA trying to set up XA permissions.)

So it seems that all along the request pipeline, the OSB has that row locked for update, but hasn't done the update to P yet. If I try to set it in my flow, the two updates deadlock until the XA timeout occurs. However, when setting it on the response pipeline, the update to P has already happened, so it works there.

I could have rewritten all my proxies to only change the status on the response pipeline, but that would have been a painful rewrite of the flows. An easier solution was to have the poller proxy immediately drop the message on a JMS queue, and then have a queue listener proxy pick those up and route them. Doing this, I see the record go to P immediately, no matter what, and then success or failure, my status changes without any timeouts or XA errors.

Friday, December 03, 2010

WebLogic Annotation For MDB WorkManager

If you are like me, you have been searching the web for 2 hours looking for a way to tie your WebLogic 10g message-driven bean to a WLS WorkManager using the nice EJB3 annotations. But since you aren't me, let me save you some time.

It ain't there. Not gonna do it. Not happening for you today, my friend.

You have to do a bastardized mutt application using a combo of annotations and XML deployment descriptors (remember those?).

Allow me to save you more time by showing a more concise example, so you don't have to take a time machine back to a time when EJB2.1 and XML roamed together in dinosaur-like bliss and figure out what the descriptor should look like.

Here's an example:

My MDB class signature looks something like this....

@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "destinationType",
propertyValue = "javax.jms.Queue") },
mappedName = "jms.ens.yes943processing.queue")
public class YearEndProcessingMdb implements MessageListener {
...


And so on, with your onMessage() and all the other crap you would put in an MDB.
Then my weblogic-ejb-jar.xml file looks a bit like this....

<wls:weblogic-enterprise-bean>
<wls:ejb-name>YearEndProcessingMdb</wls:ejb-name>
<wls:dispatch-policy>Ens943WorkMgr</wls:dispatch-policy>
</wls:weblogic-enterprise-bean>

<wls:work-manager>
<wls:name>Ens943WorkMgr</wls:name>
<wls:max-threads-constraint>
<wls:name>Ens943MaxThreadLimiter</wls:name>
<wls:count>10</wls:count>
</wls:max-threads-constraint>
<wls:ignore-stuck-threads>true</wls:ignore-stuck-threads>
</wls:work-manager>
</wls:weblogic-ejb-jar>



You can tell if the thread limiter is working by deploying, chucking a bunch of messages on thequeue, and checking the WLS console.

  • Go to deployments
  • Click to expand your EAR
  • Click on the MDB name.
  • Then go to the Monitoring tab.
  • Under that click on the Workload tab.
  • Here you should see your work manager and thread constraints with the number of messages they are processing.

Monday, November 01, 2010

Oracle Service Bus - Getting XML Out of Table Column

This took me a while to figure out, and ended up being pretty simple once I knew which XQuery functions were available.

Let's say you have a table you need to query from the OSB. The result set you get back from the JCA DB adapters gets turned into XML for you. If one of the columns is a LOB containing XML, then it gets escaped using CDATA. Anything in CDATA is basically ignored by XML, XSL, XPath, etc.

It is a 2 step process to extract that value and make it usable XML:

  1. Use the fn:string() function to turn the value into a string. In this case, it strips off the CDATA wrapper and gives you a string that looks like XML.
  2. Use the fn-bea:inlinedXML() function to parse that string into XML.

You can use an ASSIGNMENT task to jam that XML into a variable, and then run any XSL, XPath, etc on it. You can also use INSERT or REPLACE tasks to embed it back into your original XML.

Wednesday, October 13, 2010

A Few More SEAM Nuggets

I just came across some stuff that was supposed to be a blog post with some more SEAM tips and tricks. Since then, I've moved on to a new job, and haven't been using SEAM in my new position.

Showing Number of Matched Records in List View

When you generate a SEAM application from a database, you end up with a set of components for each table - for example a list view, record view, and record edit. When you are displaying a list of records, it is common to want to show how many records match the current query (or the total records if you went to list view without a search criteria).

You can easily get this function by accessing the "resultCount" attribute on your view, like this:

<h:outputtext value="#{yourTableList.resultCount} rows found." rendered="#{not empty yourTableList.searchResults}">

Change Default Sort Order, But Still Allow Click-To-Sort

One requirement we ran into on one of my SEAM projects was to change the default sort order for some of the list views. However, the views that the SEAM gen tool creates allows the user to click on the column headers to change sorting as well. To achieve a default sort order on initial load, and still allow clickable headers, override the getOrder() method in your List.java source like this:

@Override
public String getOrder() {
String order = super.getOrder();
if ("".equals(order) || order == null)
{
order = "col1 asc,col2 desc";//your default sort columns here
}
return order;
}


Wednesday, October 21, 2009

Running Multiple Versions of Oracle JDBC Driver on same JBoss server

We ran into an issue recently where we need 2 different versions of the Oracle JDBC driver on the same app server, because one application needs to talk to Oracle 8.0.6 (pre-8i even) and everything else talks to newer (9i and 10g) databases.

With the newer JDBC driver out in the Jboss server's lib/ directory, the legacy application fails to connect because of the dreaded ORA-604 that you get when trying to connect to a really early DB with a driver that doesn't go back that far. See the links below for Oracle's list of what drivers support what versions of Oracle. The exception is shown below in case you haven't seen it before.

Throwable while attempting to get a new connection: null
org.jboss.resource.JBossResourceException: Could not create connection; - nested throwable: (java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1
ORA-02248: invalid option for ALTER SESSION

Putting the old driver out in lib/ means that the newer datasources won't deploy properly.

After a few hours of Google searches and pouring through the Jboss.org wiki and forums, we just couldn't find the answer. We finally made this post to the Jboss forums:
We are using Jboss AS 4.2.2-GA and have hit a snag. One application needs to connect to an older Oracle 8 database, so we need to use the older Oracle JDBC driver. For all of our other applications, we need to use the newer Oracle JDBC driver.

But the classnames for the drivers are the same, so we can't figure a way to tell one *-ds.xml file to deploy under the early driver and everything else to use the newer driver.

We tried adding the older driver JAR file and the *-ds.xml file right in our application EAR file, but when deploying it picked up the newer Oracle driver from the server's lib directory anyways. This puzzled me as we are using ear-scoped classloaders.

Both applications are SEAM applications using EJB3/Hibernate. We can get one or the other to work depending on which Oracle driver we put in lib/ but can't get both to work at once.

I've been searching Google and the Jboss forums and wiki for the past 2 hours, and find lots of newbie "this is how to deploy a datasource" stuff, but nothing on 2 conflicting versions of a vendor's driver. HELP!
We got the response the next morning, and it turns out we were on the right path by putting the datasource file and classes12.zip in the application EAR file, but because of JDBC classloader issues, we had to also include a few other files and some extra application.xml config. Here is the complete article.



Links:

Tuesday, August 18, 2009

Multiple Column Subqueries (Oracle)

I recently had to do something like this in an application, and I had to look it up to see if it was even possible. I knew you could do this with a single value, but was skeptical if multiple columns could be done this easily.

For my own benefit, I am posting the basic syntax for next time I need to do it. Replace your table names where t1 and t2 are, column names for c1, c2, c3, etc. I did this in Oracle, but it may work the same or very similar in other databases.

SELECT *
FROM t1
WHERE (c1,c2,c3)
IN (
SELECT t2.c1,t2.c2,t2.c3
FROM t2
)

For reference, I found my answer at: http://www.java2s.com/Code/Oracle/Subquery/WritingMultipleColumnSubquerieswithtablejoin.htm

Wednesday, July 15, 2009

More Jboss SEAM Nuggets

As I dig farther into the Jboss SEAM world, I figured I would share a few nuggets of info as I find them. It's more notes than tutorial, so don't expect too much....


ORACLE TIMESTAMP ISSUES

If you are using Oracle, more specifically Oracle 9i and newer, you will probably have issues with date fields. There was a change in Oracle's JDBC driver somewhere between 8i and 9i that changes how the driver reports a DATE field in the metadata. Anyways, running seamgen gets you entities with Date objects with annotations like @Temporal(TemporalType.DATE).

When you go to deploy though, The validation fails because it is expecting a TIMESTAMP field, but gets a DATE field. That keeps the EJB from deploying and keeps the EntityManager from being bound.

Luckily, there is an easier fix than manually updating the data types and annotations in all your generated entities. You can add the following JVM argument to your startup to force the Oracle driver to report DATE fields based on the Oracle 8 driver behavior instead of the 9i+ driver:
-Doracle.jdbc.V8Compatible=true


RENDERING ISSUES ON SERVER

Speaking of JVM args, I noticed on my dev box (Windows), my SEAM app rendered beautifully. When I deployed to the Linux server, some of the fancy "3d" type components suddenly looked flat. There were exceptions in the log for some Swing classes (sorry I don't have the exact exception or stack trace, it was a while ago). Why is it using Swing to render page elements? Don't know, and at this point, don't care, as long as there is a simple fix. And alas, there is...

I added the following JVM argument to my Jboss startup to let it know it's a headless server. Seems to have fixed my issue.
-Djava.awt.headless=true


MULTIPLE PAGE DEFINITIONS FOR ONE PAGE

When you build out a new application using seamgen, you will notice that for each entity, you will have several view components. For example, you will have a TableName.xhtml and a TableName.page.xml file. The *.page.xml contains your <page> definition, that will define the view id, parameters, conversation settings, etc.

You will also notice that the SEAM pages.xml file also has (or can have) <page> definitions. Guess what, the pages.xml definition for a given page, if it exists, overrules the *.page.xml version. Remember that when changes you make to *.page.xml don't seem to take effect, or other odd behavior where those values seem to be ignored.

It's not a hierarchy, it's not an inheritance, it's a one-or-the-other situation. It caused me quite a bit of grief until I figured that out.



USING SEAM COMPONENTS FROM SERVLETS

So you need to throw in some regular old-school Servlet's into the mix? But you want your SEAM goodies too? Damn, you just want the best of everything.

There are a few ways to do it, and I found the easier way is to "wrap" your Servlet(s) in the SEAM filter. Add a line something like this to your SEAM components.xml file (make sure to change your URL pattern appropriately. In my case my Servlet is to download a CSV file).
<web:context-filter pattern="/csv"/>
And then in your Servlet code, you can get your SEAM stuff from the Components object like the sample below:
UnmappedAccount unMapAcct = (UnmappedAccount)Component.getInstance("unmappedAcct");
In this example, UnmappedAccount is a class in my EJB module annotated as a SEAM component.
import org.jboss.seam.annotations.Name;
...

@Name("unmappedAcct")
public class UnmappedAccount { ... }


CASCADING EJB'S

Allow me to throw out a minor warning on the generated SEAM code. The default CascadeType in the generated EJB's is "ALL", as seen in the annotation below.
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "...")
It's not devastating, it's not a bug, but it is something you should be aware of in case you don't want cascading (or worse, aren't aware of cascading and what it really means, and just happily go with the defaults).

See http://java.sun.com/javaee/5/docs/api/javax/persistence/CascadeType.html for more information on the various CascadeTypes, in case you don't already know. If you don't want cascading, remove the "cascade = CascadeType.ALL" portion of the generated annotation.

Let's say you try to delete a record that has children records attached to it. You might expect to get an error back saying you can't delete a record that has children attached. That's what you would get from, say TOAD or Squirrel or SQL-Plus, or even from applications written using plain old ODBC or JDBC statements. But with cascading, that delete will happily take care of those children for you without complaining ;-)



NAMED QUERY DEFINED IN COMPONENTS.XML

I just found this one, and it seems to be a good fit with what I have to do right now. I haven't finished it yet, so not much to share here yet. Once I get that working, it might be worth mentioning in my next nuggets post.

Wednesday, April 08, 2009

Google App Engine And Java

I recently posted about my experience playing with the Google App Engine and the Python language, in which I wrote:
For now, the only supported language is Python....I wouldn't mind seeing other languages supported in GAE, though not sure it really matters or if it is worth Google's time, money, and effort to expand support to other languages. I'm sure if they asked 100 developers they would get 100 different answers of what languages should be supported.
Well, just when I was getting used to the idiosyncrasies of the Python language, I went to look something up on http://code.google.com/appengine/ and found that they have an early preview of Java running on the engine. Here's the blog posting.

If I were one of the 100 developers mentioned above, my first answer would have been Java. I signed up as soon as I saw it, but alas, I'm on a waiting list. Looks like I'll be flirting with Python a little longer while I wait for my true love....

The really cool part of getting Java running in the engine is that should bring the other languages that run on the JVM as well, e.g. Scala, Groovy, JRuby, BeanShell, and, yes, even Jython.

Oh the fun!

Tuesday, March 31, 2009

Google App Engine & Python

I finally took the dive into the Google App Engine last week. It's free to get started (up to 10 applications per Google account) and gets my feet wet for this whole "cloud computing" crapfest. Here are my first impressions of Google App Engine and Python. I won't go into my issues with cloud computing in general and all the hype surrounding it, and how it will magically solve all of our scalability and maintenance issues.

I was surprised at how well done the Google App Engine is, and how quickly I could get started. Downloading and installing the local development environment was quick and painless, and walking through the tutorial, I had a very basic "guest book" application written and deployed out in the vast Google cloud for the world to see. The local development server was up and running within minutes of downloading and installing, and making changes to the Python scripts didn't require any redeployment or restarts. Uploading to the Google servers was a matter of running a single script and entering your user id and password. There is even an admin console where you can see stats on your page visits, bandwidth used, performance, etc.

I like that the Google users and authentication is pretty much built in, as well as the simple "webapp" MVC framework, and that you can use any pure Python library or framework you want to use (as long as there aren't any extensions written in C). The data access layer and GQL query language is interesting -- one big free-form data store where you aren't dealing with individual tables so much as just defining your entities in your code's data structures, and reading and writing from them as if they are tables.

For now, the only supported language is Python, which I have never dealt with. That really wasn't much of a hurdle since the syntax is pretty straight forward and easy to learn. I wouldn't mind seeing other languages supported in GAE, though not sure it really matters or if it is worth Google's time, money, and effort to expand support to other languages. I'm sure if they asked 100 developers they would get 100 different answers of what languages should be supported.

I'm a little more ambivalent toward Python. I didn't dislike it, but it just didn't grab me by the balls and make me exclaim it's superiority either. I can say I'm not a fan of the whole "indentation exception" crap. As a guy with more of a C and Java background, I like my curly brackets instead of relying on indentation levels, which remind me too much of COBOL, yuck!

Anyway, here's my trivial little application. It's all "tutorial-ware", straight out of the book with a few CSS enhancements and a simple "about" page. It's not useful, but not bad considering how little time it took to write.

Next step.... write something useful. I definitely want to get into this more and add it to my development toolbox.

Tuesday, March 03, 2009

An Overzealous SEAM Validation

I am using the Jboss SEAM framework for the project I am currently working on. The first thing that really bit me was a validation on single character fields that seems a bit "too stringent". I'm sure I'm not the first to run into this. In fact it may be fixed by now in a newer version of SEAM, but figured it's worth a post anyways.

When you use Jboss Developer Studio (JBDS) to reverse engineer your database (I imagine the seam-gen tools do the same since JBDS uses them), the getter method on the EJB looks something like this...

@Column(name = "DEFAULT_REMAP_IND", length = 1)
@Length(max = 1)
public Character getDefaultRemapInd() {
return this.defaultRemapInd;
}
Looks fine, looks reasonable. Single character fields are often used for flags or indicators, as this one above is -- it's a simple Y/N field. So in my XHTML I use a radio button control instead of a free form text field.

<h:selectOneRadio id="defaultRemapInd" value="#{ocamCustTypeDfltHome.instance.defaultRemapInd}" required="true">
<f:selectItem itemValue="Y" itemLabel="Yes" />
<f:selectItem itemValue="N" itemLabel="No" />
<a:support event="onblur" reRender="defaultRemapIndDecoration"/>
</h:selectOneRadio>

The SEAM framework will use that @Length annotation to perform some field validations for you automagically, which is pretty cool as it can be a real time-saver. But the funny thing is that when this "max length of 1" validation fires, you get the lovely message shown in this partial screen shot ....

Not sure how to get a single character with a length greater than 0 but less than 1, but I do know that the easiest thing to do in this case is remove the @Length annotation for that field. I had to do that for a few different tables. Luckily they were all flags that could be replaced with radio buttons, but in the case where you had to allow free input, you might have to get more creative (you can always put a max length on the input text field).

For reference, I am using Jboss 4.2.2, SEAM 1.2GA, Jboss's EJB3 implementation (which is Hibernate under the hood), XHTML and Facelets for the views. Like I said, this might be fixed in a later release of SEAM.

Monday, August 18, 2008

Simple JSP To List Java JVM Environment

Here's a simple JSP to list out all the JVM environment keys and values. Very simple, but occasionally useful. For example, a few weeks ago I needed to see which SSL keystore (javax.net.ssl.trustStore) our test servers were using.

I'm sure every Java developer has written similar code at some point, so I won't claim it's original, unique, or ingenious. But if you find it useful, go ahead and use it instead of writing another.


Sunday, May 18, 2008

Jboss SQL Deployer

I whipped up a fairly simple SQL deployer for Jboss this past week. It is currently fairly limited, but also very straight forward and should be easy to maintain.

It consists of a class implementing java.lang.Runnable (a Thread) that wakes up every 20 seconds or so and scans a directory for any new SQL files. Of course there is also a class implementing java.io.FileFilter to look for just SQL scripts. To turn this into a JMX service, I wrote a simple BeanShell wrapper to drop into the deploy directory.

Once a SQL file is found, the code assumes the first line will contain the DataSource JNDI name, so it knows what database to connect to. Then it currently assumes the rest of the file is one query. The query results are formatted and dumped to STDOUT.

To make this truly useful, I will have to make it accept updates as well as queries, and parse the file looking for multiple SQL statements instead of assuming it is just one. Other than those limitations, it works great with the few tests I have done so far. I have been testing under Jboss 4.0.3, but this should work with any version of Jboss with the BSHDeployer.

SqlFileScanner.java


SqlFileFilter.java



sqldeployer.bsh



Why would you use this? That's always a good question to ask, and this time I have an answer besides "because you can".
  • Running ad hoc queries right from your app server, using the same Jboss DataSource bindings your applications are using, and from the same server your apps are running, can be very helpful in troubleshooting issues.
  • Let's say you use Realms instead of username/password in the DataSource XML descriptor, for security reasons. Now you can troubleshoot database issues as that user even without knowing the DB username and password.
  • Set up simple reporting jobs without needing an Oracle client installed on the machine -- run them right from Jboss.
Conslusion
I think I may create a new open source project to house this as well as all the other Java "odds and ends" I have written over the years, like some of the code generators, MQ tools, servlet filters, JSP tags, etc. The hardest part will probably be coming up with a meaningful project name -- who wants to download and install "RobbsRandomJavaCrap.jar"?

Thursday, May 01, 2008

Some Old-School JAM and JPL Tips

The JAMster Speaks...

I was cleaning out the barn and found a CD of some old code and documents I had written at an old job, kind of a "portfolio" CD if you will. We used JAM to build Motif screens.

JAM let you visually build your screens, and had it's own procedural programming language, JPL (JAM Programming Language). JAM came with the necessary C code to handle launching of the screens and handling events. You could write your own custom C code to be called from the screens, or write your code in the JPL file for the screen, or a combination of both. One nice thing is you could write SQL code right inline with the rest of your JPL (just prepend the keyword "sql") and everything was taken care of, even down to binding the result set to variables.

It's not exactly cutting edge technology now, but I know it is still in use by at least a few companies. This is not a tutorial for non-JAMsters, but rather a collection of troubleshooting tips I had taken note of. Maybe this could be of use to someone just inheriting legacy apps, or who knows when I might run into JAM again. Yuck!

For reference, these tips are mostly for JAM 5 and 7, but they may be applicable for other versions as well.
























SELECT 1 FROM table...This is often
done to see if a record meeting your criteria (where clause) exists in
the table.
Doing this from a JAM screen (at least in Jam 5) will produce a
@dmrowcount of
0 (zero), even if there are records in the table meeting the criteria.
There
are two alternatives within JAM to get the same information:

1. SELECT
COUNT(*)
temp_var FROM table...

2. SELECT
column temp_var FROM table...
SELECT column FROM
table
This one can be tricky.
If there is no JAM variable with the same name as the the selected
columns,
then JAM will create those variables and put the results of the query
in those
variables. If the variables do exist already, JAM will overwrite the
values
with the results of the query, even when the query returns nothing (it
will essentially
clear the variables).
Mixed Case VariablesMixed case variables
can be a real problem with JAM, and the error messages are not
intuitive enough
to let you know what the real problem is. Keep tihs in mind when you
can’t
figure out some quirky behaviour, and all the other logic and syntax is
proper.
Changes in screen file don’t seem to take effectCheck the local
directory you are running from. JAM will use screen, JPL, and
dictionary files fro mthe current directory before
checking in the SMPATH, regardless of what the SMPATH is set to.



Check the data
dictionary. The screen fields and variables can be stored in here, as
well as
in the screen definition file. Data dictionary tends to overwrite
local (screen) vars.
Some Useful environment VarsMost of the relevant environment variables
start with SM, e.g. SMVARS, SMPATH

  • Also worth noting is that while it might make sense that they would just make use of the underlying Motif widgets, in some cases that was not the case. Simple text boxes for instance would not work with bi-directional Hebrew whereas pure Motif screens did. We had to have JYACC / Prolifics issue a patch for us before we could release to an Israeli customer.
  • There were also issues with some characters in the Turkish (ISO-8859-9) character set. Their database layer simply could handle it for some reason. Wouldn't bring back results, wouldn't update, and yet We ended up having to write our own generic database access layer using Pro-C, and replacing all the JPL "sql" statements with "call" statements into our library.

Tuesday, April 29, 2008

Some Notes On The Jboss BeanShell Deployer

I've been playing a little with the BeanShell Deployer in Jboss lately. Technically, it's pretty cool. Drop a .bsh script in the deploy directory and the hot deployer picks it up just as if you dropped a .war/.ear/.sar file in there. If it's a simple script, the bsh deployer runs it immediately. Or you can implement any or all of the methods of the ScriptService interface (below) and your script will be deployed as a service mbean.
public interface ScriptService
extends org.jboss.system.Service
{
public String objectName ();
public String[] dependsOn ();
public Class[] getInterfaces ();

public void setCtx (ServiceMBeanSupport wrapper);
}

It was extremely easy to write a few scripts and drop them in the deploy directory. Of course, you can start with the requisite "Hello World" script, which upon deployment, prints out to the console. A few more minutes of scripting (adding the above methods) yields a service mbean that can be managed via JMX.

But then the obvious questions: Why? Why would I write mbeans using bsh instead of Java? What do I gain? What do I lose? Is it really any quicker?

I don't really have good answers for the why question yet. I did write a few services using bsh. They were easy enough to implement, but nothing that couldn't have been done in a similar time frame using Java. You lose compile time error checking, but you avoid some of the plumbing regarding build scripts, deployment descriptors, and building .ear or .sar files.

I did write a few services. One connected to a Websphere MQ (a.k.a. MQ Series) queue manager to get queue depths and print them to the Jboss console. I ripped most of the code right from an existing MQ tool I wrote a few years ago. So not the most useful thing in the world, but it proves out importing existing Java classes and the Java syntax. Another used JDBC to connect to an audit database and purge old transactions. Again, nothing that couldn't be done in regular old Java code in the same amount of time.

Overall, I didn't feel like I was saving any time. For one, the syntax is Java. That's great for code re-use (either cutting/pasting or importing libraries), but Java syntax doesn't have that "lightweight scripting" feel to it. Also, the lack of compile-time error checking doesn't save you much time if you have to run the script to find errors. Make a simple mistake like a type mismatch or failing to catch a specific exception, and your IDE and/or compiler will tell you about it. Do the same thing in a bsh script, and you find out after you deploy it and run it.

I think this could prove useful in the future, as one more tool in my programming toolbox, but have to admit I don't have a lot of use for it right now. Maybe I'm just not seeing the big picture, or just haven't run across the scenario where this is the ideal way to solve a problem. If you are using the bsh deployer, please let me know what you are doing with, or what types of problems you are solving with it.

Once I have a reason to use it, at least I know it is easy to do. And once the why question starts to have answers, maybe I'll explore writing a JRuby or Groovy deployer. Or actually, what would be really useful would be a SQL script deployer, so you could run ad-hoc queries against your Jboss DataSources without writing JDBC code or having to launch a DB tool like Squirrel or TOAD. Since Jboss deployers are service mbeans, maybe I could write the SQL deployer in bsh...


Monday, April 14, 2008

The BeanShell Servlet Filter Summary

OK, now that I step back and look at this post I wrote a few days ago, I realize I use too many words, tend to blather on and on and on.

So to summarize:
  • What's the point? It's a Java Servlet Filter that delegates to BeanShell scripts to do the actual Filter work.
  • Does it really work? Yes. I am currently running it in Glassfish, but should work in any Java servlet container. It's still just a proof-of -concept and needs to be cleaned up to make it production ready.
  • Where's the code? Of course, you still have to go to that post to see the code, but you can skip the blathering on and on and on.
  • What's the point? Well, just because it can be done I guess. My theoretical ramblings on "why" are what made the post so long in the first place.

Saturday, April 12, 2008

Dynamic Servlet Filters Using JVM Scripting

What got me on the subject of Servlet Filters in the first place was an idea that occurred to me recently. Servlet Filters aren't the sort of thing that can be easily altered at runtime. They are mapped in the web.xml file, so if there are Filters you only want for development or test, but not production (like the DebugFilter I presented in the last post), you have to jump through some hoops to make that happen. You could edit the web.xml before deployment, or have separate dev/test/prod web.xml files that ANT copies into place depending on the build, or have some sort of runtime flag (DB property, value bound in JNDI, etc.) that will either run the Filter logic, or just pass through to the next in chain.

But what if you could not only enable or disable the Filter, but also change it's behavior, on the fly at runtime without special build or deploy steps. I was pondering this idea and came up with the concept of a Servlet Filter, that by itself, does nothing.

Nothing? Well, nothing by itself.

"By itself" is the key phrase here. Instead of doing something in the Java code (getting timings, checking security, auditing calls, printing debug statements, etc.) it just instantiates a scripting engine, like BeanShell (BSH), JRuby, Groovy, etc. It starts up the scripting engine, passes the Request and/or Response objects, and runs a script that you have identified. That script does all the meat-n-potatoes work, and the Filter then calls next in chain like it normally would. And the best part is, the script could be changed at runtime, from a simple do-nothing-and-return to full blown screwing around with the Request and Response objects.

I've developed a proof-of-concept (POC) and have it running under Glassfish v2 application server. I used BeanShell for the scripting engine in the POC, but as stated above, any of the scripting engines for the JVM should work. This isn't quite ready for primetime, but it fully works.

There are actually 2 scripts called by this filter, one before the chain.doFilter() call is made, and one after. That way you have the flexibility to do operations either on the request, on the response, or both.

First, the Java code for the Filter:


Then, the 2 BSH scripts:

BSHServletFilter_PRE.bsh


import java.servlet.*;
import java.servlet.http.*;
import java.util.*;

System.out.println("This is the BSHServletFilter_PRE.bsh script!!!");

StringBuffer output = new StringBuffer();
output.append("\nRequest Attributes\n");
Enumeration attrs = request.getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = (String) attrs.nextElement();
output.append(attr +" - " + request.getAttribute(attr));
output.append("\n");
}

output.append("Request Parameters\n");
Enumeration params = request.getParameterNames();
while (params.hasMoreElements()) {
String param = (String) params.nextElement();
output.append(param +" - " + request.getParameter(param));
output.append("\n");
}

System.out.println(output.toString());
System.out.println("This consludes the BSHServletFilter_PRE.bsh script!!!");



BSHServletFilter_POST.bsh


System.out.println("This is the BSHServletFilter_POST.bsh script!!!");
System.out.println("About to alter the response...");
response.getWriter().print("<h1>This response is from the BSH script</h1>");
response.getWriter().flush();
System.out.println("Done altering the response");


And the browser screenshot...

This is currently just at the POC stage. It is working as-is, running under Glassfish. But as you will immediately notice, the filenames for the scripts are hard-coded, and there is definitely some more cleanup to make this production quality code. But, you can change the behaviors of the filter, for better or worse, at runtime without any compiling, deploying, or restarting of servers. You can even "disable" the filter by writing BSH scripts that do nothing.

Thursday, April 10, 2008

A Servlet Filter For Easier Debugging

I whipped up this quick Java Servlet Filter (javax.servlet.Filter) to aid in development and debugging. This simply dumps all the HTTP request attributes and parameters and Session attributes to the log. Like any other Servlet filter, it can be chained with other filters like the timing filter, GZIP filter, etc.

This isn't meant to be a tutorial on Servlet filters, I am assuming you either know (or know how to figure out) what filters are, and how to tie them into your application in the web.xml descriptor.

I "printed" the source into a PDF to keep the formatting in tact. Here is the link, or if your PDF plugin is working, it should appear in an iframe below....



Monday, March 17, 2008

Oracle on Windows Authentication Woes (And Solutions)

For my current project, I need to have my own development Oracle instance. Instead of carving out space on one of the servers, I figured it's a good time to just bite the bullet and install Oracle XE on my desktop (Windows XP). For the most part, it has been a fairly painless experience.

Except that several times already, when trying to run imports or simply connecting via SQL-Plus, I get the following crap:
C:\oraclexe\app\oracle\product\10.2.0\server\BIN>sqlplus XXXXXX/XXXXX

SQL*Plus: Release 10.2.0.1.0 - Production on Mon Mar 17 08:50:29 2008

Copyright (c) 1982, 2005, Oracle. All rights reserved.

ERROR:
ORA-12638: Credential retrieval failed
The first time it happened, I simply restarted the OracelServiceXE and OracleXETNSListener services. Then it happened again today, and restarting services had no effect. And I am NOT rebooting my whole machine just to get Oracle to work.

But thanks to someone named "babu george" on this forum, I fixed the issue quite simply by getting rid of NTS authentication.

In your sqlnet.ora file, simply comment out the (NTS) line and create a new line with (NONE) in place of (NTS).
#SQLNET.AUTHENTICATION_SERVICES = (NTS)
SQLNET.AUTHENTICATION_SERVICES = (NONE)
Alas, don't get me started on how much I love Windows.

Friday, March 14, 2008

Trashy Yet Effective Oracle Trick

I need to post this so I can remember it next time I screw up...


I was running an Oracle import (imp) on my local Oracle 10g XE instance today, and realized I did it incorrectly and imported everything into the SYSTEM schema. Oh crap, I can't just wipe everything out, it's my SYSTEM schema! I need surgical precision to only remove the crap and leave all the Oracle stuff unscathed.

I could go through and drop each table I created, but there were hundreds.

Then, like a tornado in a trailerpark, it hit me. An idea that walks the fine line between genius and insanity. All the new table names started with a common prefix, which for sake of discussion I will call "BLAH_". So in Squirrel I run the following query:

select 'drop table system.' || table_name || ';' from all_tables where owner = 'SYSTEM' and table_name like 'BLAH_%'

Then cut and paste the results back into the Squirrel query runner and run the results as a script.

I'm sure there's an "official" way to accomplish the same thing, but screw that, this was extremely quick and kind of fun.

Trashy yet effective.

Monday, February 25, 2008

FCKeditor - Embedded HTML Editor

For a recent project, I wanted something fancier than a regular HTML text area to allow user input with formatting. "Something like the editor on Blogger", I thought.

After hitting Google, I ran across FCKeditor. I had heard of it before, and even played with the demo once, but never did anything with it. Never had much of a reason to. Today that all changed.

After reading through the Developers Guide, I downloaded the ZIP, unpacked into my public web directory, and had it working in no time. In less than 30 minutes, I had the FCKeditor completely tied into an existing Rails form, replacing a boring old text area. After a few minutes of testing inserts and updates, and some cross-browser testing with Firefox and Internet Exploiter, I was happy.

There were only a few lines of JavaScript code to add to the page, and those are all spelled out in the Developer's Guide, so I don't feel the need to repeat those here.

Overall, I was pleasantly surprised. Unlike a lot of open source projects out there, this was extremely easy to get started with, easy to install and embed into existing applications, and the documentation was pretty good for a change. The quality so far has also been nothing short of impressive. (the editor is more full-featured than the one Blogger uses.)

It's licensed under the GPL, LGPL, or MPL (your choice), and can be embedded in any project, open source or commercial. Also, in addition to the JavaScript version I used today, there are versions for JSP, ColdFusion, PHP, Python, etc.

This project today was just a personal side project, but I think FCKeditor might find it's way into my arsenal for work projects as well.