Get pathVariable in Aspect - Spring boot - spring

I want implement an annotation in spring boot. It's required to get path variable and use in annotation.
#PostMapping("/v1/{id}")
#HasZone(id = "#id")
#ResponseStatus(HttpStatus.NO_CONTENT)
fun createCompany( #PathVariable id: String) {
....
}
#Target(AnnotationTarget.FUNCTION)
annotation class HasZone(vararg val id: String)
#Before("#annotation(hasZone)")
fun checkZonePermissions(hasZone: HasZone) {
println(hasZone.id)
}
I get the parameter in PreAuthorize like this: #id. But in this function, name of the variable path to function as a string.
Where is the wrong thing to do?
How can I fixed the problem?

Related

Custom ConditionalGenericConverter annotation doesn't convert parameters in Spring GraphQL

I have a REST API developed in Spring and now I'm learning how to use GraphQL in my Spring project so I'm "translating" my REST endpoints to GraphQL queries.
Just to give some background on what I'm trying to do, I will show how one of my REST controllers look like (code in Kotlin):
Rest Controller
#RestController
#RequestMapping("countries")
class CountryController(private val countryService: CountryService) {
#GetMapping("{code}")
fun findByCode(#PathVariable #Uppercase code: String): Country {
return countryService.findByCode(code)
}
}
It's basically an endpoint that fetches a country based on a code. For example /countries/bra will fetch information about the country Brazil.
In the code above there's also a custom annotation called #Uppercase. This annotation extends ConditionalGenericConverter and the only thing it does is to take the code parameter and convert it to uppercase. This is the code for this annotation:
#Uppercase implementation
#Target(AnnotationTarget.VALUE_PARAMETER)
annotation class Uppercase
#Component
class UppercaseConverter : ConditionalGenericConverter {
override fun matches(sourceType: TypeDescriptor, targetType: TypeDescriptor): Boolean {
return targetType.getAnnotation(Uppercase::class.java) != null
}
override fun getConvertibleTypes(): MutableSet<ConvertiblePair>? {
return mutableSetOf(ConvertiblePair(String::class.java, String::class.java))
}
override fun convert(source: Any?, sourceType: TypeDescriptor, targetType: TypeDescriptor): String {
return (source as String).uppercase()
}
}
Everything works as expected in the code above and the code parameter is always converted to uppercase if I use the #Uppercase annotation in my REST controller.
Now I created a similar controller for Spring GraphQL that looks like this:
GraphQL Controller
#Controller
class CountryResolver(private val countryService: CountryService) {
#QueryMapping(name = "country")
fun findByCode(#Argument #Uppercase code: String): Country {
return countryService.findByCode(code)
}
}
And my GraphQL is executed properly with the code above, except that the parameter code is not converted to uppercase when I use my custom annotation #Uppercase. It seems that my custom annotation only works with #PathVariable in the REST controller, but it doesn't with #Argument in the GraphQL controller.
Any idea why on how to make it work with GraphQL as well? Thanks in advance!

spring json serialization issue

I am unable to get is_secure object attribute in json response, what is wrong with this code ?
#Configuration
class RouterConfiguration( ) {
#Bean
fun testRoutes(testHandler: TestHandler) = coRouter {
GET("/test", testHandler::testFunction)
}
}
data class TestClass(
val is_secure: Int? = 1,
val xyz: String?
)
#Component
class TestHandler{
suspend fun testFunction(request: ServerRequest): ServerResponse =
ServerResponse.ok().bodyValueAndAwait(TestClass(1,"abc"))
}
is prefixed fields (with camelCase or snake_case pattern) are only serialized if they are of type Boolean. You can find more details about it here.
If you wish to keep the is prefix, you may do so by using #get use-site target. Just use #get:JsonProperty("is_secure") on the is_secure field and it should do.

JSON key is missing (using #JsonComponent on Spring-boot with kotlin)

Thanks reading this question.
this problem confused me.
I created code that response JSON data like below.
#RestController
class JsonTestController {
#GetMapping("jsonTest")
fun jsonTest(): ResponseEntity<HaveBoolean> {
val value = BooleanValue(true)
return ResponseEntity.ok(HaveBoolean(value))
}
data class BooleanValue(val value: Boolean)
data class HaveBoolean(
val isAdmin: BooleanValue,
)
}
and #JsonComponent is below.
#JsonComponent
class BooleanValueJson {
class Serializer : JsonSerializer<JsonTestController.BooleanValue>() {
override fun serialize(value: JsonTestController.BooleanValue, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeBoolean(value.value)
}
}
class Deserializer : JsonDeserializer<JsonTestController.BooleanValue>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): JsonTestController.BooleanValue =
JsonTestController.BooleanValue(p.valueAsBoolean)
}
}
When I request localhost://8082/jsonTest, I got empty json ({}).
but, I tried other variable name like hoge, mean coding like below.
data class HaveBoolean(
val hoge: BooleanValue,
)
then, I request again, I can get correctly json ({"hoge": true}).
Can't I use isAdmin name on data class ?
Do you have any idea why this problem is happening?
thanks.
This is a known issue with jackson in kotlin. Jackson basically tries to remove is from the name but kotlin data class implementation doesn't have a proper getter without "is" resulting in mismatch. You can add JsonProperty("isAdmin") to the variable and it should work.
data class HaveBoolean(
#get:JsonProperty("isAdmin")
val isAdmin: BooleanValue,
)

Inserting Post Method with Spring Boot

I'm learning Kotlin, part of my project is to integrate JSON as an object and use the POST method to change or add information.
I'm not able to do this, I need help.
package com.example.blog
import org.springframework.web.bind.annotation.*
data class Relatorio(
val titulo: String,
val autor: String,
val serie: String
)
#RestController
#RequestMapping("/Bradesco")
class BradescoController {
#GetMapping()
public fun relatorio(): Relatorio {
val result = Relatorio(
"Investimentos",
"Luis Felipe",
"Bradesco Analises"
)
return result
}
#PostMapping
#RequestMapping( #RequestBody "/empiricus")
public fun relatorio2() {
"titulo" = "Contra as altas taxas"
return "Atualizado";
}
}
It looks like some annotations are out of place in your relatorio2 method. You want to register a REST-endpoint for the POST-method and the path /empiricus.
This can happen one of two ways:
Annotate the method with #RequestMapping(value = "/empiricus", method = RequestMethod.POST)
Annotate the method with `#PostMapping("/empiricus") (you can omit the method-parameter from the example above, since this a shortcut for exactly that.
The #RequestBody annotation needs to be placed in the parameter of the relatorio2 method since it tells Spring to map the POST request-body to an object.
Therefore the method should look something like this:
#PostMapping("/empiricus")
public fun relatorio2(#RequestBody relatorio: Relatorio) {
"titulo" = "Contra as altas taxas"
return "Atualizado";
}
Since you added a path on class level, the complete path to call the method is /Bradesco/empiricus. When the object is available in the relatorio2 method, you can use it in your business logic.

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.

Resources