I am in the process of creating a REST web service in Java Spring. I've successfully loaded STS and the example detailed at :
"This guide walks you through the process of creating a "hello world" RESTful web service with Spring."
http://spring.io/guides/gs/rest-service/
However that tutorial only goes so far.. I want to create a WAR file instead of a self running jar containing a servlet, and deploy that WAR file. I then found this tutorial, and attempted to just modify the first tutorials build.gradle file.
"Converting a Spring Boot JAR Application to a WAR"
http://spring.io/guides/gs/convert-jar-to-war/
It seemed to build just fine into a .war file.. the service is running in my TOMCAT instance's manager.. but I get 404's once I attempt to use the service.
URL 404'd
http://localhost:8080/gs-rest-service-0.1.0/dbgreeting?name=MyName
Do I need to modify the mapping?
DataBaseController.java
#RequestMapping("/dbgreeting")
public #ResponseBody DataBaseGreeter dbgreeting(
#RequestParam(value="name", required=false, defaultValue="World") String name) {
return new DataBaseGreeter(counter.incrementAndGet(),String.format(template, name));
}
Now I have the .war file created according to a blending of things.. and worried I perhaps missed something.
I've since discovered XAMPP on OSX doesn't contain a webapp/ folder, which has forced me to load Bitnami's Tomcat stack instead. Do people generally switch between XAMPP and other stacks based on this? or did I miss something to get webapp folder created in XAMPP?
A WAR is just a JAR with special properites. It needs to have a WEB-INF, under which you need a web.xml to describe your deployment, any app server dependentXML configuration files, and usually a lib, classes, and other odds and ends.
The easiest way would be to use Maven to create your WAR. I think you should be able to simply change the project type in the pom.xml from JAR to WAR. The tutorial you followed seems to use Gradle, which in turn uses Maven I believe, so you should have one there somewhere. Other than that, google for tutorials on how to construct a WAR. I don't believe that Tomcat requires any special deployment descriptors, so you should only need the web
.xml.
(Answer from OP moved from question to here)
Boy I feel really dumb.. Found there was more to the tutorial after changing the gradle instructions.. including the very needed Auto Configuration that supercedes/replaces the need for a web.xml
Solution
Initialize the servlet
Previously, the application contained a public static void main() method which the spring-boot-gradle-plugin was configured to run when using the java -jar command.
By converting this into a WAR file with no XML files, you need a different signal to the servlet container on how to launch the application.
src/main/java/hello/HelloWebXml.java
package hello;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.SpringBootServletInitializer;
public class HelloWebXml extends SpringBootServletInitializer {
#Override
protected void configure(SpringApplicationBuilder application) {
application.sources(Application.class);
}
}
Will give credit to the first answer, but you both were correct that the web.xml (or what Spring-Boot uses to replace it) was needed.
I would expect to see some INFO output when a spring boot application starts so some ideas are:
Try a regular tomcat instance
Download and extract the zip distribution.
Start tomcat with bin/startup.sh
Copy your war to the webapps directory
Check the logs... hope to see some evidence of spring starting up
Manually inspect the war file
Unzip your war file
Expect to see WEB-INF/web.xml
Related
everyone,
I'm new on web development. Recently, I start a tutorial to build Registration and Login with Spring Boot and MySQL Database. When I run the unit test, there are errors showing up. I cannot find ApplicationContext file in the tutorial, and also try serval methods on stack overflow e.g. change plug setting in pom.xml but isn't working.
Can anyone answer this problem?
Errors on IDE
The application context is not a file – it's a term Spring uses to describe the entire state of your application. So the error means that Spring is not able to start your application because of missing database configuration.
Looks like you are using maven (src/main/java). In this case put the applicationContext.xml file in the src/main/resources directory. It will be copied in the classpath directory and you should be able to access it with
#ContextConfiguration("/applicationContext.xml")
A plain path, for example, "context.xml", will be treated as a classpath resource from the same package in which the test class is defined. A path starting with a slash is treated as a fully qualified classpath location, for example "/org/example/config.xml".
So, it's important that you add the slash when referencing the file in the root directory of the classpath.
I need to load the application.properties file from outside the spring boot war which going to be deployed in tomcat.
I tried various solution missing something
Tried setting environmental variable as below in windows
name : SPRING_CONFIG_NAME
value:D:/test/application.properties
i tried multiple values for above value like file:/// in prefix and only file: as perfix .Nothing worked
Tried having context parameter is tomcat like mentioned in below SO answer
https://stackoverflow.com/a/44697239/2751962
Tried loading like this in main file which extends SpringBootServletIntializer
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class)
.properties(getProperties());
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
SpringApplicationBuilder springApplicationBuilder = (SpringApplicationBuilder) (new SpringApplicationBuilder(Application.class))
.sources(Application.class)
.properties(getProperties())
.run(args);
}
static Properties getProperties() {
Properties props = new Properties();
props.put("spring.config.location", "file:///D:/test/application.properties​");
return props;
}
I not sure what i missed , Kindly help.
External Configuration in Spring Boot
When using Spring Boot, there are documented naming conventions and directory structure. A Spring Boot app searches for properties to load from a prioritized list, so there are to suggestions for you to consider:
Use command-line flag spring.config.location to target specific file or directory from which to load properties sources. You can use this to specify directories to search or individual files to load. Be cautious loading individual files though, if you intend to use profile-based properties. (add flag in command like this: java -jar MyJar.jar --spring.config.location=D:\test\)
By default, Spring Boot will look for a ./config/ directory where the WAR is and the directory of the WAR itself, so you may place "application.properties" in either position and it will be loaded.
Pivotal provides a super great reference for Spring Boot. Section 24 covers properties more extensively than I can in a post.
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html (*links to most recent release's reference)
Note: I am not a Windows user, so be careful pasting in that filepath above. Edit Me.
Extending Configuration to Deployable Packages
Normally Spring Boot packages into an executable WAR or JAR that has an embedded servlet container engine that is used for the runtime. In your case, however, you are packaging a conventional WAR and deploying that to an external instance of Tomcat, so the configuration parameters must be propagated through Tomcat, using the JAVA_OPTS variable.
For a Apache Tomcat, the convention is to place your properties in ${catalina_base}/conf where catalina.base points to the location of the Tomcat instance. I created a working demo just now following these steps:
First, follow section 88.1 of the reference to setup a base WAR app
mvn package
Place application.properties in conf directory within Tomcat
set JAVA_OPTS=-Dspring.config.location=${catalina.base}/conf/
"%CATALINA_HOME%"\bin\startup
Deploy
It's not the cleanest deployment pipeline, but if you must use an external Tomcat instance, then this will work. However, to run multiple apps with separate property files on the same Tomcat instance would complicate things. In that case, using Spring Framework (not Boot) would be easier to configure.
You can try setting properties via XML and or Java configuration and #PropertySource.
#Configuration
#PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
//...
}
source :- https://www.baeldung.com/properties-with-spring
I have created sample web application, packaged it into WAR, then put it into webapps folder into jetty. And it does not work.
Proof, windows from top to bottom:
1) The content of GreetingController.java
2) The compiled file is present inside WAR file in appropriate place
3) The web application is working, it's name is recognized (folder content displayed)
4) Controller is not working and it's name is not recognized
What else to check?
UPDATE
My WAR file: https://www.sendspace.com/file/mb94jt
I think you are missing something in your app. The page you are referring is just a guide to help understand how the framework works. For complete simple examples, please refer to:
https://github.com/javalite/activeweb-bootstrap - this is a simple app with Bootstrap and no database support
https://github.com/javalite/activeweb-lessc - simple app without database, but with Less instead of CSS
https://github.com/javalite/activeweb-simple - simple ActiveWeb + ActiveJDBC webapp (CRUD)
Here is the Getting Started page: http://javalite.io/getting_started_activeweb
hope it helps
I have a very simple java web-application which is deployed to Tomcat.
In this application I have some code which goes like this:
package com.mywebapp.hello;
import javax.servlet.http.*;
import java.io.*;
public class PdfTwoServlet extends HttpServlet {
public void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
httpServletResponse.setContentType("application/pdf");
InputStream is = PdfTwoServlet.class.getResourceAsStream("/two.pdf");
When I compile my code and deploy it to tomcat, the directory structure goes like this:
This is under say C:\Tomcat\webapps\myApplication :
So
PdfTwoServlet.class.getResourceAsStream("/two.pdf");
works fine and finds the file two.pdf which is under classes folder, but I have no idea how this works.
Accessing properties file in a JSF application programmatically here BalusC says:
The Class#getResourceAsStream() can take a path which is relative to
the location of the Class which you're using there as starting point.
If you use /foo/filename.properties, then it will actually load
foo/filename.properties from the classpath root.
I have 2 questions:
1) Why is the classpath root is WEB-INF\classes folder? Where is it determined? ( As far as I understand, it should be because code is working fine as I said. )
According to this: http://docs.oracle.com/javase/tutorial/essential/environment/paths.html , I do not have a classpath set in my local machine. So maybe when I start tomcat, it sets the classpath? But there are few web-apps deployed, are there few classpaths?
2) Is there a better way to make this work instead of: PdfTwoServlet.class.getResourceAsStream ? Something like getClassPath().getResourceAsStrem ?
Edit: Maybe someone more experienced and with better English can edit the title of this question. I am not sure if it is good enough.
For 1) The classpath root in a servlet application is by specification the WEB-INF\classes folder of the jar, plus the root of all the jars in WEB-INF/lib of that WAR. Anything in those locations will be seen as the root of the classpath.
For the question on how classpaths in tomcat work, when tomcat deploys it set's the classpath in the following way: each WAR corresponds to a separate class loader which has access to WEB-INF/classes and all the jars in WEB-INF/lib.
By default if the resource searched is not found here, it will be searched for in the tomcat/lib directory. If it's not found there, it will ask the parent class loader, and so on, the explanation can be found here
If there are several web-apps deployed, each WAR will have it's own class loader pointing to it's own WEB-INF/classes and WEB-INF/lib jars.
For 2) there is not method like getClasspath(), ServletContext.getResourceAsStream() is the advised way in servlet applications for getting resources from inside the WAR. The WAR might be zipped or exploded, and this works for both, see this answer.
Is it possible for a web application to access its own deployed folder. I am using JSF 1.2 framework and i need to access some of the files which i have it in the deployed directory.
Does JSF has any in built method to give us the deployed folder and the files in it?
Use ExternalContext.getResourcePaths("/"). In a servlet container, this will delegate to ServletContext.getResoucePaths(String). As the documentation notes:
For example, for a web application
containing:
/welcome.html
/catalog/index.html
/catalog/products.html
/catalog/offers/books.html
/catalog/offers/music.html
/customer/login.jsp
/WEB-INF/web.xml
/WEB-INF/classes/com.acme.OrderServlet.class
/WEB-INF/lib/catalog.jar!/META-INF/resources/catalog/moreOffers/books.html
getResourcePaths("/") would return
{"/welcome.html", "/catalog/",
"/customer/", "/WEB-INF/"}, and
getResourcePaths("/catalog/") would
return {"/catalog/index.html",
"/catalog/products.html",
"/catalog/offers/",
"/catalog/moreOffers/"}.
For portable code, do not assume you can access resources via the file system:
This method (getResource(String)) allows the servlet container to make a resource available to servlets from any source. Resources can be located on a local or remote file system, in a database, or in a .war file.
You can get access to resources in the classpath, but the servlet API does not guarantee their physical representation. In other words, if you deploy a WAR file, the container may explode the WAR file or keep it as is, or do something completely different depending on its needs.
In this particular context it mean that you introduce a subtle container dependency by assuming that a web application is deployed to a folder, which you should be very careful about.
If all you need, however, is to get some items you have in the classpath you should have a look at this question: Getting the inputstream from a classpath resource (XML file)
FacesContext.getCurrentInstance().getExternalContext().getResource("/").toString();
you will get the path to your WEB-INF/classes dir traverse using parent(); method from File class to get the location