In Wildfly, "/" is rewritten to "/index.html", bypassing RequestMapping("/") - spring-mvc

I am migrating a Spring MVC app from JBoss 7.1.1 to Wildfly 8.1, which has required (encouraged?) me to use the new "undertow" module instead of the older "web" module. Things are coming right along, except that now requests to "/", which used to invoke the controller method annotated with #RequestMapping("/"), no longer reach the controller method. Instead, it appears that such requests are being immediately rewritten (not redirected) to "/index.html". Since I don't have (and have never needed) such a file, all requests for "/" are now generating 404 errors.
Interestingly, all of the other #RequestMapping-annotated controller methods continue to function normally.
Here is the relevant snippet from my standalone.xml file.
<subsystem xmlns="urn:jboss:domain:undertow:1.1">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" socket-binding="http" max-post-size="4194304"/>
<host name="default-host" alias="localhost">
</host>
</server>
<servlet-container name="default">
<jsp-config development="true"/>
</servlet-container>
</subsystem>
I suspect that when the subsystem definition for Wildfly's undertow module does not explicitly declare a handler, Wildfly defaults to a file handler, which may be responsible for the the URL rewrites -- but I am not certain of this.
Documentation about handlers in the Undertow project, upon which Wildfly's undertow module is based, indicate support for a "Redirect" handler. I have considered using this to work around the unexpected "/" rewriting, but it is not clear to me whether Wildfly's undertow module supports this, and if it does, how to configure it in standalone.xml. Even if I was able, however, I think it would feel like a hack, and I'd prefer to get to the root of the problem (no pun intended) instead.
There are many S.O. questions describing disappointing RequestMapping("/") behavior, and many answers suggesting using other paths (such as "", "/index", etc.), but don't forget: the existing (unchanged) code works just fine in JBoss 7.1.1. (Also, none of those questions mention Wildfly, which is probably the key consideration for this question.) Nevertheless, I experimented with the various suggestions and got nowhere. It simply seems like the URL is being rewritten before it ever reaches the dispatcher servlet.
So, in summary, my question is:
How can I get a Spring MVC app with RequestMapping("/") to run in Wildfly 8.1 as it does in JBoss 7.1.1?

In Wildfly, if your web.xml doesn't have a <welcome-file-list> element, then one is provided for you, as if you had configured it this way:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
With this default configuration, when Wildfly receives a request for for "/", the path is automatically rewritten as index.html. This path will then not match the controller method annotated with RequestMapping("/").
JBoss 7 apparently behaves differently, perhaps only referring to the welcome file list after failing to find a matching servlet.
Whatever the cause, you can work around the new behavior by explicitly defining your own welcome file list and including, as the last <welcome-file> element, an empty welcome file:
<welcome-file></welcome-file>
This allows Wildfly to rewrite "/" as "/", in turn allowing the request for "/" to be processed by the servlet dispatcher (provided that its url-pattern is set to /). The servlet dispatcher will then invoke the controller method annotated with RequestMapping("/").

Related

Configure Jetty 9.4 event listener

I want to listen to contextInitialized() and contextDestroyed() events. I created jetty.xml file where I want to specify the class that will be responsible for listening. The error message I get: Unknown tag: listener.
The content of the file:
<Configure class="org.eclipse.jetty.server.Server">
<listener>
<listener-class>test.Application</listener-class>
</listener>
</Configure>
<Configuration> is for configuring a specific object in Jetty.
That syntax has a DTD that explains what you are allowed to use as far as what XML elements.
<listener> is not available in that DTD.
That's the reason for the error Unknown tag: listener
Now, lets dig a bit deeper...
Why do you want a Listener that listens for contextInitialized() and contextDestroyed()?
I assume you want a javax.servlet.ServletContextInitializer based on those method names.
That's only available in a specific webapp, not for all webapps.
The most common way to configure that is in the webapp's own WEB-INF/web.xml
That's where your <listener> block needs to be.

ASP.Net Web.config client endpoint name

I have a service that has references to other services with some of them being references to different environments of the same service (e.g. prod/test).
I am using the #if precompile directive to include different versions of these references with the using statement. Example:
#if Debug
using ServiceTest
#else
using ServiceProd
#endif
In the Web.config file I have two child nodes inside the <client> node. Example:
<client>
<endpoint address="http://test.domain.com/Service"
binding="basicHttpBinding" bindingConfiguration="Service"
contract="ServiceTest" name="Service" />
<endpoint address="http://prod.domain.com/Service"
binding="basicHttpBinding" bindingConfiguration="Service"
contract="ServiceProd" name="Service" />
</client>
Is the above part of the Web.config valid or not? More precisely, can there be any side-effects because of having two endpoints with the same name and binding configurations? The main concern is having a wrong endpoint called (e.g. calling prod endpoint instead of test or the other way around).
Any guidance and advice regarding the above will be really appreciated.
Is the above part of the Web.config valid or not?
Every time when you run your application CLR reads web.config file and deserialize it as an object. To deserialize XML it's uses classes declaration in "configSections" section of your config file.
So, the answer "valid or not" depends on implementation of "client" configuration section. I believe this should be part of your application or code from nuget library. This is why we can't answer you with confidence.
More precisely, can there be any side-effects because of having two endpoints with the same name and binding configurations?
Frankly, I don't understand how this should work. In what manner 3rd library should know that it needs to load first but not second client endpoint?
Possible solutions.
You can use web.config transformation. There are tons of resources about this feature of .NET Framework.
The simplest scenario would be to substitute endpoint address keeping the same endpoint name.
Another common scenario is to give different endpoint names and keep "alive" endpoint name in AppSettings. In this case your code should resolve endpoint name first and then actual endpoint address.

switch to "trace" log level, but only for current web request (nLog)

I would like the ability to turn on trace-level logging in nLog, on production, but only for the current web request.
In other words, I'd like to be able to do something like...
http://mywebsite.com?logeverything=true
... which would do trace-level logging, but only for that web request, not the hundreds of other requests that are happening at the same time. I'd also like the logs for that request to go to a different file than where the rest of the logging is going to. An acceptable alternative to a query string would be to turn on the trace-level logging but only if the web request is local.
I could write my own Logger class and override the nLog log methods to do something along these lines, but my web project uses a number of different assemblies and and switching all the projects to use a new logger class would be something of a pain.
Anyone doing anything like this?
This could be done without the need of wrappers.
Install also NLog.Web (or in the case of ASP.NET Core: NLog.Web.AspNetCore nd follow the installation tutorial
Create your trace logs in c#
Write to session it's your request
Filter your logs in the .config
<logger name="*" writeTo="myFile">
<filters>
<when condition="${aspnet-session:Variable=myRequest} != 1" action="Ignore" />
</filters>
</logger>
in this case I use the session, but you could also use ${aspnet-request-url} - but that makes the config a bit more complicated

Process Monitor shows "path not found" for valid URLs

We use "Process Monitor" (ProcMon) to monitor the w3wc.exe process on a Windows Server 2008 running IIS7 . We have noticed that requests to perfectly legal urls still results in a "PATH NOT FOUND" entry in ProcMon.
For example, we have configured a handler in web.config like:
<add name="ImageVaultHandler.aspx_*" path="ImageVaultHandler.aspx" verb="*" type="ImageStoreNET.Classes.Handlers.ImageHandler, ImageStoreNET" preCondition="integratedMode,runtimeVersionv2.0">
Requests to this handler eg. "http://localhost/id_123/ImageVaultHandler.aspx" will return an image as expected, but when you analyze the request in ProcMon the w3wc.exe process looks to have unsuccessfully searched for a physical file with the same path in my web directory.
Is this behaviour by design? Or have we missed something, the application pool used is configured to run in "Integrated Mode".
This sounds reasonable to me - what IIS is probably doing is checking to see whether or not the file exists in order to determine what handler to use when processing that request:
It looks like the logic in IIS doesn't bother to check first whether there is an applicable handler that can be used even when the file doesn't exist.

How do I Resolve an application URL from a background thread in ASP.NET MVC?

The app splits off into two threads; the main web app and a secondary thread used for asynchronous event handling. The secondary thread receives an event where it needs to send an email with a fully qualified URL of the main app (plus additional route arguments) inside it.
Eg. http://Server.com/App/RouteData?AdditionalArguments
Of course the background thread does not have the luxury of using HttpContext.Current to resolve a Url, because there's no request. No HttpRequest, no HttpContext...
I discovered that most of the methods ASP.NET (even with MVC) uses to build URLs rely on HttpContext. Does there exist a way to build a fully qualified application URL in ASP.NET without using HttpContext or any of it's derivatives?
I'm looking for a thread-safe method like:
UrlHelper.GetApplicationtUrl()
Any Ideas? Your suggestions are much appreciated.
I had this exact problem. I ended up storing the url in the web.config file. I did mine like so:
<appSettings>
<!-- Urls -->
<add key="AppDomain" value="http://localhost:1273/" />
<add key="ConfirmUrl" value="http://localhost:1273/Auth/Confirm/?code={0}" />
</appSettings>
and called it like this in the service layer:
string confirmUrl = string.Format(ConfigurationManager.AppSettings["ConfirmUrl"], confirmCode);
If you can't just use the configuration file, when creating the Thread, use the ThreadStart delegate to provide the base information you need to the new thread.

Resources