Tuesday, April 3, 2012

NClass - Free UML Class Designer



If you are ever looking for a nice UML class designer look no further than NClass. I used this for a project to port a large code base from .NET to Java. The program was able to reverse engineer UML from compiled .NET code. Love it.

Thursday, March 29, 2012

A Spiritual Feast

I am excited for the 2012 LDS spring conference sessions.

Come listen to living prophets


Come listen to living prophets

You can listen or watch them for free online. Consider accepting my invitation to attend conference and pull up your own chair to a spiritual feast.

Friday, March 23, 2012

Performance settings for production weblogic deployments

Put this in the weblogic.xml under WEB-INF folder: 
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN" "http://www.oracle.com/technology/weblogic/servers/wls810/dtd/weblogic810-web-jar.dtd">

<weblogic-web-app>

<container-descriptor>
<servlet-reload-check-secs>-1</servlet-reload-check-secs>
</container-descriptor>

</weblogic-web-app>

For JSPs you can also set this in weblogic.xml:

<jsp-descriptor>
<jsp-param>
<param-name>pageCheckSeconds</param-name>
<param-value>-1</param-value>
</jsp-param>
</jsp-descriptor>


Unless you are altering servlet code and JSPs on the fly in production (bad idea), there is no need to ever check for changes. These two settings can help with performance because without them, Weblogic will have periodic threads blocking
requests to poll the filesystem for Servlet or JSP changes.

So by default in thread dumps you will see one or more of this sort of thing:

waiting for monitor entry [c4f7f000..c4f7fc28]
     at weblogic.servlet.internal.ServletStubImpl.checkForReload(ServletStubImpl.java:771)

unless you disable that like shown above.

Monday, March 5, 2012

8 reasons why your browser does NOT send the cookie as part of the request

There are several reasons why a cookie you attempted to set on a remote client browser as part of a HTTP response is NOT sent back on the next request:
  1. The domain of the request does not match the cookie's domain attribute
  2. The path of the request does not match the cookie's path attribute
  3. The cookie has expired
  4. The cookie was set the secure attribute and the client's request was plain text HTTP.
  5. The cookie was set with the httpOnly attribute and the client's request was not HTTP/HTTPS (e.g. you used FTP).
  6. The client has disabled cookies globally or specifically for your domain.
  7. The client deleted or cleared the cookie that was set before the next request was made.
  8. The client's browser does not trust the SSL certificate used to sign your site and you are trying to use HTTPS communication.
Your domain of the request does not match the cookie's domain attribute
This one appears to be the most obvious of them all but does have a small gotcha. A cookie set for domain www.google.com will not be sent for a request to www.yahoo.com. We can understand that, but it will also not be sent for mail.google.com! The domain mail.google.com does not match www.google.com, so cookies set on one do not affect requests for the other. So when setting cookies that should be sent for all sub-domains: use .domain.com as the cookie's domain attribute, i.e. leave off the sub-domain (www) and just lead with the . prefix.

Your path of the request does not match the cookie's path attribute
If you set the path to /, all paths on the domain are going to send the cookie with the request, even if the request is for an image.. So use path wisely to avoid unnecessary overhead in your requests, especially if you are a heavy user of cookies. you only get one cookie path, make it count. You will be ding'd on Yslow if you don't avoid sending cookie info for images.

Your cookie has expired
Duh. Don't expect old cookies to join your request party. Be careful of short expiration on cookies, they may go stale before they are even set.

Your client has disabled cookies globally or for your specific domain
This is why it is important to document the requirements for your application. If you need cookies enabled (or even better detect that cookies are not enabled), tell the user to enable them (and how to enabled them) in a big red alert box with a flashing siren.


This is my list, do you have other reasons to add?





Thursday, February 16, 2012

Java little endian IO gotcha

Java's goal has been to provide developers with a language that is cross platform, write once run everywhere. To do this Java handles many platform details for you. But sometimes those details are important. Here is an example, I needed to output a TIFF using little-endian byte ordering regardless of what platform the Java code was running on.

import java.io.FileOutputStream;

byte[] imgData = //create the image data using JAI;
String filename = "platform-endian.tiff";

FileOutputStream fos = new FileOutputStream(filename);
fos.write(imgData);
fos.close();

My code would work fine on platforms with Intel or x86 architecture which is little-endian byte order, but when I moved my code to a Solaris system running a SPARC processor, my code started outputting in big-endian TIFFs. This is due to the fact that FileOutputStream hides some of the complexity involved with writing data out to disk. Hiding this complexity is fantastic if all you care about are outputting TIFFs that are byte-order-compatible with the environment your Java code is running in; which is what you would want in 99% of the use cases for creating TIFFs programmatically. But this feature of Java is very bad when you always need little-endian TIFFs at all times. I need little-endian because it is a Federal Reserve regulations are that the TIFFs I make be little-endian.

Thankfully there is a way to force Java to use a specific byte ordering. Use ByteBuffer.

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.io.FileOutputStream;

byte[] imgData = //create the image data using JAI;
String filename = "little-endian.tiff";

ByteBuffer buffer = ByteBuffer.allocate(imgData.length);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.put(imgData);
out = new FileOutputStream(filename).getChannel();
out.write(buffer);

This code will output directly in little-endian regardless of the architecture of the system running the code.


Thursday, January 26, 2012

Java static initialization gotcha

If you have a class which has a singleton instance of itself as a static member, and also use a static inititialization block, then you can run into an issue with initialization like I did where static final members are null.
01 import java.util.*;
02
03 class MySingletonClass {
04 private static final instance = new MySingletonClass();
05 private static final List MY_STRINGS;
06 static {
07 MY_STRINGS = new ArrayList();
08 }
09 public MySingletonClass() {
10 System.out.println("MY_STRINGS: "+MYSTRINGS);
11 }
12 }

The above will throw a NullPointer Exception on line 10 because the MySingletonClass constructor is called BEFORE the static initialization block is executed. So change it to this:
01 import java.util.*;
02
03 class MySingletonClass {
04 private static final instance;
05 private static final List MY_STRINGS;
06 static {
07 MY_STRINGS = new ArrayList();
08 instance = new MySingletonClass();
09 }
10 public MySingletonClass() {
11 System.out.println("MY_STRINGS: "+MYSTRINGS);
12 }
13 }

Now the instance static member variable is not created until AFTER the other static member is initialized. So the constructor can correctly execute the print statement.

Tuesday, January 24, 2012

Use package-info.java for all your package level annotation needs

I had a problem, I needed to annotate all the occurrences of java.sql.Timestamp with an XmlJavaTypeAdapter for all classes in a Java package. For example I needed this done in dozens of generated source files:

@XmlJavaTypeAdapter(com.fourgablesguy.dao.hibernate.util.TimestampAdapter.class)
public Timestamp getCreateTs() {
return this.createTs;
}

The TimestampAdapter class is the following:
package com.fourgablesguy.dao.hibernate.util;

import java.sql.Timestamp;
import java.util.Date;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class TimestampAdapter extends XmlAdapter {

@Override
public Date marshal(Timestamp v) throws Exception {
return new Date(v.getTime());
}

@Override
public Timestamp unmarshal(Date v) throws Exception {
return new Timestamp(v.getTime());
}

}


The reason I needed this done is because Timestamp does not have a public no-arg constructor and XStream could not marshall objects containing Timestamp objects. The nice solution to annotating these is to use package-info.java, you place this file in the same folder as the source java files, but it is not a typical source file. Here is the contents of my package-info.java:
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters
({
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value=com.fourgablesguy.dao.hibernate.util.TimestampAdapter.class,type=java.sql.Timestamp.class)
})
package com.myama.dao.hibernate;

This package-info file is used by Java to annotate all classes in a package, with this single file my problem was resolved. My TimestampAdapter allowed me to marshall Timestamp objects with XStream. I used fully qualified names of classes in the package-info since I was not clear if you could import packages or if you had package access to the enclosing namespace.

About Me

My photo
Lead Java Developer Husband and Father

Tags