7
votes

I'm having problems accessing the sample springBoot application after I deploy it to Weblogic12C. It works fine using the springBoot-embedded Tomcat server.

Install and test using SpringBoot-embedded Tomcat: all is well

Steps to reproduce: get the springBoot "getting started" application code following the steps: https://spring.io/guides/gs/spring-boot/

  • git clone https://github.com/spring-guides/gs-spring-boot.git
  • cd gs-spring-boot/complete/ (we'll be using the gr-spring-boot/complete dir so that you don't have to go through the "getting started" page above (all changes done for you in "complete").
  • open the file gs-spring-boot/complete/build.gradle and add " apply plugin: 'war' " below the other "apply plugin" entries

At this point, you can validate that all is well by running the gradle "bootRun" tasks which starts the app in the embedded Tomcat server. Once tomcat started, browse to localhost:8080/ and see that you get "Greetings from Spring Boot!"

Now let's install this on Weblogic 12C

  • run "gradle war" (again, work from gs-spring-boot/complete/) you will now have a war file under gs-spring-boot\complete\build\libs\complete.war
    • go to your weblogic12C console. I didn't make changes to my WL12C so the console is located at localhost:7001/console NOTE: I downloaded the WL12C developer version one week ago from the Oracle site. I didn't make any changes to it, as downloaded. The dev version of WL12C download requires that we point it to our already installed JDK. My WL12C uses java version:

      java version "1.7.0_45" Java(TM) SE Runtime Environment (build 1.7.0_45-b18) Java HotSpot(TM) Server VM (build 24.45-b08, mixed mode)

    • when in the console, deploy the war file:
    • click on "deployments"
    • click on "install"
    • browse to you "gs-spring-boot \ complete \ build \ libs" dir
    • select the radio button next to complete.war and hit next
    • select "install as application" and hit next
    • leave all options as is [DD only, use the defaults, use same accessibility] and hit next
    • click finish

At this point, you will see that the application deployed fine: - click on "deployments" again and see that your "complete" springBoot app is listed and ACTIVE - click on "complete" and notice on this page: "Context Root: /complete". NOTE: weblogic docs say that if there is no context-root defined in weblogic.xml, then it uses the name of the war file (minus the .war)

Now, the problem: getting a 403:

if you try to access the springBoot app at localhost:7001/complete you get a 403!!!

Error 403--Forbidden
From RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1:
10.4.4 403 Forbidden
The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.

Ok, so let's make one final change (I'm fishing here, maybe weblogic really wants a weblogic.xml):

  • create the dir: gs-spring-boot\complete\src\main\webapp\WEB-INF\
  • create this file: gs-spring-boot\complete\src\main\webapp\WEB-INF\weblogic.xml
  • edit weblogic.xml to contain:

    <?xml version="1.0" encoding="UTF-8"?>
    <wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
        <wls:weblogic-version>12.1.1</wls:weblogic-version>
        <wls:context-root>testApp</wls:context-root>
    </wls:weblogic-web-app>
    
  • now go back to your weblogic console (localhost:7001/console)

  • go to "web applications" and select the checkbox next to "complete" then hit "delete"
  • restart your weblogic12C server (just to be paranoid)
  • run the "gradle clean" then "gradle war" task again to generate a new war file
  • open the war file (using winzip or whatever) and confirm that the war file now has WEB-INF/weblogic.xml
  • go to the console the deploy the new war file (use same steps as above)
  • confirm that the app is now deployed and has a contextRoot of /testApp (as defined in weblogic.xml)
  • browse to localhost:7001/testApp/

The 403 is still there. So:

  • weblogic DOES know about this application (returns 403). Because if it didn't know about the application, it would return 404 (try it by going to localhost:7001/doesNotExist and you'll get 404)
  • but it looks like WL12C doesn't route requests to spring. In the past, we'd define a bunch of things in web.xml but nowadays, with javaConfig and SpringBoot, this should all be done automagically...
    • note: because SpringBoot uses JavaConfig (Servlet3), we can't use anything lower that weblogic12C (which is the latest)

Another thing I tried: change RequestMapping

In the sample code above, open the file gs-spring-boot\complete\src\main\java\hello\HelloController.java and replace:

@RequestMapping("/")

with this:

@RequestMapping("pierre.htm")

Now, if you browse to (remember weblogic.xml define context-root as /testApp):

  • localhost:7001/testApp/pierre.htm you'll get a 404
  • localhost:7001/testApp/ you'll get 403

And if you try on tomcat with "gradle bootrun", you can get to it fine: localhost:8080/pierre.htm (you get "greetings from SpringBoot!").

So this yields the following hints:

  • Weblogic does know about /testApp
  • Weblogic has no idea what /testApp/pierre.htm is. It's like it was never configured as a RequestMapping.
  • there is some "Spring wiring" missing for it to work on weblogic....

This is where I'm stuck... Can anyone think what JavaConfig "wiring" I'm missing to make it work on Weblogic? Any help greatly appreciated. Thanks!!

Solution

If anyone comes here, to make it simpler than read all the comments, below, here's how to make it work:

  • start with the SpringBoot sample app and git the "complete" solution from here: spring.io/guides/gs/convert-jar-to-war/
  • update the class WebInitializer so that it implements WebApplicationInitializer. So change it from this:

        public class WebInitializer extends SpringBootServletInitializer {
    

To this:

        public class WebInitializer extends SpringBootServletInitializer implements WebApplicationInitializer {
  • create a new file src/main/webapp/WEB-INF/weblogic.xml and put this contents in it:

    <?xml version="1.0" encoding="UTF-8"?>
    <wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
        <wls:weblogic-version>12.1.1</wls:weblogic-version>
        <wls:context-root>helloApp</wls:context-root>
        <wls:container-descriptor>
            <wls:prefer-application-packages>
                <wls:package-name>org.slf4j.*</wls:package-name>
            </wls:prefer-application-packages>
        </wls:container-descriptor>
    </wls:weblogic-web-app>
    
    • gradle war
    • deploy to Weblogic12C
    • it should work now :) Thanks so much to both Dave Syer and Evgeni!

Previous Solution (kept here for posterity)

  • start with the SpringBoot sample app and git the "complete" solution from here: spring.io/guides/gs/convert-jar-to-war/

    • in the sample app's package "hello", add a new public class HelloWebXml implements WebApplicationInitializer
    • take all the code from org.springframework.boot.context.web.SpringBootServletInitializer and copy it into HelloWebXml but change these lines:

      protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application; }

To this:

    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(Application.class);
    }
  • copy the class org.springframework.boot.context.web.ErrorPageFilter into package "hello" in the sample app
  • create a new file src/main/webapp/WEB-INF/weblogic.xml and put this contents in it:

    <?xml version="1.0" encoding="UTF-8"?>
    <wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
        <wls:weblogic-version>12.1.1</wls:weblogic-version>
        <wls:context-root>helloApp</wls:context-root>
        <wls:container-descriptor>
            <wls:prefer-application-packages>
                <wls:package-name>org.slf4j.*</wls:package-name>
            </wls:prefer-application-packages>
        </wls:container-descriptor>
    </wls:weblogic-web-app>
    
    • gradle war
    • deploy to Weblogic12C
    • it should work now :) Thanks so much to both Dave Syer and Evgeni!

NOTE: There is a similar questions here: Deploy Spring Boot app in Weblogic ...but that other question is about the deployment and it's a little vague (deployment itself works fine for me)

3
That sample isn't immediately convertible to a war just by changing the packaging. Did you see the "converting" guides, e.g. github.com/spring-guides/gs-convert-jar-to-war-maven?Dave Syer
AH, good point, I didn't see that. That is definitely part of the "Spring wiring" I was missing. So, I just tried it and still not luck. So, instead of using a version of the code that had my dirty hands on it, I used the "gradle version" of the Maven doc you linked: spring.io/guides/gs/convert-jar-to-war and used the "complete" folder to generate the war file (it has all the changes mentioned on that page). I use "gradle war" to generate the war and deploy that to WL. Unfortunately, I still get a 403 upon hitting my local Weblogic12C at localhost:7001/gs-convert-jar-to-war-0.1.0/Pierre

3 Answers

3
votes

The problem with Weblogic is that it looks for a class that directly implements WebApplicationInitializer to load the context. You probably extend SpringBootServletInitializer. Try to create a class that implemets WebApplicationInitializer and copy the content of SpringBootServletInitializer in it(you will need to also copy one package level class from the spring source, so your custom class can see it, as far as I remember).

4
votes

The soluation by Evgeni works thanks. But i have an improvement.

Rather than take a copy of the SpringBootServletInitializer and ErrorPageFilter, you can continue to extend it, but simply add a redundant "implements WebApplicationInitializer" to your class:

@Configuration
@EnableJpaRepositories
@EnableAutoConfiguration
@ComponentScan("nz.co.myapp")
public class Application extends SpringBootServletInitializer implements WebApplicationInitializer {

    /** Used for running in war */
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

}
-1
votes

Redundant superinterface WebApplicationInitializer for the type Application, already defined by SpringBootServletInitializer