I have a very simple spring boot application that I want to deploy to Jboss EAP. Here is my simple application class:
#SpringBootApplication
public class MayurApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(MayurApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<MayurApplication> applicationClass = MayurApplication.class;
}
#RestController
class GreetingController {
#RequestMapping("/hello/{name}")
String hello(#PathVariable String name) {
return "Hello, " + name + "!";
}
}
and my pom.xml is also very basic. When I run this application on Tomcat, using the embedded Tomcat what ships with spring boot. Everything works like charm in just one click. I can access http://localhost:8080/demo/hello/World and it works too.
Now I tried to make it Jboss EAP compatible war, I disabled the Tomcat by excluding from spring-boot-starter-web, and convert it into a war project. (as suggested by article http://spring.io/blog/2014/03/07/deploying-spring-boot-applications).
I also added:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>,
as it was complaining.
Now after all this, it compiles fine and creates a war too. When I copied this war to jboss deployment, I can see it successfully deployed on console.
But the rest api http://localhost:8080/demo/hello/World just does not work and constantly throws error on browser:
JBWEB000068: message /demo/hello/World
JBWEB000069: description JBWEB000124: The requested resource is not available.
What am I doing wrong?
Found this in Spring Boot Reference Guide, add the below line in application.properties file
server.servlet-path=/*
tested this in jBoss EAP 6.2 and worked fine.
Answer is here : Spring Java Config vs Jboss 7
Apparently "/" does not work on Jboss EAP 6.3 , but "/*" works.
and they seems to have fixed it with wildfly 8
You mentioned JBoss 6 in you tags. Based on my experience Spring Boot Autoconfigure and JBoss 6 (specifically) is a no-go. If Hot Deploy is turned on or perhaps some other condition JBoss VFS performs some aggressive scanning of all jars in the war file. Once it starts to scan the classes in the autoconfigure module, it will abort due to an error akin to ClassNotFoundException. If you are using Autoconfigure, one solution might be to place the spring modules in the Container's lib. But this would make deployment unwieldy. I did not see this behavior on JBoss 7 nor Wildfly 8.
Related
I am using the io.springfox springfox-boot-starter v 3.0.0,
According to the documentation, this Spring Boot setup would disable the swagger endpoint for prod:
#Configuration
#Profile({"!prod && swagger"})
public class SwaggerConfig implements WebMvcConfigurer {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.select()
.apis(RequestHandlerSelectors.any())
.build()
.apiInfo(apiInfo());
}
...
When on prod, the customisations of swagger defined here are indeed missing, but the Swagger UI endpoint is still there. How can I suppress the /swagger-ui/ endpoint altogether? Is there nothing like a springfox.swagger-ui.enabled=false property I can set somewhere in the spring boot application configuration?
You can disable using below property
springfox.documentation.enabled=false
Springfox Boot Starter API enable by default the 'auto-startup' configuration, means Swagger UI html page (ex. /swagger-ui/index.html) and Api-Docs (/v2/api-docs) JSON page containing a swagger with All API definitions.
For production environment is a good choise disable all the API documentation.
To disable all the swagger auto-configurations you can add on your application-prod.properties file the property below:
springfox.documentation.auto-startup=false
In this case with Your config on prod you have nothing about swagger.
If you want to remove the swagger-related resources completely, consider do it in the compile-time.
If you are using Apache Maven, it is easy to control dependencies and runtime configuration in a Maven profile, eg swagger.
When building for production, run the following command.
mvn package -Pprod
// for dev stage.
mvn clean spring-boot:run -Pdev,swagger
My example is a little old which used Maven to control different configuration in different stage.
I have written a Grails Plugin, written in Grails 2.1.1, which offers a service. Now, I have created a new Grails project with Grails 2.4.4 and wanted to inject the service, but this fails.
package testproject
class HomeController {
def myService
def index() {
println myService
}
}
Always nullis printed. I tested this with a Grails 2.4.4 project and with a Grail2 2.4.3 project. When I create instead my Grails Project with Grails 2.1.1 it works.
Why? Shouldn't be a service reachable for newer versions? Do I always have to upgrade the plugin, which contains the service, to be able to use newer Grails versions?
I had this problem as well, and it didn't hit me until 2.4.4. I have a custom security plugin that depends on the Spring Security Plugin. In my plugin, I'm setting a custom user details service in doWithSpring. This definition looks like this:
userDetailsService(UserService) {
grailsApplication = ref('grailsApplication')
errorService = ref('errorService')
}
I had references to userService in my application and in my plugin. These references stopped being injected in Grails 2.4.4. I was able to fix it by replacing these references with userDetailsService. I don't like this though, because the reference looks like it points to the Spring Security version of this service, and I'm invoking methods that only exist in my UserService class.
Anyways, I'm not sure if it's a bug or bug fix in 2.4.4, but check and make sure that your plugin and/or resources.groovy files aren't redefining your MyService class as something else.
I'm running a Spring Boot web app with an underlying Neo4j database. In order to be able to view the Neo4j browser (direct web view onto the db), the Neo4j web server is embedded into the application using the following configuration.
#Bean(initMethod = "start", destroyMethod = "stop")
public WrappingNeoServerBootstrapper neo4jWebServer() {
return new WrappingNeoServerBootstrapper((GraphDatabaseAPI) graphDatabaseService());
}
and by including the following in the maven pom:
<dependency>
<groupId>org.neo4j.app</groupId>
<artifactId>neo4j-server</artifactId>
<classifier>static-web</classifier>
<version>2.0.2</version>
</dependency>
This all works fine when running from STS (i.e. unpackaged).
When I package the application up using the spring-boot-maven-plugin. This creates the uber-jar correctly containing the neo4j-server-2.0.2-static-web.jar file in the /lib folder of the uber-jar.
When I run the application directly using the uber-jar file and then attempt to hit the http://localhost:7474/browser/ URL for the Neo4j browser, it returns a 404.
The reason for this is that the Jetty DefaultServlet attempts to getResource() from the WebAppContext which, in turn, calls JarFileResource.exists() which tries to operate on the following URL string:
jar:file:/home/dev/myapp/target/myapp-0.0.1-SNAPSHOT.jar!/lib/neo4j-browser-2.0.2.jar!/browser/
Jetty fails to match anything in its resource list as it's looking for a resource called /lib/neo4j-browser-2.0.2.jar!/browser/ as the code, e.g. at http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java#n123 (and a couple of other places) is looking for the first !/ in the string.
I am going to submit a Jetty bug for this with a suggestion that they use String.lastIndexOf("!/") in their code, which will resolve the issue.
In the meantime, apart from producing our oun standard maven assembly, does anyone have any suggestions for how I could get this to work within a Spring Boot uber-jar?
Many thanks.
Spring Boot uber-jars use some special techniques to allow content to be loaded from nested jars. Jetty (quite understandably) assumes that jar URLs will only contain a single ! which unfortunately is not the case here.
Your easiest solution is probably to switch to the maven-shade-plugin. This creates an uber-jar by unpacking all of your dependencies before repacking them into a single jar.
Some other alternatives are suggested in the Spring Boot reference documentation
If you're using SpringBoot+Maven you can add the following:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<requiresUnpack>
<dependency>
<groupId>org.neo4j.app</groupId>
<artifactId>neo4j-browser</artifactId>
</dependency>
</requiresUnpack>
</configuration>
<executions>
...
</plugin>
Obtained from this gradle suggestion
I have a Grails app that uses the Rest plugin
When I drop my war into my JBoss deploy directory and start it up, the deployment of the app fails because of the following error:
2012-11-01 15:48:33,931 ERROR [org.jboss.web.tomcat.service.deployers.JBossContextConfig] XML error parsing: context.xml
org.jboss.xb.binding.JBossXBRuntimeException: Failed to create a new SAX parser
I believe this refers to the grails app containing a version on xercesImpl as well as JBoss having it's own. We usually rectify this by removing xercesImpl from our apps or setting them to "provided" scope.
I'm trying to figure out how I fix this deploy issue. I'm assuming I have to edit the BuildConfig.groovy script and tell it, somehow, to exclude xerces right? How would I do that for this plugin? If this were a "dependency" that appears to be easy to specify the exclusions. But I'm not sure how to do it for this plugin...
any ideas?
In your BuildConfig.groovy add this:
inherits('global') {
excludes 'serializer'
}
It turns out, doing the following in the plugin section of my BuildConfig.groovy did the trick after all...
compile(":rest:0.7"){
excludes "xercesImpl"
}
Is there a way to run jetty 7 or 8 from ant? There's an ant plugin that works fine with the (pre-eclipse) version 6 only, but the eclipse versions seem only available in standalone form.
Quote from http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty
Jetty has a slogan, "Don't deploy your application in Jetty, deploy Jetty in your application." What this means is that as an alternative to bundling your application as a standard WAR to be deployed in Jetty, Jetty is designed to be a software component that can be instantiated and used in a Java program just like any POJO. Put another way, running Jetty in embedded mode means putting an HTTP module into your application, rather than putting your application into an HTTP server.
This means that you can just add a single java class in your project, compile and run with something like:
<target name="run.jetty">
<java class="myjettyrun/RunJetty" classpathref="classpath.run.jetty"/>
</target>
And the RunJetty.java would look something like this:
package myjettyrun;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
public class RunJetty {
public static void main(String[] args) throws Exception {
Server server = new Server(80);
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
webapp.setWar("distrib/wars/root.war");
server.setHandler(webapp);
server.start();
server.join();
}
}
This has been tested with Jetty 8. Make sure you have all the required jetty jars (jetty-webapps, jetty-server) and possibly jsp support (eg. jsp-2.1-glassfish) with their dependencies in classpath.run.jetty.
In http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty you can find more examples on how to run jetty in different situations.