We have a web application on JBoss 7.2.
Now I want to display the build timestamp in my UI for debugging purposes, so I added
a properties file looking like that:
version=${pom.version}
build.date=${timestamp}
in the POM properties:
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
</properties>
On build, this successfully generates a .properties file with the correct values, e.g.
version=0.1-SNAPSHOT
build.date=2021-08-25 12:00
However, when deployed, that properties file isn't available anymore. I get a FileNotFoundException when my frontend bean tries to access the file via
String propertyPath = "src/main/resources/version.properties";
try (InputStream properties = new FileInputStream(propertyPath)) {
Properties prop = new Properties();
prop.load(properties);
}
...
Now of course I can add the properties to my standalone.xml, but I wasn't able to replace the values during build time. Any tips on how to make it work?
The problem you are experiencing makes total sense. You are attempting to read the file using the source code path src/main/resources/version.properties. Since you have built your app and created a jar out of it, the file in question no longer resides under this path.
You should therefore attempt to load the file using the classloader. Check more on that here.
Related
I explain my problem;
I have a web app developed using Vue.js and Spring Boot, this application working a PDF sheet and saves the file that is generated by Java, I use two lines of code to separate my development part from the production part (I leave you the 2 lines of code like this you understand the concept well)
FileReader leggoFile = new FileReader(System.getProperty("user.dir") + "/temp/webapps/foolder/foolder/file.pdf");
// FileReader leggoFile = new FileReader(System.getProperty("catalina.base") + "/temp/webapps/foolder/foolder/file.pdf");
This whole application is built using the "bootWar gradle plugin" which returns me a .war which I will then upload to a Tomcat server;
My goal is this:
I would like to set a single environment variable so that if I want to build the project I don't have to comment/uncomment that line for example:
FileReader leggoFile = new FileReader({{variableEnvironment}} + "/temp/webapps/foolder/foolder/file.pdf")
my question is this:
How dp Gradle and Spring Boot handle environments? Is there a way to separate environments? Is this possible or should I start thinking differently?
I tried to search on something but unfortunately I was tied to the problem that I don't understand how the .war file is generated through the BootWar Gradle plugin, also searching on the internet I understood that environment Gradle and environment Spring are two separate things but in general even if I know the line of code is wrong in the beginning my question is always the same:
How are environment variables handled in Spring and Gradle?
With Spring Boot, you can add properties to your application by adding an file named application.yaml to your resources folder (src/resources/). In addition you can add properties through application-{profile}.yaml to add properties only for given Spring profiles. For instance application-test.yaml would only be read if "test" is an active profile. When booting up the application, Spring will first read application.yaml, then any profile-specific YAML-files, such that any overlapping properties are replaced.
There are several approaches to injecting the property. A simple solution is to add a field to your component annotated with #Value("${PATH}) and replace PATH with the property's path in the YAML.
I have a pretty simple servlet setup with
Jersey
no web.xml
Tomcat 9
Maven for creating the .war and handling dependencies
Now I need to deploy a test and a production version of the servlet on the server and I a trying to use the individual context.xml file for each environment. A quote from the docs
Individual Context elements may be explicitly defined:
In individual files (with a ".xml" extension) in the $CATALINA_BASE/conf/[enginename]/[hostname]/ directory. The context path and version will be derived from the base name of the file (the file name less the .xml extension). This file will always take precedence over any context.xml file packaged in the web application's META-INF directory.
All this also sounds easy here:
To give an example: if we wanted to deploy three installations of an application for test, stage and production, we would create three context.xml files:
tomcat/conf/catalina/localhost/test.xml
tomcat/conf/catalina/localhost/stage.xmltomcat/conf/catalina/localhost/prod.xml
And then deploy the same .war file three times as:
tomcat/webapps/test.war
tomcat/webapps/stage.war
tomcat/webapps/prod.war
And each installation would pick up its specific configuration automatically.
You can also read this documentation:
For Tomcat 5.0.x and later, WTP 2.0.x and later offers the opportunity to write the contexts to separate XML files in the proper folder (typically conf/Catalina/localhost) according to the requirements of that particular version. This behavior is enabled by checking the Publish module contexts to separate XML files option in the Server Options section of the Tomcat server editor. Note that only contexts for added projects will be written to separate XML files. Manually added contexts in server.xml will remain there.
There are several instructions, how to retrieve a value from the context.xml. For example:
<Environment name="companyName" value="My Company, Incorporated" type="java.lang.String" />
Can be used by
InitialContext context = new InitialContext();
Context xmlNode = (Context) context.lookup("java:comp/env");
String companyName = (String) xmlNode.lookup("companyName");
But this was listed for a Spring setup, how can this be done in a Jersey ResourceConfig based application/servlet?
For example:
#ApplicationPath("/")
public class MyMain extends ResourceConfig {
private final Logger logger = LoggerFactory.getLogger(MyMain.class);
public MyMain() {
try {
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
String myEnv = (String) envCtx.lookup("my-env");
this.logger.debug("Env: {}", myEnv);
} ...
is running into NamedExceptions: javax.naming.NameNotFoundException: Name [my-env] is not bound in this Context. Unable to find [my-env].
Is there any way to get the context configuration with Jersey, or do I need to use a different approach?
I also have no clue, how to debug the InitialContext. So the file is there and it is read by Tomcat, but I don't know how I can access it in the application. Do I need to use ServletContext.getInitParameter() instead - and how?
Update
My Eclipse setup seems to be the problem, because the published xml file is not the original, individual context.xml in my /Catalina/localhost folder. Is there any way to make sure that the original file is published in the Eclipse-Tomcat server?
"Publish module contexts to separate XML files" is checked. What is Update context paths? in publishing options (no effect visible, though)?
Here is the :
I'm managing many jobs in Jenkins by DSL plugin. That plugin is using .groovy definitions so I think even if someone doesn't use Jenkins but using groovy may be able to help.
Generally, I want to create an additional file, that may be a groovy file, JSON or YAML, whatever. It important is the possibility to connect that file with my .groovy file.
In that file, I'm defining variables(rather just strings) for example address IP or other stuff
eg.
ip_gitlab: 1.2.3.4
default_user: admin
In my groovy files, I want to be able to use these variables.
That approach is possible in groovy?
I suggest use a property file as #JBaruch wrote
ip_gitlab=1.2.3.4
default_user=admin
And load it
Properties properties = new Properties()
File propertiesFile = new File('test.properties')
propertiesFile.withInputStream {
properties.load(it)
}
Then you can use it, get ip for example:
def ipPropertyName= 'ip_gitlab'
properties."$ipPropertyName"
Make groovy file and define some general information and use load.
E.g., hello.conf (written by groovy)
build_name = 'hello'
build_config = [
'git': 'your git repository',
'build_job': ['bulid_a', 'build_b']
]
And use it by load
load 'hello.conf'
println(build_name)
for (job in build_config['build_job']) {
build job: job
}
if you want a Jenkins specific answer:
There's a Config File Provider Plugin to jenkins.
You can store config/properties files via Managed files.
Go to Manage Jenkins>Managed files and and create a new file. It supports .groovy, .json, .xml and many others.
Once you have that, you can load the said file inside a job using the Provide Config file checkbox which will load the file into an env variable automatically.
I'm using Liquibase in my Scala application which is packaged in a JAR using sbt assembly. When the changelog location is supplied using a local file path, everything works fine. In order to deploy using only the JAR, I'd like it to look inside the JAR instead. How can I do this?
Current Setup:
build.sbt includes "org.liquibase" % "liquibase-core" % "3.3.5" as a dependency
Run:
val liquibaseChangeLog: String = (from config)
val liquibase = new liquibase.Liquibase(liquibaseChangeLog, resourceAccessor, liquibaseConnection)
liquibase.update(new Contexts())
I'd like to set liquibaseChangeLog to a classpath like org/my_org/my_project/changelog.xml but I get an error:
Exception in thread "main" liquibase.exception.ChangeLogParseException: org/my_org/my_project/changelog.xml does not exist
liquibase.parser.core.xml.XMLChangeLogSAXParser.parseToNode(XMLChangeLogSAXParser.java:100)
liquibase.parser.core.xml.AbstractChangeLogParser.parse(AbstractChangeLogParser.java:17)
Looking through the Liquibase source in this stack trace, I see that it explicitly wants a file. Is there a way to look in the JAR instead?
So, here's the deal.
I'm using Spring Framework to develop a appointment app.
Everything's going fine in my localhost, even the email send part.
But when i pass the project to my weblogic, the resource.loader.path property appears not to load.
Here's the important part of my code:
Properties prop = new Properties();
prop.setProperty("resource.loader", "class");
prop.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
prop.setProperty("class.resource.loader.path", "../jsp/email-templates");
VelocityEngine.init(prop);
Template template = VelocityEngine.getTemplate("user-response.jsp");
As i said, just the important part of my code. Basically is configured like this with a Properties Object and the VelocityEngine.getTemplate() loading the user-response.jsp file that are inside the folder mentioned above.
As i said, in my localhost, he just works fine but in weblogic appears that way:
org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource '..nulluser-response.jsp'
For some reason, the class.resource.loader.path property do not load in weblogic.
So... someone has already been through this problem? Any ideias of what's wrong?
Obs.: The two projects (localhost and weblogic) are the same, using a version control software (bazaar)
I'd recommend making it relative to the CLASSPATH. If you put the /email-templates folder under WEB-INF/classes and make the load path "email-templates" it should work.