May 12 10

Here’s a pretty neat approach to add AccessDescisionVoters to the default AccessDescisionManager in Spring Security:

/**
 * This BeanPostProcessor adds all {@link AccessDecisionVoter}s that are set with
 * {@link #setAdditionalAccessDecisionVoters(List)} to beans that are instances of {@link AffirmativeBased}. This is the
 * default {@link AccessDecisionManager} implementation that the spring security namespace handler creates.
 * <p>
 *
 * The configuration could look like:
 *
 * <pre>
 * {@code
 * <bean id="voterAdder">
 *   <property name="additionalAccessDecisionVoters">
 *     <list>
 *       <bean />
 *     </list>
 *   </property>
 * </bean>
 * }
 * </pre>
 */
@Component
public class VoterAdder implements BeanPostProcessor {
  private List<AccessDecisionVoter> additionalAccessDecisionVoters;

  public void setAdditionalAccessDecisionVoters(List<AccessDecisionVoter> additionalAccessDecisionVoters) {
    this.additionalAccessDecisionVoters = additionalAccessDecisionVoters;
  }

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof AffirmativeBased) {
      AffirmativeBased dm = (AffirmativeBased) bean;
      additionalAccessDecisionVoters.addAll(dm.getDecisionVoters());
      dm.setDecisionVoters(additionalAccessDecisionVoters);
    }
    return bean;
  }
}

Source: http://forum.springsource.org/showthread.php?116830-How-to-add-voters-to-the-default-accessDecisionManager&s=1a6d05dedb0342570b900141a6d53d2e&p=386079#post386079

Apr 12 18
  final Image image = ...;
  final ByteArrayOutputStream baos = new ByteArrayOutputStream();
  try {
    final BufferedImage bufferedImage = createBufferedImageFrom(image);
    ImageIO.write(bufferedImage, "png", baos);
  } finally {
    IOUtils.closeQuietly(baos);
  }
  return baos.toByteArray();

private BufferedImage createBufferedImageFrom(final Image image) {
  if (image instanceof BufferedImage) {
    return (BufferedImage) image;
  } else {
    final BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null),
        BufferedImage.TYPE_INT_RGB);
    final Graphics2D g2 = bi.createGraphics();
    g2.drawImage(image, 0, 0, null);
    return bi;
  }
}

If you don’t want to make use of IOUtils from Apache Commons Lang, you should you know, the code in the finally block would be something like

try {
  if (baos != null) {
    baos.close();
  }
} catch (IOException ioe) {
  // ignore
}
Dec 11 23

Recently I tried to use dnsjava to resolve whatever address request.getRemoteAddr() would return. This worked very well in most cases. However, in some cases I would see something like:

java.net.UnknownHostException: Invalid address: fe80::1d9:b65a:ed86:7940%11

Not being much of a networking expert I was puzzled about the ‘%11′. Once again superuser.com came to rescue:  http://superuser.com/questions/99746/why-is-there-a-in-the-ipv6-address.

Nov 11 19

At the technical panel discucssion on Friday morning at Devoxx there was the interesting question “Does Oracle’s corporate culture stand in the way of success for Java?”. Even more interesting was the answer from either Brian Goetz or Mark Reinold (don’t remember), both big wings at Oracle…

“I think Java became a success despite Sun’s corporate culture. Priorities at Sun changed quite rapidly from time to time. At Oracle it takes longer to make a plan but then with stick with it” (something along the lines of that)

Aug 11 06

Creating a DDL in the Maven build with the hibernate3-maven-plugin fails if you explicitly configure an array of javax.persistence.CascadeType values in your JPA annotations. The stacktrace is similar to

javax.persistence.PersistenceException: [PersistenceUnit: spontacts] Unable to configure EntityManagerFactory
	at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:265)
	at org.codehaus.mojo.hibernate3.configuration.JPAComponentConfiguration.createConfiguration(JPAComponentConfiguration.java:28)
...
Caused by: java.lang.ArrayStoreException: sun.reflect.annotation.EnumConstantNotPresentExceptionProxy
	at sun.reflect.annotation.AnnotationParser.parseEnumArray(AnnotationParser.java:673)
	at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:462)

Once I realized what the actual cause is, the fix was simple. Turns out that the CascadeType is not in the classpath when Maven runs the hbm2ddl goal. Hence you need to add a dependency to JPA to the hibernate3-maven-plugin:

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>hibernate3-maven-plugin</artifactId>
	<dependencies>
		<dependency>
			<groupId>org.hibernate.javax.persistence</groupId>
			<artifactId>hibernate-jpa-2.0-api</artifactId>
			<version>1.0.0.Final</version>
		</dependency>
	</dependencies>
	<executions>
		...
	</executions>
	<configuration>
		...
	</configuration>
</plugin>

A solution to this exception in a different context was posted here: http://javahowto.blogspot.com/2008/10/solve-javalangarraystoreexception.html

Apr 10 05

When you need to support self-signed SSL certificates in your Apache HttpClient based application you can use the contributed EasySSLProtocolSocketFactory as described in the HttpClient docs.

Instead of using HttpClient’s HostConfiguration object directly you’d modify its protocol socket factory in your code like so:

...
if (config.isAllowSelfSignedCertificates()) {
  ProtocolSocketFactory factory = new EasySSLProtocolSocketFactory();
  try {
    URI uri = new URI(config.getBaseUrl());
    int port = uri.getPort();
    if (port == -1) {
      port = 443;
    }
    Protocol easyHttps = new Protocol(uri.getScheme(), factory, port);
    hostConfiguration.setHost(uri.getHost(), port, easyHttps);
  } catch (URISyntaxException e) {
    throw new IOException("could not parse URI " + config.getBaseUrl(), e);
  }
}
...

Somewhere you’d instantiate a HttpClient object. Then you get its host config through HttpClient#getHostConfiguration() – I stored this in the hostConfiguration variable. The if, the config variable, checking for port, etc. is all my own code and has nothing to do with HttpClient directly.

There is one caveat, though! Never use absolute URIs against the HttpClient 3.x with the EasySSLProtocolSocketFactory in place! If you did you’d get the dreaded

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I found that the HttpClient 3.x has the following code in its executeMethod() method:

...
if (hostconfig == defaulthostconfig || uri.isAbsoluteURI()) {
  // make a deep copy of the host defaults
  hostconfig = (HostConfiguration) hostconfig.clone();
  if (uri.isAbsoluteURI()) {
      hostconfig.setHost(uri);
  }
}
...

So, in my case (absolute URI) the modified host config (uses EasySSLProtocolSocketFactory) is cloned.

Problem: since the so called “deep copy” isn’t a proper deep copy the copy’s protocol’s socket factory is no longer EasySSLProtocolSocketFactory but the standard SSLProtocolSocketFactory instead!

Update

Apparently, this behavior is “well known and documented”. Since I couldn’t find anything in the HttpClient 3.x documentation I tried Google again and made note of the following JIRA issues and one particular mailing list entry:

Please note that HttpClient 4.x does not have this limitation!