Kotlin Singleton EJBs and CDI

Part of my learning curve in picking up Kotlin over the last three days was figuring out how to get dependency injection working using CDI (Java EE). I tried lateinit field injection but couldn't seem to get it working.

package net.brandonlamb.calendar.webapi.controllers

import net.brandonlamb.calendar.provider.CalendarService  
import net.brandonlamb.calendar.webapi.mapper.orika.CalendarMapper  
import net.brandonlamb.common.converters.DateConverter  
import net.brandonlamb.common.webapi.controllers.BaseController  
import net.brandonlamb.common.webapi.pagination.PagedRequest  
import java.util.*  
import javax.ejb.Lock  
import javax.ejb.LockType.READ  
import javax.ejb.Singleton  
import javax.inject.Inject  
import javax.ws.rs.*  
import javax.ws.rs.core.MediaType.APPLICATION_JSON  
import javax.ws.rs.core.MediaType.APPLICATION_XML

@Singleton
@Lock(READ)
@Consumes(APPLICATION_JSON, APPLICATION_XML)
@Produces(APPLICATION_JSON, APPLICATION_XML)
open class DateController @Inject constructor(  
  val mapper: CalendarMapper,
  val service: CalendarService,
  val pagedRequest: PagedRequest
) : BaseController() {
  @GET
  @Path("/")
  open fun getCalendarDate(
    @PathParam("calendarDate") date: String
  ): Response = Response.ok(
    mapper.map(service.findByDate(DateConverter.toLocalDate(date, 212001), locale))
  ).build()
}

Below are some of my learnings:

  • You must mark EJBs as open as they are proxied
  • You must also mark methods open
  • Use constructor injection with @Inject and constructor(), this seems to work