Internationalization for user defined input - internationalization

I'm trying to build a localization for user defined input. Example: a user could define categories like soccer but in several languages.
The model entity could have a filed something like this:
#ManyToMany
#MapKeyColumn(name = "locale", insertable = false, updatable = false)
public Map<String, L18n> titles;
I'd like to store the localized strings like this:
#Entity
public class L18n {
#Id
#Constraints.Required
#Formats.NonEmpty
public Integer id;
public String key;
public String locale;
#Column(columnDefinition = "TEXT")
public String text;
}
We use yaml to store the testdata:
category:
- !!models.Category
...
titles:
- !!models.L18n
key: soccer
l18n:
- !!models.L18n
key: soccer
locale: de-CH
text: fdfdfsee
- !!models.L18n
key: soccer
locale: fr-CH
text: dlfkjsdlfj
With this solution I'm getting this error:
[error] Caused by: org.yaml.snakeyaml.error.YAMLException: No suitable constructor with 1 arguments found for interface java.util.Map
[error] at org.yaml.snakeyaml.constructor.Constructor$ConstructSequence.construct(Constructor.java:574)
[error] at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:182)
[error] at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:296)
[error] ... 65 more

I think the problem is you've defined titles as a map, but don't use the YAML mapping syntax to define it. YAML Collections
I think the syntax for titles should look like the example here using langauges: YAML Dictionary Example
titles:
soccer: - !!models.L18n
key: soccer
locale: de-CH
text: fdfdfsee
football: - !!models.L18n
...
If you change the format of your .yml file so that the L18n instances are defined first and use references, the YAML spec calls them Alias Nodes, you could make your titles look a lot more streamlined:
l18n:
- &soccerDE !!models.L18n
key: soccer
locale: de-CH
text: fdfdfsee
- &soccerFR !!models.L18n
key: soccer
locale: fr-CH
text: dlfkjsdlfj
category:
- !!models.Category
...
titles:
soccerDE: *soccerDE
soccerFR: *soccerFR

Related

How to connect to remote oracle database using typeorm in nestjs?

I was wondering how to connect to remote oracle database from nestjs using typeorm.
I installed typeorm and oracle package using following command.
npm i --save #nestjs/typeorm typeorm oracle
npm install oracledb --save
and then tried configuring in app.module.ts using TypeOrmModule.forRoot but it was not succesfull.
Here are my configuration settings.
TypeOrmModule.forRoot({
type: 'oracle',
host: 'ip of hostname',
port: port number,
username: 'username',
password: 'password',
serviceName: 'servicename',
synchronize: false,
entities: []
})
Can anybody help me out what am I missing? Also would like to know how can I execute the query once this connection is succesfully? If any example that would be helpfull.
Got it.
one missing thing was database name.
Added
database: 'databasename' in above configuration and it worked.
But, still my question is how to use this connection in service to fetch/push the data from/to oracle databse?
If you provide a name in your connection details you should be able to refer to the database connection using that. Otherwise, if no name is provided I believe it assigns it the name 'default'.
Basically these are the steps you should perform to use the database connection: (examples below each)
Create a model - this is how TypeORM knows to create a table.
export class Photo {
id: number
name: string
description: string
filename: string
views: number
isPublished: boolean
}
Create an Entity. - this should match your model, with the appropriate decorators. At minimum you should have the #Entity() decorator before your class definition and #Column() before each field.
import { Entity, Column } from "typeorm"
#Entity()
export class Photo {
#Column()
id: number
#Column()
name: string
#Column()
description: string
#Column()
filename: string
#Column()
views: number
#Column()
isPublished: boolean
}
Create your data source - looks like you have already done this. But I would give it a name field and you will need to pass your entities into the entity array you have.
const AppDataSource = new DataSource({
type: "postgres",
name: "photos",
host: "localhost",
port: 5432,
username: "root",
password: "admin",
database: "test",
entities: [Photo],
synchronize: true,
logging: false,
})
Then you can use repositories to manage data in the database:
const photo = new Photo()
photo.name = "Me and Bears"
photo.description = "I am near polar bears"
photo.filename = "photo-with-bears.jpg"
photo.views = 1
photo.isPublished = true
const photoRepository = AppDataSource.getRepository(Photo)
await photoRepository.save(photo)
console.log("Photo has been saved")
const savedPhotos = await photoRepository.find()
console.log("All photos from the db: ", savedPhotos)
For more details I would spend some time reading through the typeORM website, all the examples I pulled were from there:
https://typeorm.io/

Hibernate diffChangeLog producing change sets that exist already in the table

I am using spring boot with hibernate 5.3.8. After I run the first schema I generate a diffChangeLog and its dropping and creating the same index. When I look at the collection_days table a common_collection_search exists
How can I mark it as completed so it no longer appears in the diffChangeLog. I only want generate a changelog with the newest changes so I can run it and update the database
collection_days table
index_name|index_algorithm|is_unique|column_name|condition
common_collection_search|BTREE|f|waste_generator_id,refuse_type|NULL
This is from my master schema that I ran on a fresh database
- changeSet:
id: 1572649828026-46
author: comp (generated)
changes:
- createIndex:
columns:
- column:
name: wg_id
- column:
name: type
indexName: common_collection_search
tableName: collection_days
diffChangeLog results
- changeSet:
id: 1615578168770-16
author: comp (generated)
changes:
- dropIndex:
indexName: common_collection_search
tableName: collection_days
- changeSet:
id: 1615578168770-17
author: comp (generated)
changes:
- createIndex:
columns:
- column:
name: wg_id
- column:
name: type
indexName: common_collection_search
tableName: collection_days
CollectionDay entity
#Data
#Entity
#Table(name = "collection_days", uniqueConstraints = {
#UniqueConstraint(columnNames = { "wg_id", "type", "day_of_week" }) }, indexes = {
#Index(name = "common_collection_search", columnList = "wg_id,type") })
public class CollectionDay implements Serializable {
#Column(name = "wg_id",updatable = false,insertable = false)
private Long wgId;
#Column(name = "type")
#Enumerated(EnumType.STRING)
private ESEnums.type type;
build.gradle
compile "org.hibernate:hibernate-core"
compile "org.hibernate:hibernate-entitymanager"
compile "org.hibernate:hibernate-envers"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "com.zaxxer:HikariCP"
compile "org.hibernate:hibernate-ehcache"
compile 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5'
compile "org.postgresql:postgresql"
compile "org.liquibase:liquibase-core"
compile "org.hibernate:hibernate-validator:6.1.6.Final"
liquibaseRuntime 'org.liquibase.ext:liquibase-hibernate5:3.8'
liquibaseRuntime sourceSets.main.output
liquibaseRuntime sourceSets.main.compileClasspath
liquibase {
activities {
main {
driver 'org.postgresql.Driver'
url 'jdbc:postgresql://localhost:54323/db2?stringtype=unspecified'
username ''
password ''
changeLogFile "src/main/resources/liquibase/migrations/changelog.yaml"
classpath 'src/main/java'
referenceUrl 'hibernate:spring:com.project.domain.entities?dialect=org.hibernate.dialect.PostgreSQL82Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy'
}
}
}
I think the problem is that PostgreSQL is smart enough to realize that the index is unnecessary and doesn't create it in the way you expect it. Your unique constraint already covers the columns of the index and since it is backed by an index, it will just tell you that it won't create your index, because it is already covered.

Unable to generate example json value from yaml

I am trying to parse a given yaml to a JSON example like swagger does. I am using the below yaml.
$id: 'https://example.com/person.schema.json'
$schema: 'http://json-schema.org/draft-07/schema#'
title: Person
type: object
properties:
firstName:
type: string
example:MyName
description: The person's first name.
lastName:
type: string
description: The person's last name.
age:
description: Age in years which must be equal to or greater than zero.
type: integer
minimum: 0
I am trying to parse this yaml to its json like the below one. If the example is given in the yaml then it should show the example else it should show a default value.
Person:{
"firstName":"MyName",
"lastName":"string",
"age":0
}
But while parsing I am getting an Exception:
com.fasterxml.jackson.core.JsonParseException: Unrecognized token '$id': was expecting ('true', 'false' or 'null')
at [Source: (String)"$id: 'https://example.com/person.schema.json'
line: 1, column: 4]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:703) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2853) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddValue(ReaderBasedJsonParser.java:1899) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:757) ~[jackson-core-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4042) ~[jackson-databind-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:2551) ~[jackson-databind-2.9.8.jar:2.9.8]
at io.swagger.parser.SwaggerCompatConverter.readResourceListing(SwaggerCompatConverter.java:210) [swagger-compat-spec-parser-1.0.44.jar:1.0.44]
at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:123) [swagger-compat-spec-parser-1.0.44.jar:1.0.44]
at io.swagger.parser.SwaggerCompatConverter.readWithInfo(SwaggerCompatConverter.java:94) [swagger-compat-spec-parser-1.0.44.jar:1.0.44]
at io.swagger.parser.SwaggerParser.readWithInfo(SwaggerParser.java:42) [swagger-parser-1.0.44.jar:1.0.44]
at io.swagger.v3.parser.converter.SwaggerConverter.readLocation(SwaggerConverter.java:92) [swagger-parser-v2-converter-2.0.12.jar:2.0.12]
at io.swagger.v3.parser.OpenAPIV3Parser.read(OpenAPIV3Parser.java:90) [swagger-parser-v3-2.0.12.jar:2.0.12]
at io.swagger.v3.parser.OpenAPIV3Parser.read(OpenAPIV3Parser.java:78) [swagger-parser-v3-2.0.12.jar:2.0.12]
at com.pega.yaml.yamlToJsonExample.App.main(App.java:19) [classes/:na]
Exception in thread "main" java.lang.NullPointerException
at io.swagger.v3.parser.OpenAPIV3Parser.read(OpenAPIV3Parser.java:91)
at io.swagger.v3.parser.OpenAPIV3Parser.read(OpenAPIV3Parser.java:78)
at com.pega.yaml.yamlToJsonExample.App.main(App.java:19)
I am using swagger inflector 2.0.5 with the following code:
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.oas.inflector.examples.models.Example;
import io.swagger.oas.inflector.examples.ExampleBuilder;
import java.util.Map;
import com.fasterxml.jackson.databind.module.SimpleModule;
import io.swagger.oas.inflector.processors.JsonNodeExampleSerializer;
import io.swagger.util.Json;
public class App
{
public static void main( String[] args )
{
OpenAPI swagger = new OpenAPIV3Parser().read("Eclipse Workspace1\\yamlToJsonExample\\src\\main\\java\\com\\pega\\yaml\\yamlToJsonExample\\Test.yaml");
Map < String, Schema > definitions = swagger.getComponents().getSchemas();
Schema model = definitions.get("Person");
Example example = ExampleBuilder.fromSchema(model, definitions);
SimpleModule simpleModule = new SimpleModule().addSerializer(new JsonNodeExampleSerializer());
Json.mapper().registerModule(simpleModule);
String jsonExample = Json.pretty(example);
System.out.println(jsonExample);
}
}

Create AWS::Pinpoint::PushTemplate using CF template

Hi I want to create AWS::Pinpoint::PushTemplate using cloudformation template and I am following this link: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-pinpoint-pushtemplate.html.
Type: AWS::Pinpoint::PushTemplate
Properties:
Default:
Action: OPEN_APP
Body: FirstName - {{firstName}}, LastName - {{lastName}}
Title: Title
DefaultSubstitutions:
firstName: default
lastName: default
Tags:
project: project
tashi: "Pinpoint Template"
TemplateName: template_name
I am getting type validation error for`DefaultSubstitutions: Property validation failure: [Value of property {/DefaultSubstitutions} does not match type {String}]
According to docs DefaultSubstitutions is a String.
However, in your case, you set it up as map:
DefaultSubstitutions:
firstName: default
lastName: default
Maybe have to try using it as json string:
DefaultSubstitutions: "{\"firstName"\:\"default\", \"lastName"\:\"default\"}"

OpenApi - Is there a way to have a ComposedSchema with a discriminator part in a contract generated with springdoc-openapi-maven-plugin?

I have a sample SpringBoot API with the following features:
1 controller that exposes a single endpoint invokable with a GET request and that returns a custom class (ContainerClass in my example)
ContainerClass contains a property List
ParentClass is an abstract class that has 2 sub-classes: ChildA and ChildB
I try to generate an OpenApi contract from this API with springdoc-openapi-maven-plugin.
In my pom.xml, I have the following elements:
SpringBoot version: 2.2.6
org.springdoc:springdoc-openapi-ui:1.4.1
org.springdoc:springdoc-openapi-maven-plugin:1.0
Here are my classes I generate schema from.
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
public class ContainerClass {
#ArraySchema(
arraySchema = #Schema(discriminatorProperty = "classType"),
schema = #Schema(implementation = ParentClass.class)
)
public List<ParentClass> elements;
// + Getter/Setter
}
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "classType",
defaultImpl = ParentClass.class,
visible = true)
#JsonSubTypes({
#JsonSubTypes.Type(value = ChildA.class, name = "CHILD_A"),
#JsonSubTypes.Type(value = ChildB.class, name = "CHILD_B")})
#Schema(
description = "Parent description",
discriminatorProperty = "classType",
discriminatorMapping = {
#DiscriminatorMapping(value = "CHILD_A", schema = ChildA.class),
#DiscriminatorMapping(value = "CHILD_B", schema = ChildB.class)
}
)
public abstract class ParentClass {
public String classType;
// + Getter/Setter
}
#io.swagger.v3.oas.annotations.media.Schema(description = " Child A", allOf = ParentClass.class)
public class ChildA extends ParentClass{
}
#io.swagger.v3.oas.annotations.media.Schema(description = " Child B", allOf = ParentClass.class)
public class ChildB extends ParentClass{
}
When I run springdoc-openapi-maven-plugin, I get the following contract file.
openapi: 3.0.1
info:
title: OpenAPI definition
version: v0
servers:
- url: http://localhost:8080
description: Generated server url
paths:
/container:
get:
tags:
- hello-controller
operationId: listElements
responses:
"200":
description: OK
content:
'*/*':
schema:
$ref: '#/components/schemas/ContainerClass'
components:
schemas:
ChildA:
type: object
description: ' Child A'
allOf:
- $ref: '#/components/schemas/ParentClass'
ChildB:
type: object
description: ' Child B'
allOf:
- $ref: '#/components/schemas/ParentClass'
ContainerClass:
type: object
properties:
elements:
type: array
description: array schema description
items:
oneOf:
- $ref: '#/components/schemas/ChildA'
- $ref: '#/components/schemas/ChildB'
ParentClass:
type: object
properties:
classType:
type: string
description: Parent description
discriminator:
propertyName: classType
mapping:
CHILD_A: '#/components/schemas/ChildA'
CHILD_B: '#/components/schemas/ChildB'
Actually, in my context, in order to have not any breaking change with existing consumers, I need items property in ContainerClass schema to contain the discriminator part that is contained in ParentClass schema, like this:
ContainerClass:
type: object
properties:
elements:
type: array
description: array schema description
items:
discriminator:
propertyName: classType
mapping:
CHILD_A: '#/components/schemas/ChildA'
CHILD_B: '#/components/schemas/ChildB'
oneOf:
- $ref: '#/components/schemas/ChildA'
- $ref: '#/components/schemas/ChildB'
When I try to set properties in annotation, I don't manage to do that. And when I debug code of io.swagger.v3.core.jackson.ModelResolver, I don't manage to find a way to do that.
And so far I have not found an example of code that help me.
Is there a way so that a ComposedSchema (array contained in ContainerClass in my case) has a disciminator part generated by springdoc-openapi-maven-plugin execution?
This the default generation structure. Handled directly by swagger-api (and not springdoc-openapi.
The generated OpenAPI description looks coorect.
With springdoc-openapi, you can define an OpenApiCustomiser Bean, where you can change the elements of the components element defined on the OpenAPI level:
https://springdoc.org/faq.html#how-can-i-customise-the-openapi-object-
Here is my solution by defining an OpenApiCustomiser Bean:
#Bean
public OpenApiCustomiser myCustomiser() {
Map<String, String> classTypeMapping = Map.ofEntries(
new AbstractMap.SimpleEntry<String, String>("CHILD_A", "#/components/schemas/ChildA"),
new AbstractMap.SimpleEntry<String, String>("CHILD_B", "#/components/schemas/ChildB")
);
Discriminator classTypeDiscriminator = new Discriminator().propertyName("classType")
.mapping(classTypeMapping);
return openApi -> openApi.getComponents().getSchemas().values()
.stream()
.filter(schema -> "ContainerClass".equals(schema.getName()))
.map(schema -> schema.getProperties().get("elements"))
.forEach(arraySchema -> ((ArraySchema)arraySchema).getItems().discriminator(classTypeDiscriminator));
}
I get the expected result in my contract file.

Resources