With an ObjectMapper (com.fasterxml.jackson.databind) it's possible to specify that it should ignore unknown properties. This can either be done by adding #JsonIgnoreProperties(ignoreUnknown = true) on a class level or by setting it as default behavior in the mapper. However, when doing this in the initialize() method of Application<MyConfiguration> it doesn't seem to have an effect.
ObjectMapper mapper = bootstrap.getObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
It still fails for unknown properties in the configuration file. How does one configure Dropwizard to ignore unknown properties?
The reason configuring DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES for bootstrap.getObjectMapper() doesn't have the desired effect is that ConfigurationFactory (the class later on used to parse the configuration) is enabling that particular feature of the object mapper in its constructor (see here):
public ConfigurationFactory(Class<T> klass,
Validator validator,
ObjectMapper objectMapper,
String propertyPrefix) {
...
this.mapper = objectMapper.copy();
mapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
...
}
It's not possible to change the behaviour of ConfigurationFactory directly but Dropwizard provides means to override the factory that creates it, ConfigurationFactoryFactory, via Boostrap.setConfigurationFactoryFactory(). This allows to replace the real ObjectMapper with a proxy that doesn't allow to override the configuration and pass it to ConfigurationFactory:
bootstrap.setConfigurationFactoryFactory(
(klass, validator, objectMapper, propertyPrefix) -> {
return new ConfigurationFactory<>(klass, validator,
new ObjectMapperProxy(objectMapper), propertyPrefix);
}
);
The code for ObjectMapperProxy that ignores attempts to enable FAIL_ON_UNKNOWN_PROPERTIES it below:
private static class ObjectMapperProxy extends ObjectMapper {
private ObjectMapperProxy(ObjectMapper objectMapper) {
super(objectMapper);
}
private ObjectMapperProxy(ObjectMapperProxy proxy) {
super(proxy);
}
#Override
public ObjectMapper enable(DeserializationFeature feature) {
// do not allow Dropwizard to enable the feature
if (!feature.equals(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
super.enable(feature);
}
return this;
}
#Override
public ObjectMapper copy() {
return new ObjectMapperProxy(this);
}
}
Note that besides overriding enable to skip FAIL_ON_UNKNOWN_PROPERTIES copy is also implemented (together with an additional constructor) as ConfigurationFactory requires the object mapper to support copying.
While the solution above works it's obviously a workaround and I suggest upgrading to a newer Dropwizard version instead. The new Dropwizard makes ObjectMapper configuration easier to override (e.g. see this Dropwizard commit available in Dropwizard 1.1.x).
You need to disable that feature with:
bootstrap.getObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
UPDATE: The feature disable works for the API resources but not for the configuration YAML. Instead, you need to add the annotation below (same as mentioned on the question) to the configuration class:
#JsonIgnoreProperties(ignoreUnknown = true)
Related
I am new to grails and while working with Spring Security LDAP plugin it was identified that it accepts the ldap server password in plain text only. The task in hand is to pass an encrypted password which is decrypted before it is consumed by the plugin during its initialization phase.
I have already searched for all possible blogs and stackoverflow questions but could not find a way to extend the main plugin class to simply override the doWithSpring() method so that i can simply add the required decryption logic for the Ldap server password. Any help here will be appreciated.
I have already seen and tried jasypt plugin but it also does not work well if the password is stored in some external file and not application yml. So I am looking for a solution to extend the Spring security plugin main class, add the required behavior and register the custom class.
EDIT
Adding the snippet from Grails LDAP Security plugin, which I am trying to override. So If i am successfully able to update the value of securityConfig object before the plugin loads, the purpose is solved.
Some snippet from the plugin:
def conf = SpringSecurityUtils.securityConfig
...
...
contextSource(DefaultSpringSecurityContextSource, conf.ldap.context.server) { // 'ldap://localhost:389'
authenticationSource = ref('ldapAuthenticationSource')
authenticationStrategy = ref('authenticationStrategy')
userDn = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**password = conf.ldap.context.managerPassword // 'secret'**
contextFactory = contextFactoryClass
dirObjectFactory = dirObjectFactoryClass
baseEnvironmentProperties = conf.ldap.context.baseEnvironmentProperties // none
cacheEnvironmentProperties = conf.ldap.context.cacheEnvironmentProperties // true
anonymousReadOnly = conf.ldap.context.anonymousReadOnly // false
referral = conf.ldap.context.referral // null
}
ldapAuthenticationSource(SimpleAuthenticationSource) {
principal = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**credentials = conf.ldap.context.managerPassword // 'secret'**
}
You don't need to override the doWithSpring() method in the existing plugin. You can provide your own plugin which loads after the one you want to affect and have your doWithSpring() add whatever you want to the context. If you add beans with the same name as the ones added by the other plugin, yours will replace the ones provided by the other plugin as long as you configure your plugin to load after the other one. Similarly, you could do the same think in resources.groovy of the app if you don't want to write a plugin for this.
You have other options too. You could write a bean post processor or bean definition post processor that affects the beans created by the other plugin. Depending on the particulars, that might be a better idea.
EDIT:
After seeing your comment below I created a simple example that shows how you might use a definition post processor. See the project at https://github.com/jeffbrown/postprocessordemo.
The interesting bits:
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomeBean.groovy
package demo
class SomeBean {
String someValue
}
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomePostProcessor.groovy
package demo
import org.springframework.beans.BeansException
import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.PropertyValue
import org.springframework.beans.factory.config.BeanDefinition
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
class SomePostProcessor implements BeanDefinitionRegistryPostProcessor{
#Override
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinition definition = registry.getBeanDefinition('someBean')
MutablePropertyValues values = definition.getPropertyValues()
PropertyValue value = values.getPropertyValue('someValue')
def originalValue = value.getValue()
// this is where you could do your decrypting...
values.addPropertyValue('someValue', "MODIFIED: ${originalValue}".toString())
}
#Override
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/conf/spring/resources.groovy
beans = {
someBean(demo.SomeBean) {
someValue = 'Some Value'
}
somePostProcessor demo.SomePostProcessor
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/init/postprocessordemo/BootStrap.groovy
package postprocessordemo
import demo.SomeBean
class BootStrap {
SomeBean someBean
def init = { servletContext ->
log.info "The Value: ${someBean.someValue}"
}
def destroy = {
}
}
At application startup you will see log output that looks something like this...
2017-10-23 19:04:54.356 INFO --- [ main] postprocessordemo.BootStrap : The Value: MODIFIED: Some Value
The "MODIFIED" there is evidence that the bean definition post processor modified the property value in the bean. In my example I am simply prepending some text to the string. In your implementation you could decrypt a password or do whatever you want to do there.
I hope that helps.
After trying Jasypt plugin and BeanPostProcessor solutions unsuccessfully for my use case, I found below solution to work perfectly.
To describe again the problem statement here,
a) we had to keep the passwords in an encrypted format inside properties files
b) and given we were packaging as a war file so the properties must not be kept inside the war to allow automated deployment scripts update the encrypted passwords depending on the environment
Jasypt plugin was a perfect solution for the use case a), but it was not able to cover the b) scenario
Moreover, the Grails LDAP Security plugin was getting loaded quite early hence Bean Post processors were also not helping out here.
Solution:
Created a new class by implementing the interface SpringApplicationRunListener. Extended its methods and parsed the properties file using YamlPropertySourceLoader
Sample code:
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
PropertySource<?> applicationYamlPropertySource = loader.load(
"application.yml", new ClassPathResource("application.yml"),"default");
return applicationYamlPropertySource;
Once the properties were loaded inside the MapPropertySource object, parsed them for the encrypted values and applied the decryption logic.
This whole implementation was executed before any plugins were initialized during Grails bootup process solving the purpose.
Hope it will help others.
I would like to add to my log a String key and an Integer value using Log4j2.
Is there a way to do it? when I added properties to the ThreadContext I was able to add only String:String key and values but this does not help I have numbers that I need to present in Kibana (some graphs)
thanks,
Kobi
The built-in GelfLayout may be useful.
It's true that the default ThreadContext only supports String:String key-values. The work done in LOG4J2-1648 allows you to use other types in ThreadContext:
Tell Log4j to use a ThreadContext map implementation that implements the ObjectThreadContextMap interface. The simplest way to accomplish this is by setting system property log4j2.garbagefree.threadContextMap to true.
The standard ThreadContext facade only has methods for Strings, so you need to create your own facade. The below should work:
public class ObjectThreadContext {
public static boolean isSupported() {
return ThreadContext.getThreadContextMap() instanceof ObjectThreadContextMap;
}
public static Object getValue(String key) {
return getObjectMap().getValue(key);
}
public static void putValue(String key, Object value) {
getObjectMap().putValue(key, value);
}
private static ObjectThreadContextMap getObjectMap() {
if (!isSupported()) { throw new UnsupportedOperationException(); }
return (ObjectThreadContextMap) ThreadContext.getThreadContextMap();
}
}
It is possible to avoid ThreadContext altogether by injecting key-value pairs from another source into the LogEvent. This is (briefly) mentioned under Custom Context Data Injectors (http://logging.apache.org/log4j/2.x/manual/extending.html#Custom_ContextDataInjector).
I found default log4j2 implementation somewhat problematic for passing custom fields with values. In my opinion current java logging frameworks are not well suited for writing structured log events
If you like hacks, you can check https://github.com/skorhone/gelfj-alt/tree/master/src/main/java/org/graylog2/log4j2 . It's a library written for gelf. One of provided features is a layout (ExtGelfjLayout) that supports extracting custom fields (See FieldExtractor) from events. But... im order to send such event, you need to write your own logging facade on top of log4j2.
I need to intercept calls to private methods in Grails services. The following aspect IS working for any annotated public methods, however nothing happens when the annotation is at PRIVATE methods.
import exceptions.DwcpExeption
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
#Aspect
#Component
public class LoggerInterceptor {
private static Logger log = LoggerFactory.getLogger(LoggerInterceptor.class);
#Around("#annotation(newAnnotation)")
public Object aroundEvents(ProceedingJoinPoint proceedingJoinPoint, NewAnnotation newAnnotation) {
log.info newAnnotation.value()
String logMessage = String.format("%s.%s(%s)",
proceedingJoinPoint.getTarget().getClass().getName(),
proceedingJoinPoint.getSignature().getName(),
Arrays.toString(proceedingJoinPoint.getArgs()));
log.info "*Entering $logMessage"
def result
try {
result = proceedingJoinPoint.proceed()
catch (ex) {
log.error '', ex
}
log.info "*Exiting $logMessage. Result: $result"
return result
}
}
Maybe the problem is in config? I've tried in applicationContext.xml
<aop:aspectj-autoproxy proxy-target-class="true"/>
and in resources.groovy
aop.config("proxy-target-class": true)
Nevertheless, only public methods are intercepted.
Spring AOP is a proxy-based "AOP lite" approach in comparison to AspectJ. It only works for Spring components and only for public, non-static methods. This is also explained in the Spring AOP documentation as follows:
Due to the proxy-based nature of Spring’s AOP framework, protected methods are by definition not intercepted, neither for JDK proxies (where this isn’t applicable) nor for CGLIB proxies (where this is technically possible but not recommendable for AOP purposes). As a consequence, any given pointcut will be matched against public methods only!
If your interception needs include protected/private methods or even constructors, consider the use of Spring-driven native AspectJ weaving instead of Spring’s proxy-based AOP framework. This constitutes a different mode of AOP usage with different characteristics, so be sure to make yourself familiar with weaving first before making a decision.
Bottom line: Please switch to AspectJ which can be easily integrated into Spring applications via LTW (load-time weaving) as described in Section 9.8, “Using AspectJ with Spring applications”.
If you don't specify the scope it defaults to public. Add a pointcut for private methods:
#Around("#annotation(newAnnotation) && execution(private * *(..))")
I have a file under src/groovy and I have some properties that are in my Config.groovy and in external property file too. Normally if one want access properties its possible to use grailsApplication .configuration.property.name expression. I want to be able to access all those properties from this file that is under src/groovy directory. What I've tried so far
import grails.util.Holders
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
println Holders.grailsApplication.config.property.name
}
}
gave me NPE saying that grailsAppliction is null
import org.codehaus.groovy.grails.web.context.ServletContextHolder as SCH
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes as GA
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
def ctx = SCH.servletContext.getAttribute(GA.APPLICATION_CONTEXT)
def grailsAppliction = ctx.grailsApplication.getObject()
println grailsAppliction.config.property.name
}
}
the same - NPE because grailsAppliction is null
Is it possible to handle this situation somehow? Thank you!
Use the below and see if it works
println Holders.config.property.name
You don't need grailsApplication when using Holders.
The examples below are probably a little more complex than what you need, but they show how to get a configuration property at build time. I use them to merge two configuration files, but you might not need to do that.
This method returns a config property when called here at the CompileEnd event.
You could define a similar method in your app's _Events.groovy file that calls your own configuration holder class.
import org.codehaus.groovy.grails.commons.ConfigurationHolder;
class KeyAndSecret{
public static String consumerKey = ConfigurationHolder.config.consumerKey;
public static String consumerSecret = ConfigurationHolder.config.consumerSecret;
}
Try like this
What is the preferred way to remove a default pipeline contributor (OpenRasta 2.0.3)?
I haven't found a lot on that on the net, but one way seems to be writing a custom DependencyRegistrar, i.e. deriving from DefaultDependencyRegistrar and then e.g. overriding AddDefaultContributors(). Apart from that I doubt that it's the best way to remove just a single pipeline contributor, it seems to need additional per-host (ASP vs. InMemory) work, whereas I would consider messing with pipeline handlers to be a host-agnostic affair.
But even if I'd go this route, this guy here seems to have tried it without success: http://groups.google.com/group/openrasta/browse_thread/thread/d72b91e5994f402b
I tried similar things, but so far couldn't make my custom registrar replace the default.
So what's the simplest and best way to remove a default pipeline contributor, preferable in a host agnostic way? Is there a working example somewhere?
No, you just need to derive from the registrar and use the protected members that are available to imperatively remove the types you don't want auto-registered.
The registrar needs to be registered in your container before you provide it to OpenRasta, otherwise the type has been resolved already.
Answering myself with working code snippets as they might be helpful to others.
So it looks like removing default pipeline contributors cannot be done
in a host agnostic way (although I don't see why OpenRasta could not
be modified to allow for easy deletion of handlers in the future).
The 2 classes that need to be written are in fact independent of the
host(s) used:
public class MyDependencyRegistrar : DefaultDependencyRegistrar
{
protected override void AddDefaultContributors()
{
base.AddDefaultContributors();
PipelineContributorTypes.Remove(typeof(HandlerResolverContributor));
// If we remove the only contributor for the 'well-known'
// IHandlerSelection stage, like done above, we need to add
// another one implements IHandlerSelection, otherwise
// we'll run into errors (and what's the point of a pipeline
// without a handler selector anyway?). So let's do that here:
AddPipelineContributor<MyOwnHandlerResolverContributor>();
}
}
In order to make that Registrar available, we need to create an accessor
like the following, which then needs to be set in the various hosts:
public class MyDependencyResolverAccessor : IDependencyResolverAccessor
{
InternalDependencyResolver resolver;
public IDependencyResolver Resolver
{
get
{
if (resolver == null)
{
resolver = new InternalDependencyResolver();
resolver.AddDependency<IDependencyRegistrar, MyDependencyRegistrar>();
}
return resolver;
}
}
}
For Asp.Net, this seems to work for me:
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
OpenRastaModule.Host.DependencyResolverAccessor =
new MyDependencyResolverAccessor();
For InMemoryHost, which I use for integration testing and in-process access
of my handlers, I haven't found a way around copying the whole class
InMemoryHost and modifying it to my needs. In fact, we don't need
MyDependencyResolverAccessor in this case, as InMemoryHost implements
IDependencyResolverAccessor already. So here's how it could look like. Only the
last line was actually added to the existing code in InMemoryHost:
public class TwinMemoryHost : IHost, IDependencyResolverAccessor, IDisposable
{
readonly IConfigurationSource _configuration;
bool _isDisposed;
public TwinMemoryHost(IConfigurationSource configuration)
{
_configuration = configuration;
Resolver = new InternalDependencyResolver();
Resolver.AddDependency<IDependencyRegistrar, MyDependencyRegistrar>();
...