jetty unknow domain 404 error page - java

I have two webapps on one jetty server. Each has own domain, defined in jetty-web.xml, for example example1.com and example2.com. This is working fine. Now, if someone will point some other domain name(let it be example3.com) to my server, and tryed to access it by this name - server will not found context configuration for this new domain and will send default responce with list of installed apps. And I need to change this functionality - i want just hide list of my webapps. In documentation thay suggest use some webapp, named root. It is ok, but than i get conflict of names and this default webapp is overriding my applications, if it was deployed last. So my question is - how do i can change this default 404 page for hidding webapp list.

You need to prevent Jetty from showing context related information.
Hint: you can even write own implementation of DefaultHandler and inject in in same way as inbuilt is injected, as far as jetty.xml is IoC-style config.

Related

Log4j2 configuration - indentify the webapp

In my webapp I configure Log4j2 with XML file.
The case is there's might be several versions of this webapp deployed on the server (for production purpose). If I don't edit log4j2 configuration, all webapps write logs to the same location.
So I need somehow identify versions of the app and add this identifier to the end of the folder name.
Apps always have different names, so maybe I can use it.
Can anyone please suggests some solution for this?
P. S. I know I could use ${log4j:configParentLocation} or something like this, but this gives me troubles when I deploy the app.
Edit: I don't use Spring boot, just usual Tomcat Servlet webapp with web.xml.

how to add a parameter to spring project before <projectname>/login and after <localhost>:<portnumber> without hardcode?

I'm working on a Spring MVC project. When I run the application the URL is:
http://localhost:8080/insureYou/login
but I want:
http://localhost:8080/contextroot/insureYou/login
Is there any way of doing it without hardcoding?
In a spring-boot project you can set the context-root by specifying the following property in the application.properties file:
server.servlet.context-path=/yourcontextroot
Without spring-boot, it depends on the webserver and Tomcat offers a number of options.
I would personally opt for a META-INF/context.xml file in your war file containing the necessary information but you can also include the information in the server.xml file or in a ROOT.xml file.
See the following links for further guidance:
How to set the context path of a web application in Tomcat 7.0
https://tomcat.apache.org/tomcat-8.0-doc/config/context.html
https://www.baeldung.com/tomcat-root-application
This type of deployment however sometimes is handled separately, through an Apache server reverse-proxy or through URL rewriting.
I recommend you ascertain whether this type of need is already taken care of by your company's deployment procedures, as you may not need to deal with it at all.

Can I have multiple Java webapps with overlapping paths?

I have a large collection of different independent (stateless) web services written in Java and compiled as WAR files. I want to deploy them to a single web application server.
If the URIs handled by the services in each WAR file began with a prefix I could use as a web app name, then this would be easy. I could, for instance, have
SALES WAR FILE: contains code for the following:
GET http://example.com/sales/widgets
POST http://example.com/sales/widgets
GET http://example.com/sales/sky-hooks
MARKETING WAR FILE: contains code for the following:
GET http://example.com/marketing/widgets
PUT http://example.com/marketing/sky-hooks
...in which case I would simply deploy two WAR files under the names "sales" and "marketing". However, I am not that fortunate. Instead, the URI paths handled by the components overlap. Something like this:
SALES WAR FILE: contains code for the following:
GET http://example.com/widgets/sales
POST http://example.com/widgets/sales
GET http://example.com/sky-hooks/sales
MARKETING WAR FILE: contains code for the following:
GET http://example.com/widgets/marketing
PUT http://example.com/sky-hooks/marketing
My question is how (if at all) I can deploy these on a single web application server.
I am open to suggestions that require a significant amount of work. For instance, my best-so-far idea is to build services that expect a component-name prefix before the regular URI path, then pipe all incoming traffic through a different server that knows what component each URI pattern falls into and modifies the URI to add that prefix. The difficulty with this approach is that tools like Swagger that read my source code will have a mistaken idea of what the URIs look like.
Any ideas?
If you're willing to put apache in front of your web container, you can use apache's mod_proxy to forward request to the right place.
One way this could work, would be deploy the separate wars at separate prefixes as in your first case (sales and marketing) and then use ProxyPass to send the requests to the correct place:
ProxyPass /widget/sales http://example.com/sales/widget
ProxyPass /sky-hooks/sales http://example.com/sales/sky-hooks
ProxyPass /widget/marketing http://example.com/marketing/widget
ProxyPass /sky-hooks/marketing http://example.com/marketing/sky-hooks
Its probably a better idea to just refactor your routing though - it might be hard to maintain.
(EDIT: I originally suggested mod_rewrite, but I wanted to make my answer more specific, and it looks like this could be done purely with proxying)
If I understand your question correctly, one of the solutions would be (I am assuming Tomcat is used but this should apply to most of the modern servlet containers):
1) Deploy your sales and marketing wars with different prefixes. I.e., using your example, they should be able to serve the following urls:
GET http://example.com/sales/widgets/sales
POST http://example.com/sales/widgets/sales
GET http://example.com/sales/sky-hooks/sales
GET http://example.com/marketing/widgets/marketing
PUT http://example.com/marketing/sky-hooks/marketing
2) Use UrlRewriteFilter to craft lightweight web application that will be deployed to your servlet container root prefix (for Tomcat it is called ROOT.war) and will rewrite urls in incoming requests to point to relevant web application.
In other words, incoming request like:
/widgets/sales
will be transformed to:
/sales/widgets/sales
... and delivered to sales webapp.
Similarly, in response urls like:
/sales/widgets/sales
will be rewritten to:
/widgets/sales
3) Deploy this war to root of your servlet container.
This approach is somewhat similar to the one suggested by #nont but does not require apache as a frontend as the rewriting functionality will be handled by root web application (UrlRewriteFilter basically implements mod_rewrite functionality).
In other words you'll be able to deploy all your applications (including this rewrite application that is deployed to the root prefix) to single server alleviating need for extra intermediate proxy/rewrite servers.
First, Determine How the Deployments may be Configured
Are you sure the absolute URIs must overlap? The context root will prefix the path supported by each service, unless the absolute path has somehow been coded into the application itself. The first step is to enable direct access to each WAR file, either through unique context roots or application instances.
Option 1: Set the Context Root for each WAR File Explicitly
The context root for a war file is set at deploy time. For some servers, this can be set outside of the web application using an external deployment descriptor. For Tomcat, it may embedded within META-INF/context.xml. See http://tomcat.apache.org/tomcat-7.0-doc/config/context.html for more information.
Option 2: Separate the Context Root Instances using Multiple Containers
Alternatively, deploy each war file to a separate instance of a Java EE servlet container, each running on a different port. This will solve the deployment conflict in the case of a hard-coded absolute path.
Finally, Set up a Virtual Host and Proxy the Requests via Apache and mod_jk
Once the context roots instances have been made uniquely accessible by one of the previous methods, configure an instance of Apache to serve as a reverse-proxy. First, set up a virtual host to handle requests for the externally visible URI. Next, configure mod_jk to route the requests to the correct WAR file deployment. See http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html for more details.
Afterthoughts
The above solution approach is generic for this type of problem and will require some knowledge of Apache and Tomcat configuration, which were chosen as example reverse-proxy and Java EE servlet technologies for its implementation. Additional detail on the deployment constraints would help to determine an optimal solution. In general, identifying the hard constraints on what may be changed versus what may not be changed should guide you quickly to a solution.
The obvious slotuion is to rename the wars, or refactor so that the appropriate mappings are in the correct place.
Anything else is going to be a bit hacky, you can't change the war name, even to soemthing like below :
SALES WAR FILE: contains code for the following:
GET http://example.com/webapp1/widgets/sales
POST http://example.com/webapp1/widgets/sales
GET http://example.com/webapp1/sky-hooks/sales
MARKETING WAR FILE: contains code for the following:
GET http://example.com/webapp2/widgets/marketing
PUT http://example.com/webapp2/sky-hooks/marketing
You could also create another war for routing/filtering, that redirects everything appropriately - but that also relies on altering url somewhat.
This is a use case for Reverse Proxy. If your web server is Apache, as suggested by #nont proxy_mod can be used to create a reverse proxy.
I know that IBM Http Server (IHS) also allows this mod.

Load webapp on container startup without web.xml in Tomcat+Jersey?

I currently have a Jersey webapp without a web.xml. It deploys nicely, but doesn't start up until it receives its first web request.
To get the webapp to load at startup, I could create a web.xml for the webapp and give a load-on-startup tag. However, I'd strongly prefer not to make a web.xml.
Is there a way to get a JAX-RS application to load at startup without web.xml? I'll even accept a solution that is specific to Jersey and/or Tomcat.
EDIT: I would also accept a solution that loads all apps in a Tomcat instance eagerly.
EDIT: Let me give a little more information on how the app is being deployed, per a comment.
The deployment process is not sophisticated.
The App will live on an EC2 instance running Ubuntu 12.04. I'm setting up one instance of the App by hand; once it works, I will make an AMI of the app and create additional copies of it as needed.
To deploy the app on the initial instance, I'm simply copying the WAR file to /var/lib/tomcat7/webapps and restarting Tomcat. No other webapps will be running on this Tomcat instance.
If any additional information would be useful, let me know! I'll happily add it.
EDIT: For clarity's sake, this is how my webapp Application class looks, at a high level:
#ApplicationPath("/")
public class App extends ResourceConfig {
// ...
}
I'm using the Jersey-specific ResourceConfig class instead of the more general JAX-RS Application class because I'm using Jersey's built-in HK-2 to do some dependency injection.
The only way I can think of to do that is to switch to setting up the Jersey ServletContainer yourself and set its "load on startup" value to something greater than zero. You might use a ServletContainerInitializer (no relation--the naming is just a coincidence) to do it. If you happen to be using Spring, its WebApplicationInitializer offers the same mechanism with a slightly more convenient interface.
Another, rather hacky, way would be to write a class that extends ServletContainer and give it an appropriate Servlet 3.0 annotation, something like #WebServlet(value="/", loadOnStartup=1)
One solution would be to force a first request to the app by simply adding a call to curl or wget to your deployment script. It has the additional advantage of warming up any caches. And it can be used for testing if the deployment and the app really work. (Just check HTTP status code or some text on the response page...)

JBoss 4.2.2 web service soap:address

I have an EJB3 bean deployed as a web service in JBoss 4.2.2. In production the server is behind an Apache server that redirects requests to the Jboss server. This makes the WSDL have the wrong soap:address location. I was able to get the port and host name changed via the configuration file in server\default\deploy\jbossws.sar\jbossws.beans\META-INF, but I haven't been able to get it to switch the protocol to https.
The only way that I found was to specify my own WSDL (via here). By specifying https in the WSDL, JBoss picks up that it is https. However, although that is fine in production, in QA https is not used (and the service that connects to it requires valid https, so self-signed certificates won't do). So while I could get a real certificate for QA (fake certificate authorities won't do), I would rather have it be http in QA. Is there a way to force JBoss to change the protocol or otherwise change the address so that it uses http in the soap:address?
EDIT: It seems like this issue was brought up recently in their bug database and was rejected. That would imply to me that they have a work around. But what is it?
Further EDIT: At this point, I know that an EJB3 Interceptor doesn't work (they are not activated at all) and SOAPHandler's don't intercept the call to retrieve the WSDL (tested - they pick up everything else). So the filter idea is intriguing, but it is far from clear where to put it.
The URL as shown by JBoss is:
Endpoint Name jboss.ws:context=QuickBooks-QuickBooksWebService,endpoint=QBWSBeanEJB
Endpoint Address https://127.0.0.1:8443/QuickBooks-QuickBooksWebService/QBWSBeanEJB?wsdl
(Note that is when I use the custom WSDL to force https but JBoss is configured to rewrite it).
The version of JBossWS I'm using is what is bundled with 4.2.2, which according to this is 2.0.1
EDIT: With regards to the rewriting, this was indeed attempted. Here is what I found. I could get it to rewrite the host (or not as needed) and the port, but only for the recognized protocol. So in order to get it emit an https, I had to configure the bean's transport guarantee to CONFIDENTIAL, and enable https on the JBoss server, then all requests were redirected to https within JBoss. I didn't test if this would even work with mod_jk (does the AJP protocol still work if CONFIDENTIAL is required, and will the WSDL get the right protocol if the request comes over AJP? I didn't test it), however doing that has the same net effect - the requests must go over https. There is no way to have the request come in over http or AJP and then have it emit a soap:address as https, specifically configured on a per-server basis (in QA and dev, http, in but in production https even though the ssl was terminated by Apache). Using the custom WSDL got me closer, in that the request is coming in on HTTP, but the soap:address says https. Perfect for production (using the rewrite feature to push the port to 443 instead of 8443), but useless for QA (dev I don't care about, because the dev build could be different and create a different jar if needed, but I'm not comfortable with QA and production having different build processes if I can avoid it).
Why don't you set up a servlet filter on your web application which watches for WSDL requests and rewrites the soap:address in the responses using values from its configuration? Then you can set it up however you want.
It may not be the most elegant solution, I agree :-) - but then that would have been for the configurability to be in JBoss, wouldn't it? And if JBoss eventually introduces this feature, you can just remove the filter.
Update: A typical JBoss EAR has the following structure:
myapp.ear
|+ META-INF
|+ applications.xml and jboss-app.xml
|+ myapp.war
|+ web pages and JSP /JSF pages
|+ WEB-INF
|+ web.xml, jboss-web.xml, faces-config.xml etc.
|+ lib
|+ tag library JARs
|+ classes
|+ servlets and other classes used by web pages
|+ myapp.jar
|+ EJB3 bean classes
|+ META-INF
|+ ejb-jar.xml and persistence.xml
|+ lib
|+ Library JARs for the EAR
Can you confirm that your deployed EAR has this structure? If not, how is it different?
Update #2: JBoss automatically generates a web.xml for EJB3 beans which are in a JAR inside the EAR being deployed. This web.xml is definitely hard-coded (i.e. doesn't use as a basis an XML file which you can tweak) and so it is awkward (though not impossible) to change this to include a filter (you basically need to change various things in jboss-beans.xml to point to your own web.xml generator, which can do whatever you want). It would be a lot less development work if the EJB3 beans were in the WAR file - then you can configure the Filter conventionally using the WAR's web.xml, which you presumably have control over. However, that might be problematic if that's a third-party JAR you're using - or it might not. Without knowing the details it's hard to see which the best approach will be.
Edit from the question's author:
Thanks for all the effort. This appears to be the basic approach - intercept and change the WSDL. If you can't make your webservice a POJO assigned in the war, where you can use a servlet filter, then you can make a servlet that proxies the request, and do it that way. That was my solution.
We've faced similar issues in the past and decided that using SSL in all QA environments was desired (there are downsides - especially when debugging the HTTP streams - but what doesn't have downsides?)
This can be easier that you may think however since you seem to have control of all environments involved: you basically just need to tell Java that your self-signed certificates are "good". To do this you need to add yourself as a certificate authority in Java.
A good overview of the process is here:
http://en.wikibooks.org/wiki/WebObjects/Web_Services/How_to_Trust_Any_SSL_Certificate
Here's information from Sun about the KeyStore tool (although you should look for the reference specific to your version/JVM as there are differences):
http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/keytool.html
Once this is done your self-signed certs in QA will be 100% "valid" in Java.
You can even save some money sometimes in Prod: if you control both sides of the environment you can do self-issued certs in Prod and save some cash. Heck, if your user community is small/controlled enough you can add your self-signed authorities directly in client browsers as well (although that seems like it would be more trouble that its worth).
Hope this gets you moving in a useful direction!
Basically the only solution I found to this was to create a servlet which intercepts and proxies the WSDL request. I copied and implemented ProxyServlet from Apache's pivot project (it took some not-insubstantial changes, such as the Apache implementation only wrote responses to gets not posts). Basically the implementation checks if the request is a request for a WSDL, and changes the soap:address property in the WSDL. Hardly nice, but, it worked around that problem, but the whole thing is still not working because after we have communication, there is a further problem. Another question on SO I guess.

Categories

Resources