Using Scala classes as DTOs in Spring MVC - spring

In my project I'm using Spring + Scala.
Some of my Spring MVC controllers uses Spring feature for binding incoming HTTP parameters to DTO object. Like this:
#RequestMapping(value = Array("/", ""), method = Array(RequestMethod.POST))
def saveProduct(dto: MyDto): Iterable[MyDto] = {...}
And MyDto is simple scala class:
class MyDto extends Serializable {
#BeanProperty var id : Long = _
#BeanProperty var name: String = _
}
My problem is that I'm getting exceptions when trying to use Scala Option class for fields in MyDto:
class MyDto extends Serializable {
#BeanProperty var id : Option[Long] = None
#BeanProperty var name: Option[String] = None
}
Exception message is:
Failed to convert property value of type 'java.lang.String' to required type 'scala.Option' for property 'name';
What I can do to use Scala Options as type if fields in MyDto?

I am not a Scala expert, but here is one way:
Create a converter, along these lines:
import org.springframework.core.convert.converter.Converter
class TypeToOptionOfTypeConverter[T] extends Converter[T, Option[T]] {
override def convert(source: T): Option[T] = {
Some(source)
}
}
Register this converter with Spring MVC:
class WebConfig extends WebMvcConfigurerAdapter {
override def addFormatters(registry: FormatterRegistry): Unit = {
registry.addConverter(classOf[String], classOf[Option[String]], new TypeToOptionOfTypeConverter[String])
registry.addConverter(classOf[Long], classOf[Option[Long]], new TypeToOptionOfTypeConverter[Long])
}
}
That should be it, now your DTO should get cleanly mapped.

Spring has support for converting types using converters with its data binding. You will need to implement the converter so that Spring knows how to convert, for example, String to Option[String].
See:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert

Related

Expose public field of POJO to FTL in Spring

I can't figure out how to send a POJO to my template in Spring Boot.
Here's my POJO and my controller:
class DebugTest {
public String field = "Wooowee";
public String toString() {
return "testie " + field;
}
}
#Controller
#RequestMapping("/debug")
public class WebDebugController {
#RequestMapping(value = "/ftl", method = RequestMethod.GET)
public ModelAndView ftlTestPage(Model model) {
DebugTest test = new DebugTest();
ModelAndView mnv = new ModelAndView("debug");
mnv.addObject("test", test);
return mnv;
}
}
Here's my template:
HERES THE TEST: ${test}$
HERES THE TEST FIELD: ${test.field}$
Here's the output (GET /debug/ftl):
HERES THE TEST: testie Wooowee$
HERES THE TEST FIELD: FreeMarker template error (DEBUG mode; use RETHROW in production!):
The following has evaluated to null or missing:
==> test.field [in template "debug.ftl" at line 3, column 25]
[Java stack trace]
The class itself (DebugTest) must be public too, as per the JavaBeans Specification. Also, fields by default aren't exposed. Defining getter methods is generally the best (with Lombok maybe), but if you want to go with fields, configure the ObjectWrapper as such. As you are using Spring Boot, I think that will be something like this in your application.properites:
spring.freemarker.settings.objectWrapper=DefaultObjectWrapper(2.3.28, exposeFields = true)

Custom serialization of single #RestController endpoint

Is there a way (preferably some type of annotation) to register a custom serializer for a single endpoint in a #RestController? Extending the bean and putting a #JsonSerialize on it would be an option, but that demands an otherwise pretty useless new bean class. I tried the following:
#JsonSerialize(using = CustomSerializer.class)
#RequestMapping(value = "/some_endpoint/", method = RequestMethod.GET)
public SomeType someEndpoint() {
return someObject;
}
But the #JsonSerialize annotation doesn't appear to have any meaning to Spring in that context. Is there an alternative or is the extra bean class my only option?
You can use #JsonView(View.Summary::class) in the attributes you want to add or ignore and in the method you want to apply that view, for example:
public class View {
public interface Summary
}
public class A{
#JsonView(View.Summary.class)
private String serialized = "",
private String notSerialized = ""}
and then in the controller:
#JsonView(View.Summary.class)
#GetMapping("/")
#ResponseBody
public A getA(){
return A()
}
If you want to reverse the JsonView (serialize the atributtes who doesnt have the view). you can add the following propertie: spring.jackson.mapper.default-view-inclusion=true

Inject properties name into class anotation

Is it possible to inject property name into the procedureName?
im using spring boot.
Try to use the next the next construction:
procedureName = "${procedure}" but it doesnt work
Also to write the special PropertySourcesPlaceholderConfigurer i think it not a good idea .
#NamedStoredProcedureQueries({
#NamedStoredProcedureQuery(name = "test",
procedureName = "${procedure}",
parameters = {
})
})
public class R
try to get property from properties-test.yml
Spring properties used to inject values in bean properties like below,
public class ClassWithInjectedProperty {
#Value("${props.foo}")
private String foo;
}
you case is not valid for value injection.

Spring framework and java like Object collectors In Scala

In Spring framework and Java world, there is an interesting object collector pattern that I use.
For example consider below -
public interface Calculator {
SomeOutput calculate(SomeInput input);
}
#Component
public class CalImpl1 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
#Component
public class CalImpl2 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
Now this can easily injected in another class using Spring DI
#Component
public class Main {
//This line collects all to implementors of this and set it here.
#Autowired
public List<Calculator> calculators;
//other methods
}
Now problem is I am not sure how same thing can be achieved in scala. I have done some search and found cake pattern (http://loicdescotte.github.io/posts/scala-di/) used in scala but that didn't seem to achieve same thing as object collectors like above. I also want to follow open close principle which I think gets violated in cake pattern but using object collectors I can easily achieve it.
is there a way achieve same object collectors like implementation in scala?
There are templates in lighbend activator that illustration using spring DI on Play, Akka and Scala applications. Please see this: https://www.lightbend.com/activator/templates#filter:spring
I haven't used Spring as DI, I usually use Guice (explicitly used because it's default on play framework 2) and Implicits parameters both as a compilation DI.
Sample:
class B
class X(x: Int)(implicit c: B)
//DI - mostly define in main method/application
implicit val c: B = new B
val x = new X(2)
Explicitly using java.util.List worked for me. This is not the prettiest solution but it shows that it basically works. Haven't tried that but implementing a corresponding PropertyEditor you could stick with the Scala types.
trait Calculator {
def calculate(input: SomeInput) : SomeOutput
}
#Component
class CalImpl1 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class CalImpl2 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class Main #Autowired()(calculators: java.util.List[Calculator]) {
// or inject field if constructor injection is not desired
// #Autowired
// var calculators: java.util.List[Calculator] = _
}
object Main {
def main(args: Array[String]) = {
val ctx = new AnnotationConfigApplicationContext("your package name here")
val main = ctx.getBean(classOf[Main])
// calculators should now be wired in the returned instance
}
}

Cake Pattern and Spring Configurer

Spring provides utility Configurer to resolve placeholders with external configuration data (see the documentation for details). How can I configure my components in a similar way (that is, using external configuration to resolve placeholders) with Cake Pattern?
For example:
// properties configuration file
driver=com.mysql.jdbc.Driver
dbname=mysql:mydb
user=michael
password=*****
trait JdbcSupport {
val dataSource:Datasource
...
}
trait OrderDAOComponent {self: JdbcSupport =>
val dao: OrderDAO
class OrderDAOImpl extends OrderDAO {...} // use the JDBC data source here
}
How can I use the properties configuration file to initialize the OrderDAO using the Cake Pattern?
trait XmlConfigJdbcSupport extends JdbcSupport {
val xmlFile:String
override val dataSource = readConfigAndReturnDatasource()
}
object MyContext extends OrderDAOComponent with XmlConfigJdbcSupport {
override val xmlFile = "config.xml"
}
dataSource should probably be a lazy val to avoid problems with the initialization order.

Resources