Quartz.properties - java

I developed an EAR using Quartz API. I have put my quartz.properties file in the classpath(WEB-INF/classes in war). Added following lines to web.xml file
<context-param>
<param-name>config-file</param-name>
<param-value>/WEB-INF/classes/quartz.properties</param-value>
</context-param>
But Quartz still loads the default properties file from the quartz.jar

I believe that config-file should be a servlet parameter, not a context parameter, like the example given at http://www.openscope.net/2010/02/05/quartz-scheduled-jobs/. See also quartz docs on QuartzInitializationServlet here.

Try with /quartz.properties instead of /WEB-INF/classes/quartz.properties.

The param-value you had inserted is interpreted as a string, not a path.
I believe that upon initialization, the config file is being searched in "WEB-INF\classes" folder... whereas you meant something like "\webapps\\WEB-INF\classes.
(would help to add logs,at least for the initialization part...)
since the resource "WEB-INF\classes\quartz.properties" isn't found, the default quartz.properties is loaded.

You have an error between maven dependencies
erase from your pom.xml this dependencie
<!-- Quartz spring-support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-support</artifactId>
<version>2.0.6</version>
</dependency>
And relaunch...

Related

Change CodeStar Spring MVC project to Spring Boot

I have a Spring Boot project that works perfectly when run in IDE. I would like to run this via AWS CodeStar. Unfortunately, the default Spring template created by CodeStar uses Spring MVC.
I cannot just overwrite the default Spring MVC project with my Spring Boot project (it doesn't work). I can copy some of my resources to the MVC project, for example index.html and that works. But then features like Thymeleaf don't work. For this and other reasons, I would like to change the provided Spring MVC into the Spring Boot structure I already have.
I followed the instructions here: https://www.baeldung.com/spring-boot-migration
Unfortunately, this doesn't help. I can create Application Entry Point and add Spring Boot dependencies without the app breaking. But when I remove the default dependencies or the configuration associated with the MVC, the app breaks. When trying to reach the URL, I get a 404 error with description:
The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Debugging this error message (e.g. https://www.codejava.net/java-ee/servlet/solved-tomcat-error-http-status-404-not-found) didn't help.
The message seems like it's connected to the web resource. I have my web resources in folder resources as well as webapp/resources. And Spring Boot doesn't need any location configuration, right? It uses this location by default.
Can somebody tell me what things to remove and what to add to be able to use my existing Spring Boot project?
EDIT:
This is a link to a default template for AWS CodeStar Spring web application: https://github.com/JanHorcicka/AWS-codestar-template
And this is my Spring Boot project structure:
I realize that you indicated that previously you tried to use your Spring Boot project with some modifications without success, but I think it could be actually a possibility to successfully deploy your application on AWS CodeStar, and it will be my advice.
I also realized that in your screenshot you included several of the required artifacts and classes, but please, double check that you followed these steps when you deployed your application to AWS CodeStar.
Let's start with a pristine version of your Spring Boot project running locally, without any modification, and then, perform the following changes.
First, as indicated in the GitHub link you shared, be sure that you include the following files in your project. They are required for the deployment infrastructure of AWS:
appspec.yml
buildspec.yml
template.yml
template-configuration.json
The whole scripts directory
Please, adapt any necessary configuration to your specific needs, especially, template-configuration.json.
Then, perform the following modifications in your pom.xml. Some of them are required for Spring Boot to work as a traditional deployment and others are required by the deployment in AWS CodeStar.
Be sure that you indicate packaging as war:
<packaging>war</packaging>
To ensure that the embedded servlet container does not interfere with the Tomcat to which the war file is deployed, either mark the Tomcat dependency as being provided as suggested in the above-mentioned documentation:
<dependencies>
<!-- … -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- … -->
</dependencies>
Or exclude the Tomcat dependency in your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
If necessary, apply this exclusion using some kind of profile that allows you to boot Spring Boot locally and in an external servlet container at the same time.
Next, parameterize the maven war plugin to conform to the AWS CodeStar deployment needs:
<build>
<pluginManagement>
<plugins>
<!-- ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
<warName>ROOT</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<!-- ... -->
<plugins>
</pluginManagement>
</build>
I do not consider it necessary, but just to avoid any kind of problem, adjust the name of your final build:
<finalName>ROOT</finalName>
Lastly, as also indicated in the Spring documentation, be sure that your MyProjectApplication - I assume this class is your main entry point subclass SpringBootServletInitializer and override the configure accordingly, something like:
#SpringBootApplication
public class MyProjectApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyProjectApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(MyProjectApplication.class, args);
}
}
Please, feel free to adapt the class to your specific use case.
With this setup, try to deploy your application and see if it works: perhaps you can find some kind of library dependencies problem, but I think for the most part it should work fine.
At a first step, you can try to deploy locally the version of the application you will later deploy to AWS CodeStar following the instructions you provided in your project template, basically, once configured with the necessary changes described in the answer, by running:
mvn clean package
And deploying the generated war on your local tomcat environment. Please, be aware that probably the ROOT application already exists in a standard tomcat installation (you can verify it by inspecting the webapps folder): you can override that war file.
For local testing you can even choose a different application name (configuring build.finalName and the warName in your pom.xml file): the important thing is verify if locally the application runs successfully.
If you prefer to, you can choose to deploy the app directly to AWS CodeStar and inspect the logs later it necessary.
In any case, please, pay attention on two things: on one hand, if you have any absolute path configured in your application, it can be the cause of the 404 issue you mention in the comments. Be aware that your application will be deployed in Tomcat with context root '/'.
On the other hand, review how you configured your database access.
Probably you used application.properties and it is fine, but please, be aware that when employing the application the database must be reachable: perhaps Spring is unable to create the necessary datasources, and the persistence manager or related stuff associated with and, as a consequence, the application is not starting. Again, it may be the reason of the 404 error code.
To simplify database connectivity, for testing, at first glance, I recommend you to use simple properties for configuring your datasource, namely the driver class, connection string, username and password. If that setup works properly, you can later enable JNDI or what deemed necessary.
Remember that if you need to change your context name and/or define a datasource pool in Tomcat you can place a context.xml file under a META-INF directory in your web app root path.
This context.xml should look like something similar to:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/">
<Resource name="jdbc/myDS"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
url="jdbc:mysql://localhost:3306/myds"
driverClassName="com.mysql.jdbc.Driver"
username="root"
password="secret"
/>
</Context>

How to lookup property parameter in web app for log4j2?

I want to configure log4j2 to lookup the logging path dynamically from web startup (tomcat).
From the docs (http://logging.apache.org/log4j/2.x/manual/lookups.html) there is a web: lookup with different parameter possibilities.
At first I'm trying the provided example:
<Appenders>
<File name="ApplicationLog" fileName="${web:rootDir}/app.log"/>
</Appenders>
Result: ERROR Unable to create file ${web:rootDir}/app.log java.io.IOException
I also tried the other buildin properties like servletContextName and contextPath with the same error message.
So I'm probably still missing something important. But what?
Add log4j-web JAR
Your usual log4j-core JAR file on its own is not enough.
There is an additional component called log4j-web.
For automatic replacement of the ${web:...} placeholders in your logging configuration, you need the additional log4j-web JAR file. If you don't have this log4j-web JAR file, then Log4j2 itself will still work, but it will not replace these placeholders with anything. So for example ${web:rootDir} will just end up as the literal text ${web:rootDir}.
Perhaps you are missing that dependency in your project?
Log4j-web on Maven Central
Is ${web:rootDir} a value? The placeholder is not replaced by its real value.
In the page you can red:
Information on how to use Lookups in configuration files can be found in the Property Substitution: http://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution

Getting property from pom.xml within java

I have a maven project, and in the pom.xml I set properties as such:
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>myArtifact</artifactId>
<name>SomeProject</name>
<packaging>jar</packaging>
<properties>
<some-system-property>1.9.9</some-system-property>
</properties>
<...>
</project>
I want to pull the some-system-property value from within the java code, similar to
String someSystemPropery = System.getProperty("some-system-property");
But, this always returns null. Looking over StackOverflow, most of the answers seem to revolve around enhanced maven plugins which modify the code - something that's a nonstarter in my environment.
Is there a way to just get a property value from a pom.xml within the codebase? Alternatively, can one get the version of a dependency as described in the pom.xml (the 1.9.9 value below):
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
</dependency>
</dependencies>
from code? Either one would solve my needs
Those are Maven properties that apply during the build, not runtime system properties. One typical approach is to use Maven resource filtering to write the value into a properties file in the target directory.
Maven properties and not system properties.
Generally you should set the system property for a maven plugin that is triggering the execution:
surefire for unit tests,
exec for execution,
jetty or similar for starting a web container
There is also properties maven plugin than can set properties:
http://mojo.codehaus.org/properties-maven-plugin/set-system-properties-mojo.html
Property values are accessible anywhere within a POM by using the notation ${X}, where X is the property, not outside. All properties accessible via java.lang.System.getProperties() are available as POM properties, such as ${java.home}, but not the other way around. So for your java code, it will need to scan the pom.xml as a xml parsing use case, but not sure why you want to do it.

org.springframework.web.context.ConfigurableWebApplicationContext.setId(Ljava/lang/String;) and chain reaction

I was trying to make a web application (not coded by me) to run, but, upon deployment, I am getting the following exceptions.
java.lang.NoSuchMethodError: org.springframework.web.context.ConfigurableWebApplicationContext.setId(Ljava/lang/String;)V
I have already checked and validated that there are no version conflicts for the spring-blabla jars in the WEB-INF/libs folder (I am using spring version 3.2.0.M1) and the dependecies in the pom.xml file have the following form.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
I have been quite desperate, so, as a last resort, I checked a chinese site and experimented with the following listener in the *web.xml*file
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
under the already existing one:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
When I am running the application, I am no longer receiving the previous exception, but another one,
Context initialization failed
org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.web.context.support.XmlWebApplicationContext]: Constructor threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.jndi.JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()Z
and I really have no idea what to do ...
It's very likely your runtime is reading Spring 2.0 instead of 3.2. Take a look at Spring 2 ConfigurableWebApplicationContext, it doesn't have setId(String) method.
I would start debugging the problem by checking the jar/war file, see if any duplicate version of Spring. Also check the web container classpath (eg: tomcat lib folder). If there's a Spring 2 jars in there it could cause confusion

Extending spring based app

I have a spring-based Web Service. I now want to build a sort of plugin for it that extends it with beans. What I have now in web.xml is:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/*-configuration.xml</param-value>
</context-param>
My core app has main-configuration.xml which declares its beans. My plugin app has plugin-configuration.xml which declares additional beans. Now when I deploy, my build deploys plugin.jar into /WEB-INF/lib/ and copies plugin-configuration.xml into /WEB-INF/classes/ all under main.war.
This is all fine (although I think there could be a better solution), but when I develop the plugin, I don't want to have two projects in Eclipse with dependencies. I wish to have main.jar that I include as a library. However, web.xml from main.jar isn't automatically discovered. How can I do this? Bean injection? Bean discovery of some sort? Something else?
Note: I expect to have multiple different plugins in production, but development of each of them will be against pure main.jar
Thank you.
I think there is a simpler approach:
In your host application (the webapp) define something like the following contextConfigLocation parameter:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/META-INF/foo/*-configuration.xml</param-value>
</context-param>
The crucial parts are classpath*:as it results in scanning the entire classpath for config files matching the following pattern. If you only use classpath: the lookup will stop at the first file found. It also won't traverse JARs if not starred correctly.
The second crucial part is having at least one non-wildcarded basepath for the lookup to work. This is due to Classloader traits that only reliably returns all resources if they contain a base path (see the Javadoc on PathMatchingResourcePatternResolver for details).
What you now have to do with your plugin projects is place your plugin-configuration.xml in /META-INF/foo/, package that as JAR and place it into your classpath (in case you build with Maven just add the dependency).
On application start Spring will now also pickup all config files from your plugins and build the ÀpplicationContext` from em.
You also might wanna checkout another post I did on application modularity with Spring: How do you make a multi-module spring configuration?
Instead of /WEB-INF/classes/*-configuration.xml, try classpath:*-configuration.xml
You can also list configuration files, each on a new line.
You will have to make sure that main.jar ends up in WEB-INF/lib, if you're not using maven you can do this in eclipse by marking you webapp as dependent on the project that creates the main.jar, via the project properties.

Categories