BibleGateway.com Verse Of The Day

Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

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

Enabling Oracle Trace For WLS Connection Pools

We recently had the need to run an Oracle trace to catch some database diagnostics for an OSB call flow. To enable the trace only for the sessions coming from WebLogic, I added the following to the "initSql" field in the connection pool setup screens (in the WLS console). Just remove it and save the pool settings when you're done collecting your *.trc files. Works like a charm.

SQL BEGIN DBMS_MONITOR.session_trace_enable(waits=>TRUE, binds=>TRUE); END;

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, August 18, 2010

ORA-24777 When Using XA Driver

Here's something we came across this past week, and after some searching, it appears to be a fairly common issue.

We are calling some PL/SQL stored procedures through JCA adapters on the Oracle Service Bus (OSB). Our connection pool on WebLogic is setup using the XA JDBC driver.

Everything was great until we called a stored procedure that queries across a database link. Then we got the dreaded ORA-24777 - use of non-migratable database link not allowed.

Turns out there are at least 3 ways to rectify this issue....

  1. Set up Oracle to use multi-threaded server, a.k.a. shared server. There are ups and downs, and depending on who you talk to, mostly downs, especially concerning performance. We haven't tried this, but it does come up often as a fix.
  2. Create a "shared" database link. The syntax is a little different than a "normal" link. This is what we did, and it worked fine.
  3. Third option, though not right for everyone, would be to use the non-XA driver.
Creating a shared link....
CREATE SHARED DATABASE LINK 
CONNECT TO IDENTIFIED BY
AUTHENTICATED BY IDENTIFIED BY
USING ;

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.

Thursday, May 28, 2009

Emergency Startup CD for Windows

BartPE, because sometimes you actually have to run Windows.

If you have Windows and your system did not come with a "rescue", "restore", or "emergency startup" type CD (yes, I'm talking to the cheap bastards at Dell who don't include the Windows CD), then you NEED to follow the instructions at http://www.howtohaven.com/system/live-windows-rescue-cd.shtml. This creates a bootable "BartPE" CD with all the right utilities for fixin' what ails ye.

Do it now! Before you need it, not after. I learned the hard way, and after this past week, I can't sing the praises of BartPE enough. It was a life saver.

My wife's laptop booted to a BSOD when I was trying to VPN in to work. Oh well, a night off....but then it kept doing it, over and over. I couldn't get Windows to start for the life of me.

Since I didn't have a bootable Windows CD, I was left trying to boot FreeDOS from my thumbdrive (using LiveUSB Creator) . I made sure to have a copy of NTFS4DOS installed on there as well, and ran through some exercises where I got a command prompt to manually copy registry files around. That was painful, but it actually worked enough to get the machine to boot into XP. But it was a version of XP that had all sorts of issues, error messages, drivers crashing, no USB support, no CD recording, no network, etc. Without USB, network, or CD burning, I couldn't get our important files off the machine.

Anyway, to make a long story short, the FreeDOS/ntfs4dos route was crappy and painful with no real reward.

The BartPE rocks the house! It boots into a minimal XP interface with all the right utilities for fixing your issues, and USB drives are recognized, so I can copy important files off the machine in case I feel the need to wipe it clean.

I guess I really should do regular backups, but what fun is that? Preventing problems is boring, solving problems is heroic....

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 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.


Wednesday, July 16, 2008

Making Your JVM Trust Those SSL Certificates

Guess I should follow-up with a "part 2" on yesterday's post about saving off SSL certificates. The whole point of me going through the exercise was that one of the web services we consume is SSL and the certificate expired. The new certificate was self-signed, so our Java code threw exceptions saying a trusted certificate was not found.

So the second step for me was to import them so my JVM(s) would recognize the certificate as "trusted".

To get your JVM to trust the certificate, you import it into your keystore using the keytool executable (found in your JDK bin directory):
[jboss@j2apptest01 bin]$ ./keytool -import -alias SomeWebserviceName -file ~/SomeCertificateFileName.CER
If the keystore does not exist yet, the tool will prompt you to enter a keystore password. Remember that password, as you will need to use it to import new certificates or export or view current ones.

It will then display all the keys and other info about the certificate and ask you to confirm that you really want to import. You will want to verify the keys match up to what you think you are importing, of course. Then type "yes" and it should tell you the certificate was added.

After that, our calls to the web service started to ork again, like magic.

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"?

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....



Thursday, February 07, 2008

Reading And Writing Text Files in Ruby

On a recent project, I had everything automated up to the point where I had to give feedback to the business analysts on what, if any, of their data had to be fixed and re-run.

I ended up writing some Ruby scripts to run through a file of transaction responses, and sort out the various error types into separate files, and produce a summary report of the error counts in each category.
Now the only manual part was cutting and pasting the summary into an email, and attaching the various sorted files.

I was pleasantly surprised at how easy it was to read and write text files in Ruby. Let's say you just want to read a text file, line by line, and spit it back out, a la "cat"...
File.new(filename, "r").each { |line| puts line }
Wow, that was easy, eh? Let's try reading that file into an array for use later...
results = []
File.new(filename, "r").each { |line| results << line }
Let's say you want to capitalize everything in the file, and spit it out to a new file...
out_file = File.new("upper_case.txt","w")
results.each do |line|
out_file.puts line.upcase
end

That was easy. It's probably obvious, but the first argument passed to the File constructor is the filename, and second is the read/write flag.

For comparison' sake, let's read a file in Java and spit it out line for line...
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
...
BufferedReader is = new BufferedReader(new FileReader(fileName));
String line = "";

try {
while (line != null)
{
line = is.readLine();
System.out.println(line);
}
catch (Exception e) { /* do nothing for now */ }
finally
{
try {is.close();}catch(Exception f) { }
}

Definitely not "hard", but it is a bit more code. Writing a file is very similar, except of course you use FileWriter and BufferedWriter instead of FileReader and BufferedReader, and write to the file instead of reading from it.

I'm not really trying to prove anything here -- Ruby isn't better than Java, Java isn't too hard or too verbose, etc. I like Java. I like Ruby. Against my better judgment, I even like Oracle, but that's another topic. I just found that working with files was easier than I expected, even for a Ruby beginner like myself.

Monday, October 01, 2007

Let's Rock

All right, my wife's at work, my kids are in bed, Lexi is sleeping. I've got Dead Poetic on my iPod, XAMPP on my thumb drive, and a brilliant new MySQL database schema created for my new bastard stepson of a side project. Time to generate some scaffolding! For this top secret project, I will write the back-end admin stuff using Ruby on Rails. For the front end, I haven't quite decided yet. I'm just not sure how RoR scales up for an external facing website, and for what I am doing it might be easier to use Java anyways, as I can write a few JSP tags to use on any of the pages, and use Velocity as the templating engine to build the special configuration page.

Then again, I just got paged for a work issue, and that trumps side projects. DAMMIT!

Monday, August 06, 2007

A Great Interview Question

I had to do a few interviews last week, and some of my standard questions were getting a bit stale. So I went out on Google and searched for some new ammo.

I came across this question: "What is the difference between final, finally, and finalize()?"

At first I thought that was too easy, mostly because I knew the answer, and it seemed fairly obvious. Even so, I broke it out in an interview, and the guy nailed the first two, missed the last one.

I was relating that tale to a coworker afterward, and she said, "what was the question he missed?" She nailed the first two, didn't know the last. She's a good programmer; I've worked side by side with her every day for the past few years, and she missed it. That's when I came to the conclusion this is a great question.

Even good programmers don't know everything, and not many Java programmers really have to get into the bowels of memory allocations and garbage collection. This is a great question, not because I want the guy who can answer all 3, but because I want to see how people handle themselves when they don't know the answer. Sometimes that will tell you more about the person than if they just know all the answers.

The first guy I asked this question got the first two 100% correct, then he flat out said he didn't know what finalize was, hadn't run across it, and then he wrote it down in his notebook and said he would have to look it up.

The second guy I asked, he missed it, but didn't seem to know he missed it. For finally, he stammered about a bit and mentioned it was for garbage collection, then switched gears a little and said you usually use it with a try/catch block. Then for finalize, he said he didn't know what it was.

So both missed it, but was one answer better than the other?

In my mind, first guy won. He admitted what he didn't know and showed some level of ambition to look it up. The second guy tried to dazzle me with a little BS for a minute before admitting he didn't know. He didn't write anything down or mention looking it up, he just racked it up as a missed question.

They both went on to answer other technical questions to my satisfaction, but I came away with a slightly difference perspective of each. If they both just nailed every tech question I threw at them, I wouldn't have that added bit of perspective. And how do you know it isn't just "book smarts" -- a lot of those guys that rattle off every new buzzword and argue about architectures and design patterns can't write code to save their lives.


Other Interview Follies:

A lot of funny things do happen when interviewing. Everything I have ever learned about interviewing seemed like common sense, until I met some of these folks:
  • One of my manager's standard questions: "How would you structure your ideal work day?" (e.g. 50% development, 20% support, etc.) One guy told us he would sleep in, get to work late, of course he would stay late also, but his brain just doesn't work in the morning unless he has 10 cups of coffee, so he would rather sleep. Honesty is NOT always the best policy.
  • One lady told us she mostly does front-end work. When I asked her what she was using to build the interfaces (Swing, JSP, JSF, etc.), she told me she mostly does back-end server work. Nice 180, thanks for coming in today!
  • Another guy just got done telling us about all these web applications he wrote, JSP's, servlets, etc. I asked if he was using STRUTS, and he told me he wasn't sure, he might be using it. Then when I asked what application server he was using, he said UNIX and Windows. I tried to clarify, asking him which J2EE server he was using, he looked confused; so I changed my terminology to "servlet and JSP container", he still looked confused; so I made it multiple choice: "Are you using Websphere, Weblogic, Tomcat, Jboss?" His final answer: "Tomcat sounds familiar."

Tuesday, July 31, 2007

Using JConsole To Connect To Remote JVM

We have been having issues with a certain Java web application we inherited. Actually, we've had a few problems with it, but that's another story.

One issue was that, even though there is nothing running on this Linux box except a single instance of Tomcat (5.5) with this single web application deployed to it, we will get into frequent issues where we get paged for "high CPU utilization". Log in to the machine, and the Java process is taking 100% CPU. It might stay like that for a few hours, or even a few days. Occasionally it clears up on it's own, but usually the server stops responding and we have to restart Tomcat.

We have had another issue where we would get Out of Memory exceptions (Heap space), and the JVM would stop running. The two issues weren't necessarily related, but we couldn't rule out the possibility either.

We don't have much visibility into the application and what's going on since it is a vendor built "black box". We have some customized source code, but most of it is off limits to us. They rolled their own database connection pool, MVC framework, persistence framework, etc.

In comes Jconsole. JConsole is an awesome tool that comes bundled with JDK 1.5 and above. It connects to the JVM and gives you all the info you could want on the various JVM memory pools, garbage collection, threads, classloading, and lets you manage anything exposed via JMX. It also has lots of pretty graphs, such as memory usage and garbage collections over time, for any or all of the memory pools (heap, non-heap, or individual pools, like permgen and eden space). Same goes for threads and loaded classes --current number, peak, total created.

The best thing about JConsole is the ability to connect to remote JVM's so you don't add too much overhead on the box being monitored. I have JConsole hooked up to my test and production servers, and it helped me prove that the two issues above were connected. There is some condition in the application (yet to be found, actually, first step was proof of what's really happening) that causes a substantial memory leak, and once the memory usage gets at it's ceiling, the garbage collection thread basically runs constantly, trying to regain some trivial amount of memory, then filling it up, and running GC again.

With an average of 100 active sessions at a time plus full garbage collection running non-stop, the CPU gets consumed quickly. I monitored the app for about a week and a half, and memory and CPU looked great -- there were a bit over 200 full GC's in that time period. Then this past weekend, we had to restart because of a DNS issue. That was Friday evening, and by Monday morning there were over 2000 full GC's performed, and I was restarting a non-responsive server by lunch time.

Below are two screenshots, one is of several days of "normal" memory usage, notice gradual rise and then sharp decrease at full GC, all the while keeping well below the JVM's allotted memory ceiling. Second is this past weekend's issue, where memory is hovering at ceiling and a full GC doesn't do much. Also notice the old generation memory pool is quite full.




MAKING IT HAPPEN

To set up JConsole to run on a local JVM, you only need ot pass one extra argument to the JVM:
-Dcom.sun.management.jmxremote
To set up remote (with no security), it is a matter of adding a few more parameters to the remote JVM at startup:
-Dcom.sun.management.jmxremote.port=8004 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
Then when you start up JConsole, go to the remote tab, enter the server name and the port that you specified (in this case, 8004).

Simple as that. It starts collecting stats immediately and the graphs appear. As you explore the JMX tree, you will notice yo ucan click on some of the stats and the simple integer displays "opens up" into a full graph display. I'm doing this to watch the active sessions patterns through the day and week.

Thursday, June 14, 2007

Getting Thread Dump Of Running Java Process

Of course you can kill -3 a process to get the thread dump, but for Java apps you can also get thread dumps of running processes using the JDK 5 tools jps and jstack. For example, on a server where I am running Tomcat 5.5, typing jps gets a list of all Java processes running:
-bash-3.00$ jps
25515 Bootstrap
26912 Jps
Then using that process id, run jstack:

jstack 25515