Get context path in init method in Servlet 2.3 (so no ServletContext#getContextPath() available) - servlets

I'm using servlet 2.3 for my project development due to some legacy code we have. Is there a way to get the context path in the init method or any other way of the servlet?
I know it's possible on higher versions of Servlet and can get it in hacky way using the getRealPath() method on servlet 2.3. However I'm still looking for a better and cleaner code.

I wasn't able to do this. The best way I found was to move to 2.5 spec.
Posting answer just in case anyone is trying the same.

Related

Change in behaviour for IActionInvokerProviders when using UseStatusCodePagesWithReExecute between core 3.1 and dotnet 6

Context:
Upgrading an existing aspnet application from core 3.1 to dotnet 6.0.
Issue:
We have registered a IActionInvokerProvider in our web app. This simply adds some information to the context route data.
We also use UseStatusCodePagesWithReExecute
app.UseStatusCodePagesWithReExecute("/somecontroller", "?statusCode={0}");
According to the documentation https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.abstractions.iactioninvoker?view=aspnetcore-3.1
An IActionInvoker is created for each request the MVC handles by querying the set of IActionInvokerProvider instances. See IActionInvokerProvider for more information.
When running this in netcoreapp3.1 when we return a NotFound() I can observe that 2 calls are made to our action provider OnProvidersExecuting. One for the request to the resource and one for a call expected UseStatusCodePagesWithReExecute to /somecontroller.
When targeting net6.0 and changing no other code this second call to /somecontroller does not get called only the first . If I call the endpoint /somecontroller?statusCode=404 I it does trigger the invoker. I cannot find a reference to a breaking change anywhere. perhaps I missed it.
Does anyone know what the casue might be?
I have tried altering the ordering of the pipeline.
Tried to repro it in https://github.com/csi-lund/core31tonet6issue
In the version the Action provider never gets called at all
The answer was a missed breaking change and documentation.
https://github.com/dotnet/aspnetcore/issues/45589
We skip the IActionInvoker by default as an optimization for
controllers and pages. This is a really heavyweight way to add route
data to the pipeline. You can set EnableActionInvokers to true to
enable this behavior.
builder.Services.AddControllers(o => {
o.EnableActionInvokers = true; }); In your sample it would be AddMvc (since you're using that).
No change in behaviour without documentation to indicate. (There might
be might have missed it)
Yes, it seems like we missed this one. I'll make sure it gets
documented.
PR: #27773 https://github.com/dotnet/aspnetcore/pull/27773

How to create Elastic APM spans for each pipeline call

I would like a recommendation on how to instrument each pipeline call using Elastic APM API on Intershop 7.10.
I want to to create a separate span as described here:
https://www.elastic.co/guide/en/apm/agent/java/master/public-api.html#api-span-start-span
(Using try catch block with parent.startSpan())
For now I have tried looking into ICM knowledge base for topics regarding ELK stack (found none) and looked in Component Framework section on how to inject some code around PipelineProcessorImpl.executePipeline or put another pipeline processor implementation through component framewowrk but couldn't find nothing, it seems for now that pipeline processor implementation are not hooked through Component Framework.
General answer is, you should not bother replacing PipelineProcessor with your own implementation. Even for such a seemingly small task of feeding your own monitoring solution.
I (may) have a better solution for you. Haven't tested it though. Have a look at the detailed answer to this intershop question: Adding a servlet to run in Intershop 7.4 application server context
You don't want to add a new servlet but you want to bind a new javax.servlet.Filter implementation that hooks into the Application Server request chain. You can do that the same way as described, but invoke method filter("/servlet/Beehive/*") instead of serve("/servlet/DEMO/*")

Tomcat 9 and Servlet API 2.5

My spring web application is using servlet api 2.5 along with spring framework 4. Its deployed in tomcat 9. Its working fine. I am not sure why tomcat is not complaining about it as it needs servlet api 4 as per documentation. Is it backward compatible or spring is doing some magic? Just for clarity We are using interfaces from servlet api 2.5 in our code which should not compile with servlet api 4. It is compiling because we are compiling with 2.5 but we are expecting it to fail at runtime in tomcat. Thanks
Are you using methods/classes that no longer exist in servlet spec 4? There isn't magic - it's downward compatible. If you tried to run, for example, AsyncEvent code in Tomcat 5.5 (servlet spec 2.4) then yes, you'd have a problem. But running old code on a new server - without using things that have totally changed or disappeared - is rarely a problem.
EDIT
You said that the "old" code has:
Map parameterMap = request.getParameterMap();
This is still valid if not best practice. With newer compilers you may get a warning from the compiler that you are not using generics but it is still valid. And since the Javadocs from that time say:
Returns: an immutable java.util.Map containing parameter names as keys and parameter values as map values. The keys in the parameter map are of type String. The values in the parameter map are of type String array.
So your old code must be casting the keys as a String and the values as a String[] - just like the newer code that would be:
Map<String, String[]> parameterMap = request.getParameterMap();
Both versions will compile in recent versions of the compiler though, again, you may get warnings with the code that doesn't take advantage of generics.
The key is the use of generics - the <String, String[]> part. It's clearer code when using generics and the compiler can help with issues. With the non-generics version you could have tried to cast the key in the map to any object. It would compile but at runtime you'd likely get a ClassCastException.
From the perspective of Tomcat it's still returning the same thing.
Is that clearer?

Why is accesing services by classname good?

I've always worked in Symfony 2.2 and 2.8
Now glancing at the blog of the version 3.3 and I can't overcome the new feature of getting services by (fully qualified) class name:
// before Symfony 3.3
$this->get('app.manager.user')->save($user);
// Symfony 3.3
$this->get(UserManager::class)->save($user);
Before Symfony 3.3 the service container was a factory with the knowledge of how to instantiate the service class, with the great benefit of a factory: You can swith the old class to any other class, and as long as they both let's say implement the same interface, maybe you don't even have to touch anything else in your code. But if you ask for a service by class name, you have to refactor your whole code, and change the class name in every occurrence of the service. Either when directly accessing by $container->get() or by using typehint and autowire.
Considering these the old way service aliasing seem much more practical or am I just missing something? I know you still can use it the old way, I'm just wondering in what cases could one benefit from preferring this new method instead the classic one.
One of the main points about the new style of service naming it to avoid asking for services by name directly from the container. By typehinting them all (and having them instead created by the framework), then any service that is not being used at all (and is private, so not get-able), can be removed. Anything that is hinted via the container and does not exist will immediately fail on the container building step as well - it would not be possible to rename a service and forget to also change all the other uses of it.
With so much being injected into the controllers (or a controller action) as well, unit testing the services, and even controllers is also more controllable - there wouldn't be any other things that are being pulled from the container within a test.
As for the transition, because of the container compilation step, Symfony is very good about being able to say if there is anything wrong, or at least deprecated. It's not hard to mark all the current services as public with just a small Yaml snippet at the top of each services.yml file (or anywhere else they are defined).
It will be a while until most of the 3rd party bundles and other supporting libraries will be fully 4.0 compatible, but it was also the case for the breaking changes between 2.8 & 3.0. This is a large part of the reason why 2.8 & now 3.4 are long-term-supported versions - with 3.4 supported to November 2021, giving plenty of time to upgrade away from the deprecations and update the 3rd party bundles.

Best strategy for upgrading application from Symfony 2.0 to Symfony 2.4?

I need to upgrade an existing rather large application from Symfony 2.0.15 to Symfony 2.4.x (replace with current version).
I'm not quite sure what would be the best strategy to do so. Migration critical features like forms or esi are used, of course :)
Upgrade "step by step" from one major version to another (2.1, 2.2, 2.3, 2.4)
Upgrade directly from 2.0.x to 2.4
Do you have any tips / experience to share ? Would appreciate it :)
Thanks,
Stephan
Each new version comes with an update UPGRADE-2.x.md file containing all intructions to convert your application from the immediately previous version.
I had to do that on my project as well, and I found the step-by-step method more natural and easier to manage. Fact is, there is no file such file as UPGRADE-2.0-to-2.4.md that would help you out for a direct conversion to 2.4.
I shall first recommend to make sure that none of your code uses obsolete functionnalities of Symfony 2.0 (not sure if there are deprecated parts in this version, though), because these can be removed in ulterior versions and will not be included in the UPGRADE file.
If you have done indeep modifications of the core Symfony code, you may find that some undocumented modifications are needed. For instance, there is a custom error handler in my project, extending the Symfony error handler. Well, although it was not documented in the UPGRADE file, the signature of ErrorHandler::handle() was modified and needed to be updated in my custom handler.
Similarly, I had to modify some namespaces because files had been moved in the framework code.
The conversion is still ongoing and I'm currently experiencing a weird error I'm trying to get rid of: The 'request' scope on services registered on custom events generates errors in the logs.

Resources