I wrote my property class like this
#Component
#ConfigurationProperties(prefix = "third")
and my application.yml is
third:
key1:
field1: value1
field2: value2
key2:
field1: value1
field2: value2
it will render third.key1 and third.key2
But when I remove key2 in my application.yml
third:
key1:
field1: value1
field2: value2
# key2:
# field1: value1
# field2: value2
then post actuator/refresh, it response third.key2
The response shows it has recognized things changed in application.yml
the bean stil render third.key1 and third.key2
You can not delete a property by not providing it in a listing related to a "refresh" (aka update) process... If a property is not listed in such a list it is logical to assume it is simply do not need refresh - its value stays as it was before...
Instead of not providing it, provide it with an empty value.
third:
key1:
field1: value1
field2: value2
key2:
or in json:
{
"third" : {
"key1" : {
"field1" : "value1"
"field2" : "value2"
},
"key2" : ""
}
}
This should delete it.
If you want refresh the config dynamic , you should add an annotation in the class #RefreshScope.
#Component
#RefreshScope
#ConfigurationProperties(prefix = "third")
Also, your requirement need another component springcloud bus, you can check it in spring.io
Related
I'm doing transformation with dataform , I added some assertions in my transformation
example of table input (all types of columns are STRING):
id | valueu1 | value2 | value3
1 |1?2 | 01/01/1900 00:00:00|x1
2 |1.2 | 01-01-1900 00:00:00|x2
example of stg transformation:
config {
type: "table",
database: "dev",
schema: "schema1",
tags: ["staging", "daily"],
/* DESCRIPTION */
description:"some description",
columns: {
id: "description",
value1: "description",
value2: "description",
value3: "description" }
,
assertions: {
uniqueKey: ["id"],
nonNull: ["valueu1","value2"]
}
}
select
id,
safe_cast(
REGEXP_REPLACE(
value1,
",",
"."
) as numeric
) value1,
SAFE.PARSE_DATETIME('%d/%m/%Y %H:%M:%S', value2) value2,
value3
from
${ref('input')}
The problem here is when the assertion is failed beacause of column value1 or value2 of table input when I want to know the raw value from the view in assertionSchema I can't beacause in the view the value is null (the result of safe_cast).
How to get the raw value of column failed in the assertion, I know that I can get this value from input table, but I want to the value in the view of assertionSchema.
Thanks
Introduction
Let's say I have a Kotlin enum class:
enum class Type {
ONE,
TWO,
THREE,
FOUR
}
and a following data class:
data class Item(
val name: String,
val type: Type
)
Then I have a Single that emits a list of Items – can by anything but for example purposes, let's say it looks like that:
val itemsSingle = Single.just(listOf(
Item("A", Type.ONE),
Item("B", Type.ONE),
Item("C", Type.TWO),
Item("D", Type.THREE),
))
Problem
What I'd like to achieve is to have an RxJava stream that will output a map where keys come from Type and values are lists of Items matching a given Type value (where an undetermined, unsorted list of Items is provided by some other Single stream). The signature would be:
Single<Map<Type, List<Item>> // or Observable<Map<Type, List<Item>>
One additional requirement is that the map's keys should always exhaust all values from Type enum even if the itemsSingle stream contains no items for some Type values (or no items at all). So, for the provided itemsSingle example stream the returned map should look like this:
{
ONE: [ Item(name: "A", type: ONE), Item(name: "B", type: ONE) ],
TWO: [ Item(name: "C", type: TWO) ],
THREE: [ Item(name: "D", type: THREE) ],
FOUR: []
}
Attempt
With all the above, I've kinda achieved the desired result with following steps:
To satisfy the requirement of exhausting all Type enum values I first create a map that has an empty list for all possible Type values:
val typeValuesMap = Type.values().associate { it to emptyList<Item>() }
val typeValuesMapSingle = Single.just(typeValuesMap)
// result: {ONE=[], TWO=[], THREE=[], FOUR=[]}
I can get a map that contains items from itemsSingle grouped under respective Type value keys:
val groupedItemsMapSingle = itemsSingle.flattenAsObservable { it }
.groupBy { it.type }
.flatMapSingle { it.toList() }
.toMap { list -> list[0].type } // the list is guaranteed to have at least one item
// result: {ONE=[Item(name=A, type=ONE), Item(name=B, type=ONE)], THREE=[Item(name=D, type=THREE)], TWO=[Item(name=C, type=TWO)]}
finally I can combine both lists using the combineLatest operator and overwriting initial empty list of items for a given Type value if itemsSingle contained any Items for this Type value:
Observable.combineLatest(
typeValuesMapSingle.flattenAsObservable { it.entries },
groupedItemsMapSingle.flattenAsObservable { it.entries }
) { a, b -> listOf(a, b) }
.defaultIfEmpty(typeValuesMap.entries.toList()) // in case itemsSingle is empty
.flatMapIterable { it }
.collect({mutableMapOf<Type, List<Item>>()}, { a, b -> a[b.key] = b.value})
// result: {FOUR=[], ONE=[Item(name=A, type=ONE), Item(name=B, type=ONE)], THREE=[Item(name=D, type=THREE)], TWO=[Item(name=C, type=TWO)]}
Summary
As you can see, it's quite a lot of code for a seemingly simple operation. So my question is – is there a simpler way to achieve the result I'm after?
Just merge a map of empty lists with a map of filled lists
val result = itemsSingle.map { items->
Type.values().associateWith { listOf<Item>() } + items.groupBy { it.type }
}
How do I get an array or list of field names that were set to optional in Joi object?
For example:
export const schema = Joi.object<SomeType>({
field1: Joi.string().required(),
field2: Joi.string().guid(),
field3: Joi.string().allow('').optional(),
field4: Joi.string().allow('').optional(),
});
I should be able to retrieved field3, field4.
Hapi Joi https://www.npmjs.com/package/#hapi/joi
You can use describe to do so:
Returns an object that represents the internal configuration of the
schema. Useful for debugging and exposing a schema's configuration to
other systems, like valid values in a user interface.
And here we go:
for (const [key, value] of Object.entries(queueSchemaBase.describe().keys)) {
if (value.flags?.presence === 'optional') {
console.log(`${key} is optional`);
}
}
Output:
field3 is optional
field4 is optional
I have a Python and R background and I am used to work with dataframes.
If I have a following table:
>>> table
ID Phone Email Value
------------------------------
ID1 15555555555 None None
ID2 None 3Email None
ID3 3123 4Email aaa
deriving two tables from table would look like this:
>>> table1=table[["ID","Phone","Email"]]
>>> table1
ID Phone Email
------------------------
ID1 15555555555 None
ID2 None 3Email
ID3 3123 4Email
>>> table2=table[["ID","Value"]]
>>> table2
ID Value
---------
ID1 None
ID2 None
ID3 aaa
Now I am trying to achieve the same with Golang. Below is my first step:
package main
import (
"fmt"
)
type Identification struct {
ID string
Phone int64
Email string
Value string
}
func main() {
// define slice of Identification
var idents []Identification
idents = append(idents, Identification{ID: "ID1", Phone: 15555555555})
idents = append(idents, Identification{ID: "ID2", Email: "3Email"})
idents = append(idents, Identification{ID: "ID3", Phone:3123, Email: "4Email", Value: "aaa"})
fmt.Println(idents)
}
Result:
[{ID1 15555555555 } {ID2 0 3Email } {ID3 3123 3Email aaa}]
My question is how can I slice identsthe same way I did with Python in the example?
Structures in go cannot be split, all you could do is reset the values of the fields you want to get rid of.
You'd need a map to achieve what you see in Python. But Go is a typed language,so in order to store arbitrary data you can use the interface{} type. Therefore you'd need to do it with an map[string]interface{} as you are storing data of different types, otherwise make everything strings and use map[string]string.
Then for slicing, well go doesn't have anything in the standard package to slice columns. Luckily, some people have worked on opensource packages to make your life easier :) I suggest you that one https://github.com/go-gota/gota
If you'd have to do it yourself, you could do that:
package main
import "fmt"
type table []map[string]interface{}
func (t table) sliceColumns(cols ...string) table {
// create our new resulting table
var newTable = make(table, len(t))
// loop through table and populate our newTable
for i, m := range t {
var n = make(map[string]interface{}, len(cols))
for _, col := range cols {
if v, ok := m[col]; ok {
n[col] = v
}
}
newTable[i] = n
}
return newTable
}
func main() {
// define slice of Identification
var t = table{
{
"ID": "1",
"Phone": 155555,
},
{
"ID": "2",
"Email": "3Email",
},
{
"ID": "3",
"Email": "4Email",
"Value": "aaaa",
"Phone": "123",
},
}
fmt.Println(t.sliceColumns("ID", "Phone")) // [map[ID:1 Phone:155555] map[ID:2] map[ID:3 Phone:123]]
}
I am writing an api spec with RAML. I have a GET api with three query parameters. One of them is optional. In the case of other two, one of them should be present at least. How do I define this in the api spec
/api
description: api end point
queryParameters:
field1:
description: field1
required: false
type: string
field2:
description: field2
required: false
type: string
field3:
description: field3
required: false
type: string
Here field1 is completely optional. It is ok if we don't have it. But out of the other two, either field2 or field3 should be present.
So the api call should be
/api?field2=value or /api?field3=value
How do I do this in raml?
You can split the query params in two types (one for every combination) and use a union type:
types:
oneParam:
properties:
field1:
description: field1
required: false
type: string
field3:
description: field3
type: string
otherParam:
properties:
field1:
description: field1
required: false
type: string
field2:
description: field2
type: string
/api:
description: api end point
get:
queryParameters:
type: oneParam | otherParam
If you want to force so that the bad request is returned in case of no parameter is passed, then you can try to use minProperties:
{types:
oneParam:
**minProperties: 1**
properties:
field1:
description: field1
required: false
type: string
field3:
description: field3
type: string
otherParam:
**minProperties: 1**
properties:
field1:
description: field1
required: false
type: string
field2:
description: field2
type: string
/api:
description: api end point
get:
queryParameters:
type: oneParam | otherParam
}