Java tips and tricks from a lady trying to play with the boys...

Friday, August 22, 2008

Issues with CVSNT - Switching Between Unicode and Ascii

Problem: Using TortoiseCVS, a developer somehow checked in a bunch of SQL files as Unicode. I am nsure what exactly the developer did to do so, but likely it was caused by right clicking on a file when adding it to CVS and randomly selecting options from the "format" and "keywords" menus there. Who knows.

As the files were checked in and checked out of CVS by various developers, the files became more and more corrupted, merges were difficult, and the developers were unable to do their work without searching for random Unicode characters in the files and deleting them. In addition, CruiseControl stopped recognizing changes to files for updates.

Solution: A command-line interface needs to be used, I was unable to find a resolution with the CVSNT GUI interface.

  1. First, CVS.exe needs to be in your windows path. This was already done on our server because of CruiseControl and ANT using it.
  2. The command from a windows command line is:
    cvs update -kkv
  3. Once you have done this, you can use CVSNT to commit the file. If you do not commit, the changes will not be made. HOWEVER, you cannot commit using standard CVSNT means (TortoiseCVS). You need to right click on the file, select "Command" and enter the command commit -f
  4. The -f on the commit is absolutely necessary.
That's it!

Wednesday, July 9, 2008

Fumbling with JAWIN

Currently, there is no quick and dirty way to use opensource Java tools to convert Word Documents to PDF. So, to do this task I've been using BCL Technologies' Easy PDF. Since this application is written as COM, a java to COM bridge is necessary to use the SDK with Java. With Easy PDF 5.0, I had set up my own method of using the opensource tool Jawin to do this bridging. Now, I'm upgrading to Easy PDF 5.1 and they have a Jawin Java build included in their build, which I was pretty excited about. However, they built the jar with Java version 6, which I cannot use as we're stuck with Java 5 since we are dependent on Websphere (why would you not include more than one build with different java versions anyway? Whatever).

Since I had used Jawin before, I decided to attempt to do what we needed to do with Jawin, Java 5 and Easy PDF 5.1. The initial backwards compatibility with our code that was using Easy PDF 5.0 was smooth and simple - the build worked the same as I'd done before and no code changes were required.

Moving on to the new requirements, which is why we're upgrading Easy PDF. We needed to utilize additional features - merging two or more PDFs into one, splitting one PDF into two, deleting pages from a PDF, adding a watermark to a PDF. I rebuilt the code with Jawin to use these new features. And, there were difficulties. This is more of a complaint about Jawin than about Easy PDF.

Jawin is a great idea and on the surface (at least for my purposes), easy to use. However, the current version is an alpha version, and hasn't been released in several years. The real problem using it came from trying to use the Variant object. Documentation for how to use this object is spotty. Examples in the sample code are non-existent. Internet searches brought back a couple of threads, but most were just people asking the same questions that I had and not getting any answers.

Trying to create a Variant object was my first problem. I ran into multiple issues, and I was simply trying to pass something an array of Strings. That should not be as difficult as it was. I did get the "org.jawin.COMException: 8000ffff: A VT_VARIANT must be combined with VT_BYREF (base vartype 12)" yesterday, when trying to use myvariant.vt = VarTypes.VT_VARIANT or even using VarTypes.VT_BSTR, which is what I thought I was supposed to be doing. It is difficult to comprehend WHY we are putting things into a stream in order to make them into a variant, and how to get them out again.

So, I finally followed this guy's advice, which I found this morning. I overrode the class that was generated by the type browser. Instead of creating a method that accepts a Variant that is an array of strings, I created a method that just takes an array of strings and still invoked in the same way that Jawin was doing. And guess what? It worked! So, why does the typebrowser create the Variant method in the first place?

I wish the Jawin folks would continue to work on their project and get some of these bugs fixed. It's a great product with a lot of hope, but it needs help and it needs to be more user friendly to those java folks out there who don't know COM.

Friday, June 6, 2008

"Secure and Insecure Items" Warning on every page in Internet Explorer

Problem: Users connecting to the application using SSL get the mixed content "This page contains secure and insecure items" warning message on every page in the application. This issue is only happening with 2 users of the system, both are using Internet Explorer Version 7. One user also reports problems opening PDF files.

Troubleshooting: The users are up to date on their Windows patches. Internet Explorer is up to date. Adobe Acrobat Reader is up to date on the system of the user with the PDF issues.

The next thing to try is a suggestion from Microsoft.

Stay tuned...

UPDATE, June 10: The users unchecked the "show mixed content" setting in their IE Settings. This is not recommended as it is a security hole, but it's the best we could do.

Wednesday, May 21, 2008

JasperReports failure to download PDF in Internet Explorer

What is supposed to happen: We have a PDF document being generated using JasperReports in a struts-based Java application. The PDF writes to the screen, where the user is prompted to open or save this generated PDF file. Usually, the user clicks "open" and views the file.

What is happening: When Internet Explorer goes to display the Open/Save/Cancel dialogue box, it instead displays a warning message: "Internet Explorer cannot download document.pdf from server"

Notes:
  • This is not the only place in the application where a PDF is generated in Jasper and written to an output stream. The other PDFs are working, although each has subtle differences here and there as to how they are generated. Nothing that is different is causing the problem.
  • This application was recently converted to SSL, and the issue appears the be happening only on the SSL version for MOST but not ALL affected users.
  • Not all users are affected, some can access without problems. In addition, some users (including myself) get the error in one environment and not another, with the same codebase.

Investigation:

I read up on a few sites:
  1. Microsoft lists this as a bug in IE and offers several suggestions. My Do not save encrypted pages to disk check box is not checked.
  2. This big thread offers more suggestions about response headers. I have tried each of these.
  3. Another thread. More of the same.

I've tried changing the headers. Original code:


response.setHeader("Content-Disposition", "attachment; filename=Preview.pdf");
response.addHeader("Content-Description", "Download");
response.setContentType("application/pdf");


New code:


response.setHeader("Content-Length", String.valueOf(file.length));
response.setHeader("Content-Disposition", "attachment; filename=Preview.pdf");
response.addHeader("Content-Description", "Download");
response.setContentType("application/pdf");
response.setHeader("Pragma", "public");
response.setHeader("Cache-control", "must-revalidate");


No luck. I've tried loading the headers in various orders, and I've tried various header values, including blank for pragma and cache-control, and other values. No luck.

So, I'm still working.

Resolution, May 22, 2008:
The problem is fixed and has nothing to do with anything mentioned here. There was a silly block of formerly unreachable code that was now reachable, either due to a novice programmer making changes or the Websphere upgrade from 6.0 to 6.1. This code, I kid you not, removed the attachment and reset the HTTP status to 404. I never saw this code yesterday when I was working on this, but I do feel kind of stupid now.

Tuesday, May 6, 2008

Windows Environment Variables: Solved

Some of you may recall this issue that I was having with Windows Environment Variables not resolving properly on my servers. Today, on the verge of launching a shiny new production server (supposed to happen this weekend, more likely next weekend), I have resolved the issue.

The solution comes from here, but requires more explanation.

If you are experiencing this problem, you are apparently setting your environment variables by right clicking on My Computer, selecting Properties & going to the advanced tab. Not correct. You need to right click on my computer and select MANAGE, go to advanced, and set the environment variables there. I tried this months ago, but apparently if you're already experiencing the issue, just resetting the environment variables there won't work. You need to delete them and recreate them in the Manage screen, including your Path variable.

Thank goodness, that one was a real bother.

Tuesday, April 29, 2008

IBM HTTP Server Certificate Resources

More troubles with IBM HTTP Server Certificates. We have one physical server, with an IBM HTTP Server and one physical instance of Websphere 6.1 running. I want requests to come in through 2 separate URLs, be routed to the one HTTP Server, then sent to the proper App Server node (same application context though) based on the URL/Virtual Host. AND, I want all of this to happen with SSL. Fun, huh?

I wanted to share more links that I found that helped me out...

I've also once again had difficulty with WSAdmin and SSL... make sure that if you're having certificate issues with WSAdmin (or starting and stopping Websphere) to run it from the command line and not some other way. It will show you the output of the certificate and allow you to install it. If only the plugin behaved this way.

Wednesday, April 2, 2008

Setting up Acegi, CAS, Kerberos/SPNEGO and Websphere 6.1 Part TWO

Continued from part one


Step Four: Setup IBM HTTP Server and Websphere Plugin to Websphere Server 6.1

In order to prepare for SSL on Websphere, a web server front end should be used. Apache, IIS, etc can all be used, however IBM HTTP Server is the easiest setup and comes installed with WAS. Documentation for this setup is surprisingly unclear and difficult to locate. If you are unfamiliar with WAS or unfamiliar with this type of setup, you may be at a loss of even knowing where to start. Here are some hints.

  1. IBM HTTP Sever and Websphere Plugin is installed with WAS 6.1 by default.
  2. Most of the installation and configuration for the webserver can be done through the Websphere Administrative Console under Servers à Webservers.
  3. Create the new Web Server through the admin console, make sure you can access it, and make sure that WAS can connect to the HTTP Server administrator.
  4. If you are familiar with Apache Web Server, IBM HTTP Server is based off of Apache. So, Apache documentation may be helpful if changes need to be made to the httpd.conf file.
  5. Once you've got the HTTP Server up and running, generate the plug in file and propagate the plug in file to the HTTP Server.

Gotchas:

  • If you are setting up SSL, just get the web server running first. It's helpful to use WAS's snoop servlet to test the configuration.
  • If your app is already installed, you will need to map the module to the server. Do this from the Admin Console, Applications à Your Application à Manage Modules. You will see your app, and you should see your web server in the server column. If not, you can map it on that screen.
  • When setting up CAS on Websphere, if you access the CAS login screen, you may get a JSP error. Details of this can be found here and the solution provided worked. Yes, you will need to rebuild CAS.
Step Five: Setup SSL on Websphere 6.1

Setting up SSL on Websphere is a nightmare compared to setting up SSL on Tomcat. Very helpful in the SSL setup process was the following document: SSL, certificate, and key management enhancements for even stronger security in WebSphere Application Server V6.1. Otherwise, documentation of setting up SSL on Websphere was very hard to find. The server was set up with a self-signed certificate in the development environment. Like web servers, certificates can be generated and managed in WAS's Admin Console, under Security à SSL certificate and key management. For CAS and Acegi to work properly, there needs to be trust at every level – between the web server and the app server and vice versa, and between your application and CAS.

For this project, first SSL was set up on Websphere in order to make CAS available via SSL. CAS was deployed onto the Websphere server, and was accessed via the HTTP Server. The application itself was still running on Tomcat locally, but the CAS URLs were changed from the Local CAS to the Websphere (remote) CAS. On the HTTP Server side, a Virtual Host needed to be set up (through WAS Admin Console) linking the 443 port from the app server to the web server. A key store had to be specified at this point.

Also under the web server, a global directive needed to be specified with the (server IP Address):443 as the listen port. A key store had to be specified here as well. When setting these up through the admin console, WAS will automatically generate and regenerate the httpd.conf file. If in doubt, also regenerate the plug in file and populate it down to the HTTP server. Restart the HTTP server after these changes are made.

Gotchas:

  • When in doubt, if you are getting a "unable to find valid certification path to requested target" error, use the utility provided here to resolve the issue.
  • While most documentation regarding CAS and Acegi setup suggest using cacerts as a truststore, Websphere will occasionally throw errors when doing this. Either use one of the p12 format truststore/keystores or comment out the truststore variable all together.
  • This is a difficult process. Turn on Websphere tracing and pay attention to Websphere error logs to work out all of the problems.

Step Six: Set up CAS for SPNEGO / Kerberos Authentication

This step goes hand in hand with Step five, and they can be done together. JA-SIG already has some excellent documentation on setting up SPNEGO. If all of the steps are followed, you should be able to log into CAS without a login screen. Like with the Websphere SPNEGO setup, you will have to make sure that your client browser is properly configured.

Gotchas:

  • None! This works cleanly out of the box.


Step Seven: Install Application with Acegi and access CAS with SPNEGO.

Once all of the previous steps are complete, the final step is to install the application and access CAS for logging in without interaction.

Gotchas:

  • Since Acegi requires filtering on URLs where the page does not actually exist, Websphere 6.1 will not handle this properly. To fix this, a custom property in the Web Container must be set. The property is com.ibm.ws.webcontainer.invokefilterscompatibility and it should be set to true. More details can be found here.
  • CAS would not authenticate properly with Websphere version 6.1.0.13. Upgrading to 6.1.0.15 did resolve the issue.

Friday, March 28, 2008

Setting up Acegi, CAS, Kerberos/SPNEGO and Websphere 6.1 Part ONE

This article assumes a basic understanding of Acegi Security System for Spring, Central Authentication Service (CAS), Kerberos/SPNEGO and Websphere Application Server 6.1. Acegi was used for the authorization of users and access to protected pages, and CAS was used for authorization of users using a transparent / non-interactive login using Kerberos and SPNEGO.

For more information on any of these products, please see:

Websphere Application Server does come with a Single Sign-on package, but it was decided not to use this for several reasons:

    1. While WAS will use Kerberos and some Websphere setup is required, a full Websphere implementation would have required more use of proprietary IBM code than was necessary.
    2. CAS will handle requests and allow set up with very few code changes. In addition, Acegi contains plugins for CAS, and it was relatively easy to get the two to work together (adding Websphere into the mix was the true difficulty).
    3. Developers will be using an Eclipse/Tomcat combination for development, and therefore will not be able to use proprietary Websphere code.
    4. Documentation for Websphere’s proprietary code was lacking.

This project was to replace a jCifs/Acegi security implementation, so the Acegi part of the application was already written and did not require a great deal of configuration. This document is meant to explain the steps that were taken to set up the infrastructure.

Step One: Install CAS – Tomcat

CAS Server 3.1.1 was used and installed on Tomcat. CAS can be downloaded from the CAS Download Page. The basic setup was used, which allowed users on Tomcat to authenticate on the login page as long as the username matched the password that was entered.

Gotchas:

  • SSL had to be enabled on Tomcat. There are many guides for how to do this (including some guides created by CAS users), but by far the best and most easy to follow was the SSL How-To Located on Apache’s Website.

Step Two: Integrate Acegi with CAS on Tomcat

Step-by-step documentation for how to install Acegi in your app and use it with CAS can be found in the Acegi help guide. There are instructions for setting up Acegi with CAS using both CAS version 2 and CAS Version 3, but if Kerberos / SPNEGO is going to be used, it is best to go with CAS Version 3. The easiest setup is to use contacts-cas.war as an example. This can be found in older versions of Acegi, but cannot be found in the current version of Acegi. At this point, you should be able to log into CAS using the userid=password list that was standard in the InMemoryDaoImpl found in the help guide.

Gotchas:

  • Not being very familiar with Spring, I had difficulty getting the application to start after my initial setup. My application-context was setup improperly, causing the startup to fail. Check your application-context carefully before deployment.
  • SSL MUST be used at this point.

Step Three: Setup Kerberos / SPNEGO on Websphere 6.1

The best documentation for setting up Kerberos/SPNEGO on Websphere can be found in the Techdoc by IBM: Websphere with SPNEGO: Configuring SPNEGO in Websphere Environments. Following the instructions in this document will completely set up the security that is necessary on the Websphere side. At this point, if you are brave enough to integrate Acegi directly with WAS, you can do so.

Gotchas:

  • The way the document is worded and set up, it will turn on Java 2 security in Websphere. If this is desired, great. If not, many applications may not run. There are two options here: 1) Add .policy files to specify what applications have the rights to do what (you can do this using the was.policy found in ${WAS_HOME}/profiles/default/properties or in the java.policy file found at ${WAS_HOME}/java/jre/lib/security). 2) Uncheck the checkbox labeled “Use Java 2 security to restrict application access to local resources” box found in the admin console under Security -> Secure administration, applications, and infrastructure. This is the easisest way and is recommended if this type of security is not a concern. Of course, it will allow your applications to run wild, accessing all kinds of resources and wreaking havoc all over the place. If you are interested instead in editing policy files, documentation is hard to find, but some documentation can be found on Sun’s Website.
  • The client’s browser requires setup in order to send the Kerberos token through in the header. Information for doing this can be found in the Techdoc listed above, but can also be found elsewhere on the web.
to be continued... Continue to Part Two

Friday, March 7, 2008

CAS: My newest project...

Central Authentication Service
This is what I'm working on. I used to work with Siteminder, now it's CAS. Interesting stuff...