{"action":"created","issue":{"url":"https://api.github.com/repos/ninjaframework/ninja/issues/405","labels_url":"https://api.github.com/repos/ninjaframework/ninja/issues/405/labels{/name}","comments_url":"https://api.github.com/repos/ninjaframework/ninja/issues/405/comments","events_url":"https://api.github.com/repos/ninjaframework/ninja/issues/405/events","html_url":"https://github.com/ninjaframework/ninja/issues/405","id":108870400,"number":405,"title":"ObjectMapperProvider can not be replaced with a custom implementation","user":{"login":"omervk","id":1221264,"avatar_url":"https://avatars.githubusercontent.com/u/1221264?v=3","gravatar_id":"","url":"https://api.github.com/users/omervk","html_url":"https://github.com/omervk","followers_url":"https://api.github.com/users/omervk/followers","following_url":"https://api.github.com/users/omervk/following{/other_user}","gists_url":"https://api.github.com/users/omervk/gists{/gist_id}","starred_url":"https://api.github.com/users/omervk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/omervk/subscriptions","organizations_url":"https://api.github.com/users/omervk/orgs","repos_url":"https://api.github.com/users/omervk/repos","events_url":"https://api.github.com/users/omervk/events{/privacy}","received_events_url":"https://api.github.com/users/omervk/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2015-09-29T13:36:38Z","updated_at":"2015-10-01T18:51:29Z","closed_at":null,"body":"I am using Ninja and am using Scala's case classes as requests and responses. This is easily doable with `jackson-module-scala`. However, when I try to set the following to avoid null values in my responses:\r\n```\r\nobjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)\r\n```\r\nNothing changes.\r\n\r\nI've done a lot of digging to repro this issue and found that:\r\n\r\n1. ObjectMapper for Ninja Framework uses the Afterburner module (`jackson-module-afterburner`).\r\n2. Afterburner being registered before the Scala module (`jackson-module-scala`) causes Include.NON_NULL not to be taken into account when serializing options in case classes.\r\n3. Ninja declares its own global ObjectMapper using `ObjectMapperProvider`. This provider can't be replaced, injected, etc.\r\n4. There's no way to remove Afterburner after it has been set on an ObjectMapper.\r\n\r\nThe workaround to this is to replace the template engine's provider with a custom one that passes a custom object mapper in the `Module`:\r\n\r\n```\r\nval customObjectMapper = new ObjectMapper()\r\ncustomObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)\r\ncustomObjectMapper.registerModule(DefaultScalaModule)\r\ncustomObjectMapper.registerModule(new AfterburnerModule)\r\n\r\nbind(classOf[TemplateEngineJson]).toProvider(new Provider[TemplateEngineJson] {\r\n    override def get(): TemplateEngineJson =\r\n        new TemplateEngineJson(customObjectMapper)\r\n})\r\n```\r\n\r\nI would appreciate seeing a nicer implementation (such as being able to provide my own `ObjectMapperProvider`."},"comment":{"url":"https://api.github.com/repos/ninjaframework/ninja/issues/comments/144815094","html_url":"https://github.com/ninjaframework/ninja/issues/405#issuecomment-144815094","issue_url":"https://api.github.com/repos/ninjaframework/ninja/issues/405","id":144815094,"user":{"login":"raphaelbauer","id":524072,"avatar_url":"https://avatars.githubusercontent.com/u/524072?v=3","gravatar_id":"","url":"https://api.github.com/users/raphaelbauer","html_url":"https://github.com/raphaelbauer","followers_url":"https://api.github.com/users/raphaelbauer/followers","following_url":"https://api.github.com/users/raphaelbauer/following{/other_user}","gists_url":"https://api.github.com/users/raphaelbauer/gists{/gist_id}","starred_url":"https://api.github.com/users/raphaelbauer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raphaelbauer/subscriptions","organizations_url":"https://api.github.com/users/raphaelbauer/orgs","repos_url":"https://api.github.com/users/raphaelbauer/repos","events_url":"https://api.github.com/users/raphaelbauer/events{/privacy}","received_events_url":"https://api.github.com/users/raphaelbauer/received_events","type":"User","site_admin":false},"created_at":"2015-10-01T18:51:29Z","updated_at":"2015-10-01T18:51:29Z","body":"ok.. here's how I'd do it:\r\n\r\n1) Create an interface NinjaObjectMapper which has one method called getObjectMaper and returns an ObjectMapper.\r\n2) Then write a NinjaObjecMapperProvider which implements guice's Provider<NinjaObjectMapper> and has a get() method which returns the NinjaObjectMapper. In that provider we'll add the \"default\" configuration of the objectmapper as it is now.\r\n3) Annotate the NinjaObjectMapper interface with @ ProvidedBy(NinjaObjecMapperProvider.class)\r\n4) Replace all old stuff like ObjectMapperProvider, and make sure you inject a NinjaObjectMapper into the templates. Then you can call get() on NinjaObjectMapper and get the ObjectMapper for the templates.\r\n\r\nIf you want to provide your own configuration you can now create your own class that implements NinjaObjecMapperProvider and provide an explicit binding of your provider to NinjaObjecMapperProvider.class. That's how I'd do it (@jjlauer agreed?)....\r\n\r\nThat should solve everything...\r\nThe same should be done for the XmlMapper as well to keep things uniform....\r\n\r\nAs I wrote above - a PR would be very welcome, they usually get merged and you can see your improvement in the next release!\r\n\r\nLet us know if we can help further :)"}}