how to externalize context-param values in web.xml - servlets

I'm tryin to migrate some legacy (struts2-based) web application from Jboss to Open-Liberty server, and I'm wondering if there is a way to externalize the values of context-params (or filter init-params) from web.xml, like it is possible with the ${} syntax in server.xml or using mpConfig feature of eclipse microprofile.
In the original project the param values were injected in web.xml at build time, using a placeholder substitution but, according to 12-factor 3rd recommendation, I would prefer to set this values outside software, in environment variables, for example.
In my specific case I need to configure a servlet filter and a custom taglibrary with environment dependent param values.
I already tried to use the ${} syntax in web.xml, but no luck:
...
<context-param>
<param-name>remincl.resource.provider</param-name>
<param-value>${remincl.resource.provider}</param-value>
</context-param>
...
the runtime value of the context-param is: "${remincl.resource.provider}" instead of the actual value that is stored in an environment variable.
I think JEE specs doesn't allow this behavior, but I would like to know if open-liberty offers some extra feature to solve this problem. Otherwise I must keep injecting values at build time (or change the configuration strategy of both filter and taglib).

A JavaEE standard way to accomplish this would be using a javax.servlet.ServletContextListener.
For example:
#WebListener
public class MyServletContextListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
// Get the context value from wherever is most convenient:
// System.getProperty(), System.getenv(), MP Config API, etc
String value = System.getProperty("remincl.resource.provider");
event.getServletContext().setInitParameter("remincl.resource.provider", value);
}
#Override
public void contextDestroyed(ServletContextEvent event) {}
}

Related

in ASP.NET core (.NET5) how can i write logs for each request on separate files? Using Serilog or other

I'm new to .NET and to webservice development, so i'm not exactly sure how to implement the requirement i have.
My webservice gets a POST request with some data, which i need to
process to generate a pdf file: name_YYYYMMDDHHmmss.pdf.
For monitoring this i want to have a separate logfile for each request, named like the output file: name_YYYYMMDDHHmmss.log
I would like to avoid passing a config object into every class/function in which i need to add stuff to the log file
I've managed to install Serilog and it works for what i need, but not when i get concurrent requests. I'm also not exactly sure how simultaneous requests are handled in .NET (i have no thread specific code written so far), but as far as i can tell, when i change Global Logger file name, that object is shared across all threads so all of them write to the same file.
I've looked at a bunch of solutions, but i haven't managed to find nothing that suits this, and it seems most people have everything into 1 file...
Is there any clue or tips you can give me? I'm open to using something other than Serilog.
One way to have dynamic file names based on a specific context is by using the Serilog.Sinks.Map and then, via a middleware in the request pipeline, you can add a property to the log context that drives the file name to be used when writing to the log.
Examples of similar usage of Serilog.Sinks.Map to decide which file name to use at run-time:
Serilog - can not log to multiple files based on property
In Serilog dynamically changing log file path?
The best solution that I found to this problem was using Serilog.Sinks.Map. I configured my Logger something like this:
Log.Logger = new LoggerConfiguration()
.WriteTo.Map("Name", "Default", (name, wt) => {
var fileName = name == "Default" ? "log" : $"{log-{name}}"
wt.File($"./{fileName}-.txt");
}).CreateLogger();
Then on my controller, on each method where I needed this feature, I enclosed all the instructions inside a LongContext like this:
[HttpGet]
public IHttpActionResult Get() {
using (LogContext.PushProperty("Name", "theFileName") {
// ...
_myService.Method1();
// ...
}
}
public class MyService : IMyService {
// ...
public void Method1() {
// ...
Log.Information("This is what happened at this point…");
// ...
}
// ...
}
So all the Log's inside will use that context and it will write on a different file with the name you set for that context without having to modify any Log.Information/Error/Warning/etc that you already have on your code.
This is the ugly part... you have to define a context on a root place in order to make those Logs write on a different file. So for a controller method, the first thing you have to do is to enclose all with a LogContext.

How Can I make Spring-MVC #PropertySources load first, before any other configuration

I have a spring-mvc application that is using java configuration, not xml. There are #Configuration annotations sprinkled through several files. In particular, there is a #PropertySources annotation in one file in a class that implements WebMvcConfigurerAdapter. There are two classes which contain an #Autowired Environment variable. One of these classes is itself a #Configuration class, and I would like it to have access to the fully-loaded Environment at the time it runs.
This isn't happening. When this code executes, the Environment is still null. I've tried reordering the #ComponentScan packages, tried moving the #PropertySources annotation, and nothing has helped me load the property sources in time.
I want this to happen first, before any other configuration.
What must I do to make it so?
UPDATE: After trying many things, including the Order annotation, I find the problem seems to be not so much that the #PropertySources are being loaded too late as that a class I have that is derived from org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer is being loaded too soon. Nothing in my code even references this class but Spring is somehow deciding that this, above all other classes, must be initialized first. No amount of messing around with #Order seems to change this. This in spite of the javadocs, which indicate that the behavior I want is the default:
Caveats
Subclasses of AbstractDispatcherServletInitializer will register their
filters before any other Filter. This means that you will typically
want to ensure subclasses of AbstractDispatcherServletInitializer are
invoked first. This can be done by ensuring the Order or Ordered of
AbstractDispatcherServletInitializer are sooner than subclasses of
AbstractSecurityWebApplicationInitializer.
You can use ContextInitializer, catch the moment when Boot prepared its environment and "inject" your property source programmatically as you want.
If you have a ConfigurableApplicationContext then it provides a ConfigurableEnvironment, which contains the propertySources as a list. If you want your PropertySource to rule all above the others than add it as first. If you want to place it to a special position then you can add it before an other, identified by its "name".
public class ConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext ctx) {
// rule over all the others:
ctx.getEnvironment().getPropertySources().
addFirst(new ResourcePropertySource("file:/etc/conf/your_custom.properties"));
// rule over application.properties but not argument or systemproperties etc
ctx.getEnvironment().getPropertySources().
addBefore("applicationConfig: [classpath:/application.properties]",
new ResourcePropertySource("classpath:your_custom.properties"));
// names can be discovered by placing a breakpoint somewhere here and watch
// ctx.getEnvironment().getPropertySources().propertySourceList members,
// each has a name ...
}
}
You can bring into play this class by:
registering it in the application.properties :
context.initializer.classes=a.b.c.ConfigInitializer
or from application start :
new SpringApplicationBuilder(YourApplication.class).
initializers(new ConfigInitializer()).
run(args);
By the way this is a proper way to inject more of your custom properties, like properties coming from a database or a different host etc...
Not that I am an expert in Java config but maybe:
Spring 4 utilizes this feature in its #PropertySource annotation. To
remind you, #PropertySource annotation provides a mechanism for adding
a source of name/value property pairs to Spring's Environment and it
is used in conjunction with #Configuration classes.
Taken from: http://blog.codeleak.pl/2013/11/how-to-propertysource-annotations-in.html
Are you using #PropertySource or #PropertySources?
Have You tried 'order' property for spring bean initialisation?

Spring 4 AOP #Aspect isn't triggering for #RestController

I have created an Aspect which performs a basic id comparison to ensure that a user belongs to a the same group that created the entity being requested. I have had success attaching my aspect to #Service methods, but it doesn't make sense on the service layer, and I need it to be attached to #RestController methods instead. When I attempt to do this, everything seems good, but my Aspect never triggers, and the logs are silent.
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
spring context
<context:annotation-config/>
<context:component-scan base-package="my.pkg"/>
<aop:aspectj-autoproxy/>
<aop:config proxy-target-class="true"/>
Aspect
#Aspect
#Component
public class MyAspect {
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void controller() {}
#Pointcut("within(#org.springframework.web.bind.annotation.RestController *)")
public void restController() {}
#Pointcut("args(java.security.Principal,..)")
public void principalArgPointcut() {}
#Around("(controller() || restController()) && principalArgPointcut()")
public Object validate(ProceedingJoinPoint point) throws Throwable {
doValidationBefore();
Object result = point.proceed();
doValidationAfter();
return result;
}
}
where "doValidationBefore()" and "doValidationAfter()" will throw an exception if validation fails.
And finally, my RestController
#RestController
#RequestMapping("/my-path")
public class MyController {
#RequestMapping(value = "/{entityId}", method = RequestMethod.GET)
public #ResponseBody
ResponseEntity<MyEntity> getEntityDetails(Principal principal, #PathVariable("entityId") Long entityId) {
return new ResponseEntity(HttpStatus.OK);
}
}
Some things to note:
This exact aspect works when I change the execution pattern to match services and place it in my service package.
The Aspect and the RestController are in the same context
I use IDEA IDE, and when I use the "navigate to advised methods" icon on the Aspect, the method I'm testing IS listed in the list of methods.
None of the methods listed in "navigate to advised methods" are working
Things I have tried:
I added 3 libraries to my pom.xml: org.aspectj:aspectjrt:1.8.6,
org.aspectj:aspectjtools:1.8.6, cglib:cglib:2.2.2. None of these made
any difference.
I tried defining my Aspect and PointCuts directly in the context xml and removing the annotations, no difference.
I have tried setting my execution pattern to apply to ALL methods, and it still did not trigger.
I tried adding an interface for my RestController, no change.
I would love some help here, as I've been trying to solve this for quite some time now. I know it must be possible.
As it turns out, my Aspect and my Controllers were NOT, in fact, in the same context.
While I believed my Controllers to be included in the context scanning of my web-context.xml, they were actually being scanned in WEB-INF/servlet-context.xml
Once I moved my Aspect configuration to WEB-INF/servlet-context.xml, my Aspect began to trigger as expected.
Thanks for all those who contemplated my problem.
Figure out for sure where your service is being configured in spring. If you have I there is an icon that you can click to navigate to the spring bean config. Then ensure that the aspect is configured in the same file.
If they are definitely defined in the same file, look next that the aop pointcut advice matches the method on which you're expecting it to fire. Again, Idea has an icon next to the pointcut that will navigate to matching methods.

Overriding RequestMapping on SpringMVC controller

Looking through the source for our applications, I found a common Spring MVC controller which display key and values of configuration copied and pasted several times. The class definitions are exactly the same, except for the RequestMapping value, since each application want to have this page available under different URLs.
I want to move this controller into a common library, and provide a default RequestMapping value.
#Controller
#RequestMapping (value="/property")
public class CommonPropertyController {
....
}
How would each application override this value if they want to use their own url pattern?
Looking at the source code I got an idea how to do it without having to go back to manual (pre-annotation) handler definition (which is also a way how to implement what you need).
Spring allows you to use property placeholder configurers in #RequestMapping values. So it is possible to use that fact and define #RequestMapping like:
#Controller
#RequestMapping("${routing.property.path}")
public class CommonPropertyController {
....
}
Then you can simply define PropertySourcesPlaceholderConfigurer with the right properties in your application context and you are good to go.
UPDATE You can also specify a default value using property placeholder if you want to have fallback mapping in case the property is not speciefied:
#RequestMapping("${routing.property.path:/property}")

Specify run time parameter dependency in Unity

I have a class which needs a string as a parameter in its constructor but this parameter will be decided by the calling code. At the same point of time, the life time of this class has to be tied to per HTTP request. So, I created a custom PerWebRequestTimelineManager and used that for my target type in the config file. But since the string in the constructor has to be dynamically determined, I cannot use the ConstructorInjection via the config file. I can use an abstract factory to solve the problem of dynamic dependency, but I am not sure about the implementation: Can you check the code below and validate the approach. Specifically the RegisterType and Resolve calls seem a bit out of place though the successive Resolve calls across the application will be able to retrieve the same instance.:
public class PerformanceTracerFactory : IPerformanceTracerFactory
{
private readonly IPerformanceTracer tracer;
public IPerformanceTracer CreateInstance(string operationTitle)
{
_container.RegisterType<IPerformanceTracer, PerformanceTracer>(new InjectionConstructor(operationTitle));
return _container.Resolve<IPerformanceTracer>();
}
}
Relevant portion of config file:
<register type="IPerformanceTracer" mapTo="PerformanceTracer">
<lifetime type="PerWebRequest"/>
</register>
<register type="IPerformanceTracerFactory" mapTo="PerformanceTracerFactory"/>
I have another question. In case if the above way of configuring and injecting the dependency using code is correct, then I think I do not need the config entries. I can always use the suitable overload to push the custom lifetime manager. In case, I would want to achieve the same thing using only config file, then how do I code the solution?
If you use a container-based factory you don't have to register/resolve your IPerformanceTracer in each call.
Register the mapping IPerformanceTracer --> PerformanceTracer once in your config file and use a ParameterOverride when you resolve your interface.
public IPerformanceTracer CreateInstance(string operationTitle)
{
return _container.Resolve<IPerformanceTracer>(new ParameterOverride("nameOfTheParameterInTheConstructorOfPerformanceTracer", operationTitle);
}

Resources