Tomcat 8, publish 2 .war under same root directory - java

I have a Tomcat 8 instance which is used to publish multiple web applications.
As today, I have a Spring architecture which produces 2 .war:
Front-end
Back-end
And the result is the following:
http://localhost:8080/my-front-end
http://localhost:8080/my-back-end
What I would like to achieve is to have a common root path for both these wars. Is this something I can do in Tomcat? In JBOSS or IIS I can use the concept of "Virtual Directory" to achieve that.
My intended result is the following:
http://localhost:8080/my-app/my-front-end (my-front-end.war)
http://localhost:8080/my-app/my-back-end (my-back-end.war)

The Tomcat documentation says to use # in the name.
Context Name Base File Name Example File Names
/foo foo foo.xml, foo.war, foo
/foo/bar foo#bar foo#bar.xml, foo#bar.war, foo#bar
So use these names for your war files:
my-app#my-front-end.war
my-app#my-back-end.war

Set the context paths: /my-app/my-front-end and /my-app/my-back-end respectively.
For example, if you are using Spring Boot, then put:
server.contextPath=/my-app/my-front-end
and
server.contextPath=/my-app/my-back-end
in application.properties file.
If you cannot modify the application's source code, here you can find out how to configure Tomcat to get the same result.

Related

Want to change the context path in Spring boot application in an external Tomact server version 9

I want to deploy a Spring boot application in an external Tomcat server version 9. I am able to deploy it and working the endpoints also. But properties I have set in application.properties file those are not working. Like server.servlet.context-path=/myapp is is not working instead the context path which I am getting is http://localhost:8080/myapp-0.0.1-SNAPSHOT/api/ping.
I am using 2.3.10.RELEASE and Java 1.8 and Tomcat version 9.0.46 Can anyone please help me out with this.
But everything is perfectly working on embedded tomcat. Thanks in advance and any suggestion, comment is highly appreciated.
Can anyone please help me with how I can do this - My war file name would be myapp-0.1.war but the context path of the application would be like this localhost:8080/myapp/api/ping
Use finalName property in your build file (pom.xml for maven)
<finalName>myapp</finalName>
When you run a Spring Boot application in an external servlet container, the server.* properties do not apply.
If you are willing to change the naming convention you can drop a WAR file named myapp##0.1.war in the $CATALINA_BASE/webapps directory and benefit from parallel deployment (cf. parallel deployment).
If you want to stick to your naming convention, you can create a folder for your WAR files (e.g. $CATALINA_BASE/webapps-available) and create a deployment descriptor $CATALINA_BASE/conf/<engine_name>/<host_name>/<context_path>.xml (in your case probably $CATALINA_BASE/conf/Catalina/localhost/myapp.xml) with the following content:
<Context docBase="${catalina.base}/webapps-available/myapp-0.1.war" />

Spring Boot - Profiles (application.properties) to define baseUrl for HTTP requests

The situation is that I have two api projects, API A does HTTP requests to API B. Both API's are deployed to a development and production environment.
What I want to achieve is the following: Build the project based on a specific profile (dev or prod) so that the code can use a particular baseurl to talk with the correct api on the correct environment.
So if I build API A based on prod flag, I want it to use the specific url to make http requests to API B that is deployed on it's own prod environment.
It looks like you're referring to profiles of maven, however you should probably check out spring profiles. The concept should change :
You're not supposed to build different artifacts for different environments.
Instead create a spring profile in service A:
application-dev.properties:
url.addr=dev-service-host:1234
application-prod.properties:
url.addr=prod-service-b-host:4321
Then run the application with --spring.profiles.active=dev (or prod) flag.
Spring boot will load the correct definitions automatically because the dev/prod matches the suffix of properties file
You can define Spring-Boot profile as:
spring.profiles.active=prod
You also should have profiled .properties files in resources:
in application-dev.properties you should have api.b.url={api_b_url_on_dev_environment}
in application-prod.properties you should have api.b.url={api_b_url_on_prod_environment}
Or if you don't want to recompile your application after changing properties you may use outside .properties files.
In order for them to be included during app's deployment do the following:
in some config directory add application-dev.properties and application-prod.properties
deploy you app with the following properties: --spring.profiles.active=dev and --spring.config.additional-location=config/application.properties
This way the outside profiled properties will be included in deployment process. These .properties files have the highest priority in Spring.

Does depedent project in java take log4j config of parent project?

I am having project A and project B, A has jar dependency of project B. I have defined log4j.xml in project A but I am not able to see logs of sub-project(B.jar) in file appender as well as tomcat server console. Does project B will take log4j.xml form parent project A or not then which config does it use?
There is one log4j config for your entire JVM (unless you're working in a containerized environment using class loaders and.... that's not what's described).
Missing log messages implies that the configuration from log4j either (a) isn't what you think it is (i.e. a different log4j.xml is being used) or (b) doesn't have the right settings for the missing log lines.
Adding the following to the JVM at startup may help:
-Dlog4j.debug
It may also be possible to browse the log4j settings via MBeans in jconsole.
If you want all apps (WAR files) in a Tomcat instance to have the same logging configs, the simple solution is to arrange that all WAR files have a copy of the same config file.
If you want the apps to share a common logging framework (with a single configuration), then you should consider using Context Selectors, as described in the Log4j 2 documentation.
Using Context Selectors
There are a few patterns for achieving the desired state of logging separation using ContextSelectors:
Place the logging jars in the container's classpath and set the system property log4j2.contextSelector to org.apache.logging.log4j.core.selector.BasicContextSelector. This will create a single LoggerContext using a single configuration that will be shared across all applications.
Place the logging jars in the container's classpath and use the default ClassLoaderContextSelector. Follow the instructions to initialize Log4j 2 in a web application. Each application can be configured to share the same configuration used at the container or can be individually configured. If status logging is set to debug in the configuration there will be output from when logging is initialized in the container and then again in each web application.
Follow the instructions to initialize Log4j 2 in a web application and set the system property or servlet context parameter log4j2.contextSelector to org.apache.logging.log4j.core.selector.JndiContextSelector. This will cause the container to use JNDI to locate each web application's LoggerContext. Be sure to set the isLog4jContextSelectorNamed context parameter to true and also set the log4jContextName and log4jConfiguration context parameters.
The exact method for setting system properties depends on the container. For Tomcat, edit $CATALINA_HOME/conf/catalina.properties. Consult the documentation for other web containers.
I don't think there is a direct equivalent in Log4j 1.x.

Want to access static resource using CAMEL, CXF and Karaf

I am new to CAMEL, CXF and Karaf.
I want to access static file using CAMEL with CXF and KARAF.
Wanted to know the best way to do that.
I have searched through net and found that CXF based rest web service can be written for the same.
Is there any other simpler way for this.
We are using jboss FUSE server.
To solve this problem we can define a redirect-list which will contain pattern of static resources you want to serve and the CRX default servlet will take care of forwarding to the specific resource please refer the following url for more information
Redirecting requests and serving the static content
web.xml file which does what is described above
Got a better way to do the same.
Step 1
Add <_wab>src/main/webapp/ tag in you maven pluggin so that your bundle can be treated as WAB by karaf container.
Use and to declare your custom context path.
By default maven will take Bundle-SymbolicName as context.
Step 2.
Write web.xml. Place it under /src/main/webapp/WEB-INF.
Step 3.
Place your static resource file under webapp folder.
Step 4.
Build the code to generate bundle jar using maven command mvn clean install and deploy the jar in karaf
Step 5
Use below link to access the static resource.
http://:8181//

Controlling the classpath in a servlet

My servlet application includes a number of library .jars, some of which contain embedded log4j.xml or log4j.properties files. I'd like to ensure that log4j finds my log4j.xml first! I've tried searching for some specification of the priorities of the various classpath elements in a servlet (e.g. does WEB-INF/classes always precede WEB-INF/lib?), or some way to configure or tweak the servlet's classloader so that a given resource directory appears early in the classpath. So far, I've drawn a blank. Any suggestions on ensuring that a servlet .war file loads the correct log4j.xml via the classloader?
Tomcat 8.5
Ditto Tomcat 8.0.
See documentation: Class Loader HOW-TO.
Tomcat 8.0
The answer is simple, taken from the Tomcat documentation page, Class Loader HOW-TO. In particular notice the use of the /WEB-INF/ directory/folder.
Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:
Bootstrap classes of your JVM
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
System class loader classes (described above)
Common class loader classes (described above)
If the web application class loader is configured with <Loader delegate="true"/> then the order becomes:
Bootstrap classes of your JVM
System class loader classes (described above)
Common class loader classes (described above)
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
Tomcat 6
Excerpted from Tomcat 6 page, Class Loader HOW-TO.
Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:
Bootstrap classes of your JVM
System class loader classes (described above)
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
$CATALINA_HOME/lib
$CATALINA_HOME/lib/*.jar
As far as I understand the resource selection from the classpath is non-deterministic (from the point of view of the app developer). Even if the same file is loaded consistently the behaviour could change:
1. When you upgrade the version of your current container.
2. If you switch containers.
The simplest solution will be to remove embedded log4j config files from library jars. It is almost never a good idea to embed log4j config's as it leads to the problem you are seeing here...
Are they third party jars or jars you developed?
We the Spring Log4jConfigListener in our web.xml file.
You can specify as a context parameter the location of the log4j config file, i.e. you could set it as /WEB-INF/log4j.xml
Would this be an option for you? If you're not using Spring I know that you can set the Log4j location programatically which might also work.
In my experience, WEB-INF/classes typically takes precedence over jars in WEB-INF/lib, however, that also depends on the servlet container you use (I could never figure out the behavior of JRun, for instance). It would help immensely if you could tell me which container you're using.
Also, are you certain that the offending log4j configuration is in a jar in WEB-INF/lib? Typically, when I've run into classpath problems in a servlet container situation, it's because of libraries that reside outside of the web app.
The servlet specs recommend that web app classloaders load their own classes before delegating to the container's classloader (SRV.9.7.2), but since this is counter to the Java spec, not all vendors do this by default (in fact Tomcat is the only container I've used that does this by default). With that said, it's always possible to configure your container's web app classloading behavior. If you tell me which container you're using, I may be able to help you (specifically, I have done this successfully before on WebLogic, WebSphere, Glassfish and JRun)).
If you're unable to control the classpath, since Tomcat is setting it for you, are you at least able to set a system property for log4j.configuration? I believe that location pointed to by that property can be set outside of the classpath.
If not, another approach, although an ugly one, would be to explicitly run one of the configurators yourself in your application code.
You need to have log4j.properties in your CLASSPATH. The best place is under WEB-INF/classes.
You also have to make sure that you use your version of log4j.jar. So, put it in WEB-INF/lib, just to make sure you are not using one from tomcat folders, since it may cause strange classloading issues.

Categories