Is ApplicationContext file necessary if I want to run the unit test? - java

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.

Related

Can i set relative path to java.security.auth.login.config?

In my Spring Boot app i need to call to:
System.setProperty("java.security.auth.login.config", authConf);
where authConf seems to be expected as an absolute path to the file.
the problem is, my Spring Boot app is packaged and executed as a jar and i want to package the file inside the jar.
The answer provided in this question might work only when a WAR is deployed in a server. It doesn't seem to work when we run JARs with embedded container.
is there way i could set a relative path to java.security.auth.login.config to refer to my conf file packaged within my jar ?
I know that the answer is about 6 years too late, but I recently faced the same issue and found and answer. Maybe my answer will at least help the next dev who will face this issue. I was able to solve it is by first creating a javax.security.auth.login.Configuration of type JavaLoginConfig and then use the Configuration.setConfiguration(configuration method) of the same Configuration class. Using this method I was able to bundle our jaas.conf inside the jar and use a relative path to it.
To give a concrete example:
Get the URL of the security configuration file you want to use
URL configLocation=YourClass.getClassLoader().getResource("resources/jaas.conf);"
Create the JavaLoginConfig configuration
Configuration secConfig=Configuration.getInstance("JavaLoginConf", new URIParameter(configLocation.toURI());
Set the configuration to the one you created in step 2
Configuration.setConfiguration(secConfig);

Load config file from a war

I have a Maven project that I'm trying to package as both a war and a jar. As part of my application / servlet initialisation (depending on whether I'm running the jar or the war), I need to read a file called server.ini. I've put the file in src/main/resources/server.ini and am trying to load it like so:
System.class.getResourceAsStream("server.ini");
However, this always results in null. What am I doing wrong?
The server.ini file should be in the root of a resources directory.
By placing it in the webapp you're making the file available via http, but you need it accessible on the classpath, which means that you should place it in the resources directory.
There's a good chance web.xml or context.xml is better suited to what you're trying to do, but...
Try putting server.ini in WEB-INF/classes, or do something like this.
The issue was that I was using the System classloader with an unqualified path, so it was expecting to find my server.ini in the java.lang package.
Since my file is in src/main/resources, I should just use the classloader of my current class, with an absolute path:
getClass().getResourceAsStream("/server.ini")
This works in both the war and the jar.
The "Preferred way of loading resources in Java" question has a great explanation of resource loading.

Spring RESTful Service as a WAR instead of JAR in Tomcat

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

How should I invoke a packaged spring project from another spring project?

I have two spring projects both using maven. The first is a client for some api and the second is a console program that, in part, utilises that client.
I have packaged up the client into a jar and referenced it in the pom for the console program.
I have managed to get this working, just about, but I am not very happy with the solution:
1) The first problem I ran into was that each of the context xml files were named "applicationContext.xml". Therefore, I couldn't work out any way to reference the context file in the client, without renaming it to something else e.g. clientContext.xml. This works but is there any other way to reference it explicitly?
2) The next issue was how to invoke the clientContext.xml from within the console program. To do this, I have added <import resource="osrdClientContext.xml"/> to the applicationContext.xml of the console program and this seems to allow it to correctly find all of the defined beans. I'm not sure if this is best practice though?
3) Within clientContext.xml, I need to reference a properties file and so have the line <context:property-placeholder location="classpath:api.properties" />. This works when running the client on its own but appears to get ignored (or fails to find the file) when running the console program. The api.properties file is in the root of the packaged jar for the client and the jar is in the classpath of the console program. The only workaround I have found is to manually copy the properties file into the console program, at which point it is found without any problem.
4) Both projects have a resources directory with sub-directories "dev", "beta" and "prod". This allows me to define different properties depending on the maven profile I want to run against. This works fine for the individual projects but when I package the client, it only includes the properties files for the profile I am running against (which makes sense). However, that then means if I run the console project against profile "beta", it will still run the client against whatever profile it was packaged against. It would be handy to be able to package all of the properties files and get the client to run in the same profile as whatever is depending on it. Is that possible/a good idea?
Ad 1: The common place to put your JAR-based XML contexts is inside META-INF/your/project/name folder. You can check for example spring-batch-admin project. Also nowdays it is more common to name the context files {name}-context.xml (e.g. central-context.xml).
By following the advice above, you should not have problems with name conflicts. However it should be possible to overcome such problem by using classpath* pseudo protocol in your import definition:
<import resource="classpath*:do/not/put/in/root/this-can-be-duplicate.xml"/>
Ad 2: This is completely legit. You can see the same practice in the Spring Batch Admin example as linked above. Just add the classpath: or classpath*: to the resource path.
Ad 3: That is very strange and I have no clue to what is going on there.
Ad 4: This is possible to achieve via Spring profiles (not Maven profiles):
<beans profile="dev">
<context:property-placeholder location="classpath:META-INF/dev/my.properties"/>
</beans>
or via new SpEL support:
<context:property-placeholder location="classpath:META-INF/#{systemProperties['my.jvm.property']}/my.properties"/>
However what I like is to have a default properties and then let the main application be able to override them. This means, that your configuration will be on a single place and not inside the JAR. You can achieve this via properties hierarchy:
<context:property-placeholder location="classpath:META-INF/my-default.properties,classpath*:META-INF/my-optional-overrides.properties"/>
UPDATE just discovered that <context:property-placeholder> has problems with SPeL. However you can still use SPeL (and even other property configurers) when defining the PropertyPlaceholderConfigurer manually (i.e. via <bean>).

Eclipse not able to find Spring configuration file

I am wetting my hands in Spring and using Eclipse along with Spring. I have written a very simple Spring application with eclipse to inject a property in a bean. However, when I am running my application, Spring is throwing exception and it seems that the Spring is not able to find the Spring configuration file. Below is the stacktrace --
INFO: Loading XML bean definitions from class path resource [Beans.xml]
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [Beans.xml]; nested exception is java.io.FileNotFoundException: class path resource [Beans.xml] cannot be opened because it does not exist
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:341)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
I have tried the following -- Give the full path in the ClassPathXmlApplicationContext method like --
ApplicationContext context = new ClassPathXmlApplicationContext("C:/Users/devshankhasharm/workspace/FinalPowerShell/src/src/main/Beans.xml");
I have also updated the ClassPath variable in windows to add the path for my spring configuration file. But nothing worked. Any idea would be highly appreciated.
Try this
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:Beans.xml");
And of course your Beans.xml must be in classpath.
Update or maybe
ApplicationContext context = new ClassPathXmlApplicationContext("file:src/main/Beans.xml");
Beans.xml should be in classpath. You cannot give full physical path of xml file for ClassPathXmlApplicationContext . Please check if Beans.xml is there in build path of eclipse.
As you are using a full filepath for your Beans.xml example, use
ApplicationContext context = new GenericXmlApplicationContext("C:/Users/devshankhasharm/workspace/FinalPowerShell/src/src/main/Beans.xml");
BUT it is not recommended to do this. Use the ClassPathXmlApplicationContext for this instead.
Then move Beans.xml into the classpath. The simplest way to do this is to move it to the root of your java source if not using Maven or src/main/resources if using Maven
If it's not much of a bother then try using Spring Tool Suite. It's a Spring friendly IDE based on Eclipse, so that you don't have to depend on spring/maven plugin configurations. All you have to do is go and create a Spring Project instead of Java project and rest all the settings will be handled for you.
If you are using Spring Tool Suite (STS), it may be the case that when you create a Maven project the src/main/resources directory was configured with "Excluded: .". In other words, STS sets your src/main/resources directory to have all its contents excluded from output by default.
How to fix it:
Project properties (Alt+Enter) -> Java Build Path -> Source
On src/main/resources, you may see "Excluded: ."
Select this item and click on Edit...
Remove the . exclusion pattern
Click OK. Voila!

Categories

Resources