views:

219

answers:

6

For some reason, putting @Override on methods overriding interface methods causes JSP compilation to fail in weblogic. Everything is definitely running off of JDK 1.6.0_14, but this Java 5'ism still persists.

Oddly, JSP compilation occasionally fails with a stacktrace pointing at code not necessarily obviously used by the JSP itself.

What's going on here?

+3  A: 

I've seen this a lot myself. In Java 6, it is (supposedly) permissible to use @Override on interface implementation methods. In Java 5, this is an error. However in my Java 6 code, sometimes @Override is accepted on interface implementation methods, and sometimes it is not.

To make things weirder, some IDEs (e.g. NetBeans) are fine with it, while IntelliJ IDEA is sometimes ok and sometimes not. I have found, however, that compiling the code in either IDE will ignore the alleged errors being reported by the IDE.

In other words, is the problem manifesting in your IDE? If so, compile the code directly (use the command-line if necessary) and see what happens. The IDE may be reporting spurious errors.

Vanessa Williams
No, this is a real issue in JSP compilation. If the JSP (under weblogic) touches any code that overrides an interface method, the JSP will not be able to compile and render.
Stefan Kendall
A: 

In my mind, @Override makes sense on methods that are overriding methods, not implementing methods.

So if you have an interface:

public interface MyInterface {
    public void doSomething();
}

A class that implements that interface is below (MyClassA):

public MyClassA implements MyInterface {
    public void doSomething() {
        System.out.println("This is from MyClassA");
    }
}

Then, the below class extends MyClassA and overrides doSomething, and so then I'd add the @Override annotation.

public MyClassB extends MyClassA implements MyInterface {
    @Override
    public void doSomething() {
        System.out.println("This is from MyClassB");
    }
}

I wouldn't do the below (whether or not it is permissable) in any case, since it breaks the idea about overriding something - you're implementing, not overriding the interface:

public MyClassA implements MyInterface {
    @Override
    public void doSomething() {
        System.out.println("This is from MyClassA");
    }
}
jamiebarrow
So you shouldn't throw @Override when extending abstract classes? Using @Override allows you to ensure you're blowing away whatever you got from something up the inheritance tree, instead of creating a new definition. The most notorious example of this is creating an incorrect "equals" method that takes an object of type A vs type Object. This problem occurs EVERYWHERE you rely on inheritance to override/implement a method. @Override gives you the guarantee that you're doing what you think you're doing.
Stefan Kendall
Overriding an abstract class is very different to implementing an interface. My example shows when using interfaces (not abstract classes). You mentioned interfaces, not abstract classes; i.e. I thought you were only implementing an interface, which could cause an issue if the @Override annotation is used.
jamiebarrow
If I have an abstract class that has methods which need to be implemented, but it also implements an interface, I can immediately see and be sure which methods are from the interface with compile-time checking with @Override. I get no such checks without the annotation. Regardless, this syntax is perfectly valid in JDK6 and it shouldn't cause my JSPs to fail.
Stefan Kendall
Sure. But you did say overriding on 'interface' implementation methods, but didn't mention the abstract class ;) I think that led to the confusion and my answer...
jamiebarrow
+3  A: 

The @Override is supposed to only be retained in source so shouldn't come up in byte code. There might an angle you can play in ensuring those classes are complied separately from the JSPs and simply available in the classpath -- rather than the source path.

If that's already the case then it might be a different issue than what is immediately showing.

Used to be the JSP complier was a separate library shipped with the server and not tied to the vm the server is running in. WLS used to use Javelin. Seems like they switched that in 10 to use the Java Compiler API. So it should work fine as long as you have Sun vm Java 1.6. But if there's 'javelin' anything in your stacktrace, definitely check that angle.

David Blevins
Thanks. I'll look for this. Most of our WLS installations were upgrades, I believe, or had WLS9 installed at some point, so this could be the culprit.
Stefan Kendall
Javelin is definitely running. How do I switch?
Stefan Kendall
It looks like JavelinxJSPStub is in weblogic.jar. How can I possibly disable this?
Stefan Kendall
Not too sure there. They mention the switch in their release notes: http://download.oracle.com/docs/cd/E12840_01/wls/docs103/notes/new.html#wp1090981
David Blevins
I know. I found that too :(. Reality seems to disconnect from the docs, however.
Stefan Kendall
A: 

Simply avoiding the annotation on implemented interface methods will resolve the issue. When doing team development with OSX users I run into this often due to Eclipse automatically adding @Override when implementing interfaces. The OSX guys get a compile error every time, even though it is technically valid. In my opinion, needing an annotation to a say I'm implementing an interface is lame since the interface method is nothing without an implementation :).

Mondain
...you don't think I already know that changing code is a "solution" to this?That's as bad as"My Scala code won't compile...why?"A: "Don't use scala, and you won't have code to compile."
Stefan Kendall
So you would rather "waste" time where its not necessary? Good luck.
Mondain
Using "Java" isn't "necessary", nor is generics, or a proper application server. I still spend time to get them working, however.
Stefan Kendall
+1  A: 

A possible workaround might be to precompile JSP using appc. This could at least allow to circumvent the issue.

Regarding the "real" question, my understanding is that you did upgrade domains, so maybe have a look at the following resources:

This is a wild guess but maybe some backward compatibility flag is activated and WebLogic keeps using the "old" approach.

Pascal Thivent
I was hoping the flag for JSPCompilerBackwardsCompatible would do it, but no dice.
Stefan Kendall
A: 

I agree with your instinct and the other answers that WLS is using Java 5 somehere. The items below seem like useful tidbits from Oracle/WebLogic resources. I don't have a WebLogic Server 10.3 installation to confirm these:

Weblogic Server 10.3

According to this, at least Weblogic Server 10.3 is required to use Java 6, but I can't see anything the confirms this as authoritative info:

Re: WebLogic 10.0 supports Java 6?
Posted: Apr 9, 2009 12:26 PM in response to: user8324142
Hi,
Weblogic 10 will not support JDK6.
Please upgrade to Weblogic 10.3 to work with JDK 6.

Checking the Java version

Determining Which JDK Version You Are Using

You can determine which version of the JDK you are using by issuing a command, as follows:

  1. Open a command prompt window and go to the appropriate directory:
    BEA_HOME\WL_HOME\server\bin (Windows)
    BEA_HOME/WL_HOME/server/bin (UNIX)

    In both pathnames, BEA_HOME represents the directory in which you have installed your software and WL_HOME represents the wlserver_< version >.

  2. Make sure that your environment is set up properly by entering the following command at the prompt: setWLSenv.cmd (Windows)
    setWLSenv.sh (UNIX)

  3. Enter the following command at the prompt: java -version

Configuring Java version:

Setting Java Parameters for Starting WebLogic Server

... Java parameters must be specified whenever you start WebLogic Server. ... Oracle recommends that you incorporate the command into a [startup] script ...

If you used the Configuration Wizard to create your domain, the WebLogic startup scripts are located in the domain-name directory where you specified your domain. By default, this directory is BEA_HOME\user_projects\domain\domain-name, where BEA_HOME is the directory that contains the product installation, and domain-name is the name of the domain directory defined by the selected configuration template. ...

Change the value of the variable JAVA_HOME to the location of your JDK. For example:
set JAVA_HOME=C:\bea\jdk150_03

...

Bert F