Matias Blog
Sunday, November 13, 2022
Saturday, September 25, 2010
Windows has sym links!
Here is a little known (at least to me) fact about Windows Vista and Windows 7: they support symbolic links!
The command you need to use for this is mklink, and here is the syntax:
Creates a symbolic link.
MKLINK [[/D] | [/H] | [/J]] Link Target
/D Creates a directory symbolic link. Default is a file symbolic link.
/H Creates a hard link instead of a symbolic link.
/J Creates a Directory Junction.
Link specifies the new symbolic link name.
Target specifies the path (relative or absolute) that the new link refers to.
Here is an example of a soft link for a directory:
>mklink /d linkdir1 dir1
symbolic link created for linkdir1 <<===>> dir1
which comes up clearly noted in a directory listing from the command prompt
09/25/2010 12:59 AM <dir> dir1
09/25/2010 12:59 AM <symlinkd> linkdir1 [dir1]
as well as in the Windows explorer, by means of an icon overlay.
You need admin privileges to create such a link, unless you edit the Local Security Policies and add the Create Symbolic Link privilege.
This is a junction for a directory:
>mklink /j junctiondir1 dir1
Junction created for junctiondir1 <<===>> dir1
Again, clearly noted from the command prompt:
09/25/2010 12:59 AM <dir> dir1
09/25/2010 01:01 AM <junction> junctiondir1 [C:\...\dir1]
and identified in Windows graphical interface by the same icon overlay as the soft link case
A junction is a directory hard link.
Beware to delete directory links with rmdir, as del will delete the contents instead of the link! Also, deleting the original directory breaks both the symlink and the junction!
Here is a soft link for a file:
>mklink linkfile.txt file1.txt
symbolic link created for linkfile.txt <<===>> file1.txt
Showing up in the command prompt as:
09/25/2010 01:22 AM <symlink> linkfile.txt [file1.txt]
and with the same icon overlay as for directories in Windows explorer
And this is a hard link for a file:
>mklink /h hardlinkfile.txt file1.txt
Hardlink created for hardlinkfile.txt <<===>> file1.txt
Notice how you cannot tell from the command prompt:
09/25/2010 01:23 AM 32 hardlinkfile.txt
or from the Windows shell, since there is no icon overlay
Now, deleting the original file will break the soft link but not affect the hard link
So, recapping:
mklink name target
mklink /h name target
mklink /d name target
mklink /j name target
One last note (I tried this in Windows Vista): if you move the links (not the original files/directories) to another location, junctions and hard links keep working, while directory and file soft links break.
Enjoy - I know I like this!
The command you need to use for this is mklink, and here is the syntax:
Creates a symbolic link.
MKLINK [[/D] | [/H] | [/J]] Link Target
/D Creates a directory symbolic link. Default is a file symbolic link.
/H Creates a hard link instead of a symbolic link.
/J Creates a Directory Junction.
Link specifies the new symbolic link name.
Target specifies the path (relative or absolute) that the new link refers to.
Here is an example of a soft link for a directory:
>mklink /d linkdir1 dir1
symbolic link created for linkdir1 <<===>> dir1
which comes up clearly noted in a directory listing from the command prompt
09/25/2010 12:59 AM <dir> dir1
09/25/2010 12:59 AM <symlinkd> linkdir1 [dir1]
as well as in the Windows explorer, by means of an icon overlay.
You need admin privileges to create such a link, unless you edit the Local Security Policies and add the Create Symbolic Link privilege.
This is a junction for a directory:
>mklink /j junctiondir1 dir1
Junction created for junctiondir1 <<===>> dir1
Again, clearly noted from the command prompt:
09/25/2010 12:59 AM <dir> dir1
09/25/2010 01:01 AM <junction> junctiondir1 [C:\...\dir1]
and identified in Windows graphical interface by the same icon overlay as the soft link case
A junction is a directory hard link.
Beware to delete directory links with rmdir, as del will delete the contents instead of the link! Also, deleting the original directory breaks both the symlink and the junction!
Here is a soft link for a file:
>mklink linkfile.txt file1.txt
symbolic link created for linkfile.txt <<===>> file1.txt
Showing up in the command prompt as:
09/25/2010 01:22 AM <symlink> linkfile.txt [file1.txt]
and with the same icon overlay as for directories in Windows explorer
And this is a hard link for a file:
>mklink /h hardlinkfile.txt file1.txt
Hardlink created for hardlinkfile.txt <<===>> file1.txt
Notice how you cannot tell from the command prompt:
09/25/2010 01:23 AM 32 hardlinkfile.txt
or from the Windows shell, since there is no icon overlay
Now, deleting the original file will break the soft link but not affect the hard link
So, recapping:
mklink name target
- creates a file soft link
- appears in the cmd prompt as <symlink>
- has an icon overlay (a little arrow as in shortcuts) in the Windows shell
mklink /h name target
- creates a file hard link
- appears in the cmd prompt as any other file (works as full-fledged file and remains if you delete the original)
- has no icon overlay (behaves like any other file)
mklink /d name target
- creates a directory soft link
- appears in the cmd prompt as <symlinkd>
- has an icon overlay (a little arrow as in shortcuts) in the Windows shell
mklink /j name target
- creates a directory hard link (although deleting the original location actually renders the link unsable)
- appears in the cmd prompt as <junction>
- has an icon overlay (a little arrow as in shortcuts) in the Windows shell
One last note (I tried this in Windows Vista): if you move the links (not the original files/directories) to another location, junctions and hard links keep working, while directory and file soft links break.
Enjoy - I know I like this!
Wednesday, September 15, 2010
Double dispatch to solve compile method resolution issues in Java
I usually don't chain posts, but it was going to be very long so... this post is a continuation of the previous one.
Here's how to use double dispatch for the compile time method resolution case. Note that the doubleDispatch method must be defined both for Mammal and for Dog.
public class OverloadingExamples {
public static class Mammal {
public void sayHello() {
System.out.println("Hi, I'm a mammal!");
}
public void doubleDispatch(OverloadingExamples example) {
example.makeSayHello(this);
}
}
public static class Dog extends Mammal {
@Override
public void sayHello() {
System.out.println("Hi, I'm a mammal - in fact I'm a dog!");
}
@Override
public void doubleDispatch(OverloadingExamples example) {
example.makeSayHello(this);
}
}
private Dog getADog() {
return new Dog();
}
public void runExample() {
Mammal aMammal = getADog();
System.out.println("Run time method resolution");
aMammal.sayHello();
System.out.println();
System.out.println("Double dispatch resolutions");
aMammal.doubleDispatch(this);
Dog aDog = (Dog) aMammal;
aDog.doubleDispatch(this);
}
public void makeSayHello(Mammal aMammal) {
System.out.println("Compile time method resolution for a MAMMAL");
System.out.print("Corresponding run time method resolution: ");
aMammal.sayHello();
}
public void makeSayHello(Dog aDog) {
System.out.println("Compile time method resolution for a DOG");
System.out.print("Corresponding run time method resolution: ");
aDog.sayHello();
}
public static void main(String args[]) {
new OverloadingExamples().runExample();
}
}
Now here's the output:
Run time method resolution
Hi, I'm a mammal - in fact I'm a dog!
Double dispatch resolutions
Compile time method resolution for a DOG
Corresponding run time method resolution: Hi, I'm a mammal - in fact I'm a dog!
Compile time method resolution for a DOG
Corresponding run time method resolution: Hi, I'm a mammal - in fact I'm a dog!
And the makeSayHello(Mammal) implementation was not used.
Here's how to use double dispatch for the compile time method resolution case. Note that the doubleDispatch method must be defined both for Mammal and for Dog.
public class OverloadingExamples {
public static class Mammal {
public void sayHello() {
System.out.println("Hi, I'm a mammal!");
}
public void doubleDispatch(OverloadingExamples example) {
example.makeSayHello(this);
}
}
public static class Dog extends Mammal {
@Override
public void sayHello() {
System.out.println("Hi, I'm a mammal - in fact I'm a dog!");
}
@Override
public void doubleDispatch(OverloadingExamples example) {
example.makeSayHello(this);
}
}
private Dog getADog() {
return new Dog();
}
public void runExample() {
Mammal aMammal = getADog();
System.out.println("Run time method resolution");
aMammal.sayHello();
System.out.println();
System.out.println("Double dispatch resolutions");
aMammal.doubleDispatch(this);
Dog aDog = (Dog) aMammal;
aDog.doubleDispatch(this);
}
public void makeSayHello(Mammal aMammal) {
System.out.println("Compile time method resolution for a MAMMAL");
System.out.print("Corresponding run time method resolution: ");
aMammal.sayHello();
}
public void makeSayHello(Dog aDog) {
System.out.println("Compile time method resolution for a DOG");
System.out.print("Corresponding run time method resolution: ");
aDog.sayHello();
}
public static void main(String args[]) {
new OverloadingExamples().runExample();
}
}
Now here's the output:
Run time method resolution
Hi, I'm a mammal - in fact I'm a dog!
Double dispatch resolutions
Compile time method resolution for a DOG
Corresponding run time method resolution: Hi, I'm a mammal - in fact I'm a dog!
Compile time method resolution for a DOG
Corresponding run time method resolution: Hi, I'm a mammal - in fact I'm a dog!
And the makeSayHello(Mammal) implementation was not used.
Run time and compile time method resolution in Java
This post is thanks to a colleague at work.
Suppose you have a class Dog and a class Mammal it inherits from. Both have a method sayHello().
public static class Mammal {
public void sayHello() {
System.out.println("Hi, I'm a mammal!");
}
}
public static class Dog extends Mammal {
@Override
public void sayHello() {
System.out.println("Hi, I'm a mammal - in fact I'm a dog!");
}
}
If you were to call sayHello() on an instance of Dog which is declared (to the compiler) as a Mammal:
private Dog getADog() {
return new Dog();
}
public void runExample() {
Mammal aMammal = getADog();
System.out.println("Run time method resolution");
aMammal.sayHello();
.......
This would print:
Run time method resolution
Hi, I'm a mammal - in fact I'm a dog!
No surprises there, just a virtual method.
But now, suppose you have:
public void makeSayHello(Mammal aMammal) {
System.out.println("Compile time method resolution for a MAMMAL");
System.out.print("Corresponding run time method resolution: ");
aMammal.sayHello();
}
public void makeSayHello(Dog aDog) {
System.out.println("Compile time method resolution for a DOG");
System.out.print("Corresponding run time method resolution: ");
aDog.sayHello();
}
and in the example you call:
public void runExample() {
Mammal aMammal = getADog();
System.out.println("Run time method resolution");
aMammal.sayHello();
System.out.println();
System.out.println("Compile time method resolutions");
makeSayHello(aMammal);
Dog aDog = (Dog) aMammal;
makeSayHello(aDog);
}
aMammal is always the same object - a dog. In the second occurence, it's explicity cast as such.
Will both calls to makeSayHello use the makeSayHello(Dog aDog) method?
No - the first call will use makeSayHello(Mammal aMammal). Why? Because when it comes to method parameters, the resolution of overloaded methods is done at compile time. Otherwise stated, when overriding methods the 'closest' version will we used, by virtue of virtuality (pardon the repetition). When overloading methods, the version called will be the one that matches the compile time declaration of the parameter.
Note that the calls to aMammal.sayHello() and aDog.sayHello() in the respective makeSayHello() methods will call the Dog implementation (here we are using method overriding again).
The complete example follows:
public class OverloadingExamples {
public static class Mammal {
public void sayHello() {
System.out.println("Hi, I'm a mammal!");
}
}
public static class Dog extends Mammal {
@Override
public void sayHello() {
System.out.println("Hi, I'm a mammal - in fact I'm a dog!");
}
}
private Dog getADog() {
return new Dog();
}
public void runExample() {
Mammal aMammal = getADog();
System.out.println("Run time method resolution");
aMammal.sayHello();
System.out.println();
System.out.println("Compile time method resolutions");
makeSayHello(aMammal);
Dog aDog = (Dog) aMammal;
makeSayHello(aDog);
}
public void makeSayHello(Mammal aMammal) {
System.out.println("Compile time method resolution for a MAMMAL");
System.out.print("Corresponding run time method resolution: ");
aMammal.sayHello();
}
public void makeSayHello(Dog aDog) {
System.out.println("Compile time method resolution for a DOG");
System.out.print("Corresponding run time method resolution: ");
aDog.sayHello();
}
public static void main(String args[]) {
new OverloadingExamples().runExample();
}
}
And here's the output:
Run time method resolution
Hi, I'm a mammal - in fact I'm a dog!
Compile time method resolutions
Compile time method resolution for a MAMMAL
Corresponding run time method resolution: Hi, I'm a mammal - in fact I'm a dog!
Compile time method resolution for a DOG
Corresponding run time method resolution: Hi, I'm a mammal - in fact I'm a dog!
Suppose you have a class Dog and a class Mammal it inherits from. Both have a method sayHello().
public static class Mammal {
public void sayHello() {
System.out.println("Hi, I'm a mammal!");
}
}
public static class Dog extends Mammal {
@Override
public void sayHello() {
System.out.println("Hi, I'm a mammal - in fact I'm a dog!");
}
}
If you were to call sayHello() on an instance of Dog which is declared (to the compiler) as a Mammal:
private Dog getADog() {
return new Dog();
}
public void runExample() {
Mammal aMammal = getADog();
System.out.println("Run time method resolution");
aMammal.sayHello();
.......
This would print:
Run time method resolution
Hi, I'm a mammal - in fact I'm a dog!
No surprises there, just a virtual method.
But now, suppose you have:
public void makeSayHello(Mammal aMammal) {
System.out.println("Compile time method resolution for a MAMMAL");
System.out.print("Corresponding run time method resolution: ");
aMammal.sayHello();
}
public void makeSayHello(Dog aDog) {
System.out.println("Compile time method resolution for a DOG");
System.out.print("Corresponding run time method resolution: ");
aDog.sayHello();
}
and in the example you call:
public void runExample() {
Mammal aMammal = getADog();
System.out.println("Run time method resolution");
aMammal.sayHello();
System.out.println();
System.out.println("Compile time method resolutions");
makeSayHello(aMammal);
Dog aDog = (Dog) aMammal;
makeSayHello(aDog);
}
aMammal is always the same object - a dog. In the second occurence, it's explicity cast as such.
Will both calls to makeSayHello use the makeSayHello(Dog aDog) method?
No - the first call will use makeSayHello(Mammal aMammal). Why? Because when it comes to method parameters, the resolution of overloaded methods is done at compile time. Otherwise stated, when overriding methods the 'closest' version will we used, by virtue of virtuality (pardon the repetition). When overloading methods, the version called will be the one that matches the compile time declaration of the parameter.
Note that the calls to aMammal.sayHello() and aDog.sayHello() in the respective makeSayHello() methods will call the Dog implementation (here we are using method overriding again).
The complete example follows:
public class OverloadingExamples {
public static class Mammal {
public void sayHello() {
System.out.println("Hi, I'm a mammal!");
}
}
public static class Dog extends Mammal {
@Override
public void sayHello() {
System.out.println("Hi, I'm a mammal - in fact I'm a dog!");
}
}
private Dog getADog() {
return new Dog();
}
public void runExample() {
Mammal aMammal = getADog();
System.out.println("Run time method resolution");
aMammal.sayHello();
System.out.println();
System.out.println("Compile time method resolutions");
makeSayHello(aMammal);
Dog aDog = (Dog) aMammal;
makeSayHello(aDog);
}
public void makeSayHello(Mammal aMammal) {
System.out.println("Compile time method resolution for a MAMMAL");
System.out.print("Corresponding run time method resolution: ");
aMammal.sayHello();
}
public void makeSayHello(Dog aDog) {
System.out.println("Compile time method resolution for a DOG");
System.out.print("Corresponding run time method resolution: ");
aDog.sayHello();
}
public static void main(String args[]) {
new OverloadingExamples().runExample();
}
}
And here's the output:
Run time method resolution
Hi, I'm a mammal - in fact I'm a dog!
Compile time method resolutions
Compile time method resolution for a MAMMAL
Corresponding run time method resolution: Hi, I'm a mammal - in fact I'm a dog!
Compile time method resolution for a DOG
Corresponding run time method resolution: Hi, I'm a mammal - in fact I'm a dog!
Sunday, August 29, 2010
Issue with OC4J 10.1.3 web services when requiring client certificates
Recently, I was testing transport level security (SSL) on Oracle's Container for Java (also part of OAS - Oracle Application Server).
My setting was: I had one web service bound to a secure site I had configured in its own xml and included in server.xml, which run on the standard 443 port (port choice is irrelevant to the problem anyway). It was all running fine until I decided to set needs-client-auth to "true" on the ssl-config tag in the secure web site configuration. What this setting does is requesting the client to also send a certificate to the server (apart from the one the server presents to the client since this is http + ssl). This is even if you don't configure client-cert authentication as the auth-method in the login-config tag of the web service's web.xml descriptor file. In fact, the problem I faced happens even if no authentication options (no login-config tag) are configured for the web service at all.
So I went ahead and enabled needs-client-auth, created my keystore (a JKS - Java Key Store - in this case) and certificates, imported the client certificate in my browser, accessed https://myserver which asked for the client certificate to present, selected the one I had imported and the welcome page for OC4J was shown. So far, so good.
After that, I accessed the test page for the web service I had deployed. The test page is an automatically generated page which allows you to input the arguments and call the web service. I entered some test values in the input fields... and where I usually got the SOAP response envelope I got either:
SSL Error: Received fatal alert: bad_certificate
or:
java.security.PrivilegedActionException: javax.xml.soap.SOAPException: Message send failed: Software caused connection abort: recv failed
along with the following message in the console:
WARNING IOException in ServerSocketAcceptHandler$AcceptHandlerHorse:run
I then looked into the log.xml file and found this stack trace for the IOException:
javax.net.ssl.SSLHandshakeException: null cert chain
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1623)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:198)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:188)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.clientCertificate(ServerHandshaker.java:1256)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:159)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:465)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1120)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1147)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1131)
at oracle.oc4j.network.ServerSocketAcceptHandler.doSSLHandShaking(ServerSocketAcceptHandler.java:245)
at oracle.oc4j.network.ServerSocketAcceptHandler$AcceptHandlerHorse.run(ServerSocketAcceptHandler.java:867)
at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:298)
at java.lang.Thread.run(Thread.java:619)
notice the "null cert chain" part.
So, what was going on?
I also had an OC4J 10.1.2 installation, so I decided to give that one a try. I configured a similar secure web site, the same keystore in the secure web site's xml as I had used for the newer OC4J version, and deployed practically the same web service (accounting for minor differences as required by each OC4J version). Same thing, went to the test page... and it worked.
So I started thinking about what was going on. First, I noticed that the IOException and null cert chain were also logged when I chose to cancel the client certificate window in my browser (thus not presenting any certificate to the server) or when the server presented a certificate for which I had not added trust in my browser options (I was using my own CA - Certificate Authority), even for the welcome page at https://myserver. So somehow this was sounding like the client certificate was not really being sent.
Then, I looked into each OC4J web service test page code. OC4J 10.1.2 used a GET on the web service, while OC4J 10.1.3 presents a seemingly more elaborate interface which uses a POST. In essence, the test page in the newer version appears to be a complete rewrite.
Recapping, same keystore, same certificates... same web service. Variable: in general, the OC4J version; specifically: the web service test page. From that, I suspected the web service test page itself - I needed a different interface to check I was right.
Enter soapUI, http://www.soapui.org/ which offers an open source version that can be downloaded for free. Inside soapUI, go to File -> Preferences and configure your KeyStore (I tested JKS and PKCS12) and KeyStore Password, then create a New soapUI Project from the web service's WSDL. Try a request and... it works!
Take out the KeyStore from the settings and you'll see the web service complains it did not receive the certificate - as expected. Configure client-cert auth-method in the web service if desired - works as well.
In conclusion, something's fishy about the newer version web service's test page, it seems client certificates are lost in the way. But, since it works from a different interface, the server is correctly configured!
My suggestion: if you run into this problem, try soapUI to see if you configured things right.
My setting was: I had one web service bound to a secure site I had configured in its own xml and included in server.xml, which run on the standard 443 port (port choice is irrelevant to the problem anyway). It was all running fine until I decided to set needs-client-auth to "true" on the ssl-config tag in the secure web site configuration. What this setting does is requesting the client to also send a certificate to the server (apart from the one the server presents to the client since this is http + ssl). This is even if you don't configure client-cert authentication as the auth-method in the login-config tag of the web service's web.xml descriptor file. In fact, the problem I faced happens even if no authentication options (no login-config tag) are configured for the web service at all.
So I went ahead and enabled needs-client-auth, created my keystore (a JKS - Java Key Store - in this case) and certificates, imported the client certificate in my browser, accessed https://myserver which asked for the client certificate to present, selected the one I had imported and the welcome page for OC4J was shown. So far, so good.
After that, I accessed the test page for the web service I had deployed. The test page is an automatically generated page which allows you to input the arguments and call the web service. I entered some test values in the input fields... and where I usually got the SOAP response envelope I got either:
SSL Error: Received fatal alert: bad_certificate
or:
java.security.PrivilegedActionException: javax.xml.soap.SOAPException: Message send failed: Software caused connection abort: recv failed
along with the following message in the console:
WARNING IOException in ServerSocketAcceptHandler$AcceptHandlerHorse:run
I then looked into the log.xml file and found this stack trace for the IOException:
javax.net.ssl.SSLHandshakeException: null cert chain
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1623)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:198)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:188)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.clientCertificate(ServerHandshaker.java:1256)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:159)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:465)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1120)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1147)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1131)
at oracle.oc4j.network.ServerSocketAcceptHandler.doSSLHandShaking(ServerSocketAcceptHandler.java:245)
at oracle.oc4j.network.ServerSocketAcceptHandler$AcceptHandlerHorse.run(ServerSocketAcceptHandler.java:867)
at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:298)
at java.lang.Thread.run(Thread.java:619)
notice the "null cert chain" part.
So, what was going on?
I also had an OC4J 10.1.2 installation, so I decided to give that one a try. I configured a similar secure web site, the same keystore in the secure web site's xml as I had used for the newer OC4J version, and deployed practically the same web service (accounting for minor differences as required by each OC4J version). Same thing, went to the test page... and it worked.
So I started thinking about what was going on. First, I noticed that the IOException and null cert chain were also logged when I chose to cancel the client certificate window in my browser (thus not presenting any certificate to the server) or when the server presented a certificate for which I had not added trust in my browser options (I was using my own CA - Certificate Authority), even for the welcome page at https://myserver. So somehow this was sounding like the client certificate was not really being sent.
Then, I looked into each OC4J web service test page code. OC4J 10.1.2 used a GET on the web service, while OC4J 10.1.3 presents a seemingly more elaborate interface which uses a POST. In essence, the test page in the newer version appears to be a complete rewrite.
Recapping, same keystore, same certificates... same web service. Variable: in general, the OC4J version; specifically: the web service test page. From that, I suspected the web service test page itself - I needed a different interface to check I was right.
Enter soapUI, http://www.soapui.org/ which offers an open source version that can be downloaded for free. Inside soapUI, go to File -> Preferences and configure your KeyStore (I tested JKS and PKCS12) and KeyStore Password, then create a New soapUI Project from the web service's WSDL. Try a request and... it works!
Take out the KeyStore from the settings and you'll see the web service complains it did not receive the certificate - as expected. Configure client-cert auth-method in the web service if desired - works as well.
In conclusion, something's fishy about the newer version web service's test page, it seems client certificates are lost in the way. But, since it works from a different interface, the server is correctly configured!
My suggestion: if you run into this problem, try soapUI to see if you configured things right.
Eclipse Helios+ does not allow to overload methods changing just the return type
So far, many of us have found we can not overload methods which, when type erasure is applied, have the same signature. For example, the following:
import java.util.List;
public class MethodDuplicateDemo {
public int useAList(List<Integer> list) {
return list.size();
}
public int useAList(List<String> list) {
return list.size();
}
}
will not compile, giving these errors:
Method useAList(List<Integer>) has the same erasure useAList(List<e>) as another method in type MethodDuplicateDemo
Method useAList(List<String>) has the same erasure useAList(List<e>) as another method in type MethodDuplicateDemo
However, many were also used to being able to write:
import java.util.List;
public class MethodDuplicateDemo {
public int useAList(List<Integer> list) {
return list.size();
}
public String useAList(List<String> list) {
return list.toString();
}
}
(notice that one of the methods returns an int, while the other returns a String)
Well, the latter example will compile using javac (1.6), and will work on Eclipse up to version 3.5 (Galileo), but it does not compile on Eclipse Helios (3.6).
The reason: starting with Helios, Eclipse implements a java 7 restriction by which the return type should not be considered when deciding if the methods are duplicates. Even though this works with the java 6 compiler from the Sun JDK, it was implemented for all compliance levels in Eclipse. This is documented in https://bugs.eclipse.org/bugs/show_bug.cgi?id=289247 and https://bugs.eclipse.org/bugs/show_bug.cgi?id=273862 .
So, time to start changing the code where it relies on the return types being different for compilation ;-)
import java.util.List;
public class MethodDuplicateDemo {
public int useAList(List<Integer> list) {
return list.size();
}
public int useAList(List<String> list) {
return list.size();
}
}
will not compile, giving these errors:
Method useAList(List<Integer>) has the same erasure useAList(List<e>) as another method in type MethodDuplicateDemo
Method useAList(List<String>) has the same erasure useAList(List<e>) as another method in type MethodDuplicateDemo
However, many were also used to being able to write:
import java.util.List;
public class MethodDuplicateDemo {
public int useAList(List<Integer> list) {
return list.size();
}
public String useAList(List<String> list) {
return list.toString();
}
}
(notice that one of the methods returns an int, while the other returns a String)
Well, the latter example will compile using javac (1.6), and will work on Eclipse up to version 3.5 (Galileo), but it does not compile on Eclipse Helios (3.6).
The reason: starting with Helios, Eclipse implements a java 7 restriction by which the return type should not be considered when deciding if the methods are duplicates. Even though this works with the java 6 compiler from the Sun JDK, it was implemented for all compliance levels in Eclipse. This is documented in https://bugs.eclipse.org/bugs/show_bug.cgi?id=289247 and https://bugs.eclipse.org/bugs/show_bug.cgi?id=273862 .
So, time to start changing the code where it relies on the return types being different for compilation ;-)
Saturday, August 28, 2010
Eclipse code name to numeric version conversion
This is a very brief post which will not be surprising, but I wanted to have the name to number relationship of the different Eclipse versions handy:
Helios 3.6
Galileo 3.5
Ganymede 3.4
Europa 3.3
Callisto 3.2
Previous Eclipse 3.1 and 3.0 versions had no code names, while next 3.7 release is known under code name Indigo.
Helios 3.6
Galileo 3.5
Ganymede 3.4
Europa 3.3
Callisto 3.2
Previous Eclipse 3.1 and 3.0 versions had no code names, while next 3.7 release is known under code name Indigo.
Subscribe to:
Comments (Atom)