How to use a custom annotation - jsweet

With the JSweet toot, I want to generate an annotation in the typescript code, once I encounter a Java annotation on a class. Concretely, I want to accomplish the following:
#com.fasterxml.jackson.annotation.JsonSubTypes(
{
#com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = Person.class, name = "Person"),
#com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = Department.class, name = "Department")
})
// #JsonSubTypes({ types: [{class: () => Person, name: 'Person'}, {class: () => Department, name: 'Department'}]})
public abstract class Root {
should be translated into
#JsonSubTypes({ types: [{class: () => Person, name: 'Person'}, {class: () => Department, name: 'Department'}]})
abstract class Root {
I have made a custom annotation using the example here,
and I tried to process the annotation using the example here.
However, the AnnotationManager of JSweet only uses the jsweet.lang annotations part of the Jsweet framework, and not the added annotation by meself.
In other4 words: how to add my custom annotation to the Jsweet annotation manager?
Thanks,
-- Jaap

Related

Javax validation of generics in Springboot with Kotlin

I have a controller:
#PostMapping
fun create(
#RequestBody #Valid request: MyContainer<CreateRequest>,
): MyContainer<Dto> = service.create(request.objects)
with MyContainer and CreateRequest looking something like this:
class MyContainer<T>(
#field:Valid // also tried param
#field:NotEmpty(message = "The list of objects can not be null or empty")
var objects: List<#Valid T>? = listOf(),
)
class CreateRequest(
#field:NotNull(message = "Value can not be null")
var value: BigDecimal? = null,
)
In my tests, the "outer" validation works, that is I do get the expected error message if I send it { "objects": null } or { "objects": [] }. But I can not get it to validate the contents of the list. From what I understand in Java List<#Valid T> should work, but for whatever I can not get it to work in kotlin.
I figured I might need some kind of use-site target on #Valid in List<#Valid T>, but I can't find one that's applicable for this use case.
How can I get the validation to work for the list?
I managed to find a solution myself.
Apparently get: is the correct use-site target, not field: or param:. Furthermore the #Valid in List<#Valid T> was not necessary.
For reference, here's the working class (also changed it back to a data class as that doesn't seem to pose an issue).
class MyContainer<T>(
#get:Valid
#get:NotEmpty(message = "The list of objects can not be null or empty")
var objects: List<T>? = listOf(),
)
and the CreateRequest:
class CreateRequest(
#get:NotNull(message = "Value can not be null")
var value: BigDecimal? = null,
)
Changing to the get: use-site target was only necessary for #Valid, but I opted for using it everywhere for consistency and since it seems to be the one that works best.

Swagger 2 UI How to show models that are not explicitly returned by RestController

I'm having following issue, on swagger under Models, i see just abstract Base class that is extended by 3 other classes. My current end point returns Base type of class, because i can have 3 different types returned on one end point.
So basically i have something like this
#MappedSuperclass
#ApiModel(description = "Base Details.")
abstract class BaseClass(
open var id: String? = null,
var prop1: String? = null,
var prop2: String? = null,
var prop3: String? = null,
var prop4: String? = null
)
#ApiModel(description = "Some Specific Details that contains all base properties.")
data class AnotherClass(
val prop4: String,
val prop5: String,
val prop6: Set<Amount>,
val prop7: Set<Amount>,
val prop8: String
) : BaseClass()
#ApiModel(description = "Some more Specific Details that contains all base properties.")
data class OneMoreClass(
val prop4: String,
val prop5: String
) : BaseClass()
And in RestController i have this
#GetMapping
#ApiOperation(value = "End point description", notes = "Notes notes notes.")
fun getSomethingFromDatabase(): List<BaseClass> {
return someService.getData();
}
So issue that i have is on swagger UI, under Models section i see just BaseClass and no other classes at all...
I tried this, because somewhere i seen this example:
#ApiModel(description = "Base Details.", subTypes = {AnotherClass.class})
BaseClass
but this way i have "kotlin" issue, that is saying "name is missing", also i can not do AnotherClass::class...
You will have to add those in the config as below:
return new Docket(DocumentationType.SWAGGER_2)
.additionalModels(typeResolver.resolve(AnotherClass.class), typeResolver.resolve(OneMoreClass.class))
.....
subTypes is still not completely supported in Swagger 2, still has an open ticket
For your Kotlin config, this is how it should look like:
subTypes = [AnotherClass::class, OneMoreClass::class]
I have just added a sample Kotlin controller for you to refer in my github project. Look for AnimalController.kt & SwaggerConfig for required setup.

How to migrate scr annotations of AdaptorFactory class to OSGI R6 annotations?

We are migrating from AEM 6.0 to 6.3 and in process moving from Felix to OSGI scr annotations.
I have a code like this
#Component
#Service(AdapterFactory.class)
#Properties({
#Property(name = "CustomManagerAdapter", value = "adapter/factory"),
#Property(name = SlingConstants.PROPERTY_ADAPTABLE_CLASSES, value = {
"org.apache.sling.api.resource.ResourceResolver",
"org.apache.sling.api.SlingHttpServletRequest",
"org.apache.sling.api.resource.Resource"
}),
#Property(name = SlingConstants.PROPERTY_ADAPTER_CLASSES, value = "com.myapp.util.user.CustomUser")
})
public class CustomUserAdapter implements AdapterFactor
How to multi valued properties like SlingConstants.PROPERTY_ADAPTABLE_CLASSES into R6 annotation?
I tried like:
#Component(service = AdapterFactory.class, property={
SlingConstants.PROPERTY_ADAPTER_CLASSES + "=com.myapp.util.user.CustomUser",
SlingConstants.PROPERTY_ADAPTABLE_CLASSES+"={\"org.apache.sling.api.resource.ResourceResolver\"}",
"CustomManagerAdapter=adapter/factory"
})
This didnt work. Please share an example of migrating multivalued prperties.
To register multivalued properties, repeat the declaration for the property multiple times. The key, i.e property name remains same while the property value changes.
Ex:
#Component(
service = AdapterFactory.class,
immediate = true,
property = {
"adaptables=org.apache.sling.api.resource.Resource",
"adaptables=org.apache.sling.api.SlingHttpServletRequest",
"adapters=<Myclass>"
}
)

SpEL not able to extract attribute value from Scala object

I have a simple Scala class called Case
case class Case(
#(Id#field) var id: String,
var state: CaseState = new OpenCaseState,
var notes: List[CaseNote] = new ArrayList(),
var assignedGroups:Set[String] = new HashSet(),
var aclTemplateIds: Set[String] = new HashSet()
) extends Serializable { }
I created an instance of this class called a_case, setting id as 123. I am trying to get the value of the id attribute. I tried this
var parser: ExpressionParser = new SpelExpressionParser
var context: EvaluationContext = new StandardEvaluationContext(a_case)
var extractedId = parser.parseExpression("'id'").getValue(context).asInstanceOf[String]
All I get is "id" in my extractedId variable. When I try to parse "id" without the single quotes, I get an exception saying the property id is not found in Case. Am I missing something here or is this a Scala issue?
SpEL can do that for you if your id has getter.
I'm not well with Scala, but:
BeanProperty
You can annotate vals and vars with the #BeanProperty annotation. This generates getters/setters that look like POJO getter/setter definitions. If you want the isFoo variant, use the BooleanBeanProperty annotation. The ugly foo$_eq becomes
setFoo("newfoo");
getFoo();
https://twitter.github.io/scala_school/java.html

Array of annotations as parameter to an annotation, in Scala

There are plenty of questions about passing an array as a parameter to an annotation, this is not a dupe of those.
I would like to use a Java-land annotation that takes an array of annotations as a parameter, e.g.
#ManagedOperation
#ManagedOperationParameters({
#ManagedOperationParameter(name="start"),
#ManagedOperationParameter(name="end")
})
def stuff(start: String, end: String): Unit = ???
But this is not valid syntax in Scala, nor is
#ManagedOperation
#ManagedOperationParameters(Array(
#ManagedOperationParameter(name="start"),
#ManagedOperationParameter(name="end")
))
def stuff(start: String, end: String): Unit = ???
so what is the correct way to do this, if it is even possible?
BTW, I even checked all of github to see if any Scala devs are using this (Spring JMX) annotation.
In scala the inner annotation should be used as regular type:
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "moduleType",
defaultImpl = classOf[PuppetModule]
)
#JsonSubTypes(Array(
new Type(value = classOf[PuppetModule], name = "puppet"),
new Type(value = classOf[PluginModule], name = "plugin")
))
trait Module {
val moduleType: String = if (this.isInstanceOf[PuppetModule]) "puppet" else "plugin"
val nodes: List[String] = List[String]()
}

Resources