Websphere App Server 6.1: Redeploy after web.xml change required? - websphere

In WebSphere Application Server 6.1, is it necessary to redeploy the application (WAR/EAR) every time a change is made to a web.xml descriptor file?

Depends on what you refer to by "a change is made to a web.xml descriptor file".
If you made a change to the web.xml file inside your IDE, then obviously this change has to somehow make it to the application server's world. Repackage your WAR file and deploy to WebSphere, for changes to take effect.
If you made a change to the web.xml file inside WebSphere's internal directories (the installedApps directory somewhere underneath the profile) - a practice I'd advise against - then a server restart would be sufficient for the changes to take effect. It goes without saying though, that your changes will disappear next time the application is deployed.

Related

Can you replace a Spring Boot jar while the application is running?

In our Linux environment applications are restarted periodically (the reasons aren't important here). It would be convenient for us to deploy new versions of an application by copying the application Spring Boot jar on top of the existing (old) jar thereby overwriting it and then simply wait for the application to restart (that is, the JVM running the application to restart).
However, this seems to not work. We get different kinds of errors - sometimes the app just hangs, sometimes we get a ClassNotFoundException. It's as if Spring Boot (or something inside Spring Boot) reopens the jar and expects it to be the same one it was when the application was originally started.
We had a look through Spring's common application properties, but didn't see anything appropriate. Is there a way to make this work? When we were using WAR files we configured the servlet container to unpack the WAR file and run from the unpacked version. Can we do something similar with Spring Boot?
First of all the errors you are experiencing can come from multiple sources. Usually replacing the file from a process is not a big problem as the whole file is loaded into memory before execution. Java is a little bit different, because the actual process that is running is the JVM and it only loads the jar file from disk. The JVM loads classes only on demand, this means if there was any class that was not loaded before it will try to load it and most likely fail, if the jar file is different. In the case of spring boot there are also other resources (such as HTML files) inside the jar file that are dynamically loaded.
You mentioned you are using a linux environment. If you can just replace your startup with a script you can just copy the jar and start it from the copied location:
#!/bin/bash
JAR_NAME="spring-boot.jar"
NEW_JAR_NAME=".$JAR_NAME" # Use an appropriate name here
cp $JAR_NAME $NEW_JAR_NAME
java -jar $NEW_JAR_NAME
rm $NEW_JAR_NAME
Now every time you start the application a copy is being made and started from there. You can replace the original jar and on the next restart the new application will load.
You coud also use rsync instead of cp to avoid copying the same jar twice, if the application is restarted multiple times without changing the jar.
It would be convenient for us to deploy new versions of an application
by copying the Spring Boot jar on top of the existing (old) jar and
then simply wait for the application to restart
Why would you do such a thing to yourself? You are trying solve a usecase that's against best practices, sound like asking for trouble just to avoid an app restart. When you are doing a deployment, you need to make sure the deployment went through, otherwise how will you troubleshoot if something goes wrong in your application, you will have one more variable in hand when you troubleshoot, i,e the uncertainty of current version of the code.
If you are having downtime while deploying (I am assuming thats why you want to limit the restarts), why don't you bring up another instance with the newer version of code and once its healthy shutdown the old one

Set Parent_Last on websphere 9

While using Websphere 7, I had in my EAR a nice little file called deployment.xml which told my WAS server to configure the deployment to PARENT_LAST. I had this file at
/MyEAR/META-INF/ibmconfig/cells/defaultCell/applications/defaultApp/deployments/defaultApp/deployment.xml
When moving to Websphere 9, it appears it is no longer honoring this directive. I go to the admin console and can see it thinks the EAR is deployed with PARENT_FIRST under "Class loading and update detection"
here is the text of the xml
<?xml version="1.0" encoding="UTF-8"?>
<appdeployment:Deployment xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:appdeployment="http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmi">
<deployedObject startingWeight="10" warClassLoaderPolicy="SINGLE" xmi:type="appdeployment:ApplicationDeployment">
<modules startingWeight="10000" uri="Provider_lfcPractice_ImplWeb.war" classloaderMode="PARENT_LAST" xmi:type="appdeployment:WebModuleDeployment"/>
<classloader mode="PARENT_LAST"/>
</deployedObject>
</appdeployment:Deployment>
Is there still a way to configure the EAR to deploy the war with PARENT_LAST in websphere 9?
This should still work. Check this Select installation options settings, it talks about the deployment.xml
Process embedded configuration
Specifies whether the embedded configuration should be processed. An
embedded configuration consists of files such as resource.xml,
variables.xml, and deployment.xml.
So make sure that that checkbox is selected, as it is off by default. Also if you are deploying via wsadmin script, make sure that you are using that option.
The other way, would be to select all the options after installation that you require, export that ear and compare it to the one that you are installing.
With Gas's comment it was clear it should work. What happened to me is that I had added maven nature to the EAR at one point. Bad idea. Even though I had already removed the maven nature, it corrupted the file
org.eclipse.wst.common.component
It was missing the line
<wb-resource deploy-path="/" source-path="/"/>
When I added that line back, my deployment.xml file began working as expected

Externalizing static content from a WAR and serve both on jetty

In my project I use Maven to package a web application to a WAR which is later deployed to Jetty using a custom Maven plugin on CentOS. The custom plugin is used by every project that deployes to a production environment. There is now a requirement that all static content (like web site text, properties) is packed outside of the WAR so that it can be changed in production without requiring a new release cycle. I am unsure how to achieve this externalization.
The Jetty server has the directory structure described in Jetty quick start guide. Currently, the web application already offers some .properties files which can be altered externally, and these reside in the resources/ directory. These files are moved here by the custom Maven plugin. The WAR resides in the webapp/ folder. One option for my problem is to use <packagingExcludes> of maven-war-plugin to not include e.g. *.xhtml and *.properties in the WAR. Later, I can use the custom Maven plugin to move excluded files to resources/ directory. But, I have a feeling this is not the correct way to externalize static content... Shouldn't xhtml files live in webapp/ folder while the only the properties file live in resources/ folder?
I have also researched the option of deploying the WAR as exploded, but I am unsure of the implications of such. Clearly, the changes in the exploded WAR files will be overwritten in the next deploy, but the idea is to do static changes both in development and production. Also, I am not sure how to achieve WAR "explosion", is it something that Jetty does for your WAR if configured in jetty.xml or do I have to extract the WAR before deploying?
Lastly, how do people serve static content in Jetty which can be altered in production? Do both the WAR and static files live side by side
The Jetty resources folder should not be used for application files. A J2EE web application (war) should be self-contained -- and in Jetty, reside only on the /webapps folder -- and its only binding to the container (Jetty servlet engine) is via the web.xml deployment descriptor.
Since property files may be read from the classpath and the Jetty resources folder is part of the system classpath, a property file there could be read by the web application class loader. Note that there are other ways to read property files as well and the Jetty resources folder should not be used for application properties. Also, the application may not be portable as other application servers have different forms of webapp classloader isolation.
If the below architecture approach does not work for you, then your only approach would be to expand (explode the war) in the /webapps folder and hope for the best when files are edited.
Tackling this from a different angle,
- if your web application depends on .properties and .xhtml files in order to function properly, then these files are probably not 'content'. The fact that there is a business process that requires them to to be updated ad hoc does not make them content.
- 'content' is something like text, images, and videos that is added, edited and removed by an administrative user. The application does not depend on it for correct execution, it merely reads and passes it on the browser.
Suggestions:
I would suggest that you deploy your application every time there is a change to the .xhtml or .properties files change. If the editors of these files are power business users, you might think of a git push-pull tool for them and a continuous build hook, so that when they make changes and push them to the git repository, the application gets tagged with a newer version and gets built and deployed. If there is a problem (tag not closed in xhtml), then it would be easy to roll back to the last tag.
Alternately, if the changes are minor (such as text descriptions), then modify the application to read them from an arbitrary external file (outside the webapp) -- a location that is provided to the webapp on startup. You can then package a 'default' version of the file in the webapp, but the code would attempt to look in the specified external location first.
I discovered that you can add HTML tags to properties and later use <h:outputFormat> to fetch these properties with parameters. Also, you can do pretty neat stuff with property files as described in MessageFormat API.
My solution was to keep the .xhtml files inside the WAR, but use simple HTML snippets properties from the default resource bundle which is based on a .properties file. These properties were included in the .xhtml using <h:outputFormat>and <h:outputText>. This allows the user to add simple styling like bold and underline to the snippets.
The properties file are copied to the Jetty resource folder using the custom Maven plugin, so I have kept the .properties files in the WAR. For some reason the Jetty resource folder has precedence over the packed .properties files, so this works out fine. Also, as Akber pointed out, I will have the default versions of the properties available if for some reason the WAR was moved to some other application server where the resource folder is not available.
Of course, with this approach the code can break if malformed HTML is placed inside the snippet properties, as pointed out by Akber, but it works for our application as it is very small. I may never have done this if this was a much larger application, but then I might have gone for a database based solution for adding static text (like Joomla/Drupal/Wordpress).

Spring in production

What is the best practice to make changes in beans.xml file in production environment?
Lets imagine Hello World application with one Interface and 2 Implementations. After creating jar and running JVM how can we change implementation in beans.xml without opening jar and reassembling it afterwards?
Is it any trick that permits having beans.xml outside the jar, but without knowing the full file-system path?
On top of suggestion made by OrangeDog, I would suggest considering leaving the beans.xml inside your deployed application AND using the PropertyOverrideConfigurer mechanism.
Configure an override configurer to point to some fixed path outside of the application, something like /opt/configuration/something/override.properties would be ideal. If you can't use an absolute path, you can always try to play with file:../../.. style of paths. Then you can list only the changed values within the override.properties file.
Don't have the XML in a JAR. Your application should be deployed in at least a WAR, which the app server will probably "explode". The folder WEB-INF/classes will be added to the classpath. You can make changes to the exploded XML here and the app server should detect this and reload the app.
Edit:
If you are using plain Java SE, you can use a system property to pass the location of the XML file. System.getProperty("property") in code and -Dproperty=value on the command line.

JSP debugging in IntelliJ IDEA

Does anyone know how to debug JSP in IntelliJ IDEA?
When I set breakpoint in my JSP files, those breakpoints never seem to take effect. The debugger never hits them. IDEA seems to think that the breakpoints are valid. I do see a red dot placed to the left of the line where I place my breakpoint.
I read in IntelliJ forum in this post that JSP files need to be under web-inf for debugging to work.
But then I also read that JSP files placed under web-inf won't be directly accessible by the user.
I am not sure who's really right.
For JSP debugging in Intellij there are some configurations that must be in order. The fact that Intellij always allows you to add a breakpoint on a JSP line does not necessarily imply that you’ve configured JSP debugging. In the following I refer to Intellij 8 configuration, w.r.t. previous versions you will need to do similar operations as the concepts are the same.
In order to enable JSP debugging you must do two steps: set a web application configuration in your project and add a web application server configuration.
Web application Configuration: in order to have JSP debugging, you must have a “web” facet in your project structure, pointing to the correct web.xml file. Depending on the kind of web application structure you are using, the facet may be detected automatically by Intellij (go anyway to check what it has done) or you may have to add it manually. Remember in the “Java EE build settings” tab to set as anable “Create web facet exploded directory”; if you don’t want duplications, a trick is just to enable it and point to your already existing directory.
(Web) Application server: Go to “edit configurations”, there you have to add to configurations an application server, not launch the web server as an application like any other. In this way Intellij will be able to intercept JSP calls. In the list of application servers, you should have the default one, Tomcat. Be sure to have a local Tomcat installation before you do this, and point to that when adding the web application server. The last trick is going to the “Deployment” tab and selecting as “Deployment source” the same facet that you configured in the previous step.
The same configuration works if you want to use another web application server, I tested it with the latest Caucho Resin releases and debugging works fine (it didn’t with the previous Intellij and Resin combinations).
If you don’t see Tomcat in the list of available application servers to add, check the plugins in the general Intellij settings pane: in the latest releases, more and more functionality has become “pluggable”, and even very basic functions may be disabled; this plugin is called “Tomcat integration”.
Finally, it is surely not true that JSP files need to be under WEB-INF to be under debugging.
For remote JSP debugging (which also applies to localhost) you'll need to install the JSR45 support plugin. Please note this feature is only supported in the Ultimate edition of IntelliJ, not the community edition.
Go to Preferences > Plugins, search for the JSR45 plugin, and
enable it.
Create a run configuration: Run > Run Configuration > click the + button, and pick JSR45 Compatible Server, and then in the dialog that opens, select Remote, and set server host and port. Setting Application Server: Generic should work fine.
Make sure you set the correct port in Startup/Configuration > Debug.
Open the module settings (F3 on the project folder), and add a Web Facet under Facets, and under Web Resource Directories specify your JSP root folder.
Click the Configuration... button, and select the folders with the beans, classes and libraries that your JSPs depend on.
Now JSP breakpoints should work, provided that you started your server with the proper debug arguments.
If you have a maven project with auto-import enabled then you might want to disable auto-import because every time the auto-import is triggered your library settings will be reset.
Also see:
https://www.jetbrains.com/help/idea/run-debug-configuration-jsr45-compatible-server.html
Anyway, you need to launch the Tomcat in IDEA, not from a remote Tomcat.
Please make sure, that in you tomcat's conf/web.xml suppressSmap is not enabled as support of JSR45 is required by IntelliJ's debugger.
It should look like this:
<init-param>
<param-name>suppressSmap</param-name>
<param-value>false</param-value>
</init-param>
From https://tomcat.apache.org/tomcat-7.0-doc/jasper-howto.html
suppressSmap - Should the generation of SMAP info for JSR45 debugging be suppressed? true or false, default false.
If you are using the Intellij debugger you can get the value of an individual attribute by putting a breakpoint inside JSP and evaluating the expression this.jspContext.request.getAttribute("attributeName").
Note that this may return a Java Object type, and you may have to cast it to the correct type. Also if you launch a remote Tomcat the IDEA won't hit any breakpoints, so you need to launch the Tomcat in debug mode from inside the IDEA.
For the second part of your question ("jsp files placed under web-inf won't be directly accessible by user") that is correct. To allow users to access JSP files in the WEB-INF folder servlet and servlet-mapping entries need to be made in the web.xml file for each JSP page.

Resources