Error to map enums with MappingConstants.CASE_TRANSFORMATION - mapstruct

My mapstruct version is 1.5.0.Beta1
I'm trying to use #EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "uppercase") but the following error is displayed:
java: Illegal transformation for 'case' EnumTransformationStrategy. Error: 'Unexpected configuration for enum case transformation: uppercase'.
My usecase is:
public enum A {
ABCx,
EFGy
}
public enum B {
ABCX,
EFGY
}
#Mapper
public interface MyMapper {
#EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "uppercase")
B convert(A a);
}

The allowed values for the case transformation configuration are:
upper
lower
capital
You can read more about it here
This question also lead to creating mapstruct/mapstruct#2525 and to show the available options in the error message.

Related

R2DBC and enum (PostgreSQL)

Update 15/08/2020: Looks like Enum support was added on Jun 16. R2DBC commit.
Does H2DBC support PostgreSQL enums? I checked they git page but it doesn't mention anything about it. If it does, how enums could be used (INSERT, SELECT)?
Lets say PostgreSQL enum
CREATE TYPE mood AS ENUM ('UNKNOWN', 'HAPPY', 'SAD', ...);
Java class
#Data
public class Person {
private String name;
private Mood mood;
// ...
enum Mood{ UNKNOWN, HAPPY, SAD, ...}
}
I tried:
// insert
var person = ...;
client.insert()
.table("people")
.using(person)
.then()
.subscribe(System.out::println);
// select
var query = "SELECT * FROM people";
client.execute(query)
.as(Person.class)
.fetch().all()
.subscribe(System.out::println);
But I'm getting error messages:
# on insert
WARN [reactor-tcp-epoll-1] (Loggers.java:294) - Error: SEVERITY_LOCALIZED=ERROR, SEVERITY_NON_LOCALIZED=ERROR, CODE=42804, MESSAGE=column "mood" is of type mood but expression is of type character varying, HINT=You will need to rewrite or cast the expression., POSITION=61, FILE=parse_target.c, LINE=591, ROUTINE=transformAssignedExpr
# on select
ERROR [reactor-tcp-epoll-1] (Loggers.java:319) - [id: 0x8581acdb, L:/127.0.0.1:39726 ! R:127.0.0.1/127.0.0.1:5432] Error was received while reading the incoming data. The connection will be closed.
reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.data.mapping.MappingException: Could not read property private ...
I found similar post but without luck to solve my problem.. maybe I was applying it wrong..
Any help or tips are welcome.
Tested with org.springframework.data:spring-data-r2dbc:1.0.0.RELEASE and io.r2dbc:r2dbc-postgresql:0.8.1.RELEASE.
Kotlin version.
Define a enum class
enum class Mood {
UNKNOWN,
HAPPY,
SAD
}
Create a custom codec
class MoodCodec(private val allocator: ByteBufAllocator) : Codec<Mood> {
override fun canEncodeNull(type: Class<*>): Boolean = false
override fun canEncode(value: Any): Boolean = value is Mood
override fun encode(value: Any): Parameter {
return Parameter(Format.FORMAT_TEXT, oid) {
ByteBufUtils.encode(allocator, (value as Mood).name)
}
}
override fun canDecode(dataType: Int, format: Format, type: Class<*>): Boolean = dataType == oid
override fun decode(buffer: ByteBuf?, dataType: Int, format: Format, type: Class<out Mood>): Mood? {
buffer ?: return null
return Mood.valueOf(ByteBufUtils.decode(buffer))
}
override fun type(): Class<*> = Mood::class.java
override fun encodeNull(): Parameter =
Parameter(Format.FORMAT_TEXT, oid, Parameter.NULL_VALUE)
companion object {
// Get form `select oid from pg_type where typname = 'mood'`
private const val oid = YOUR_ENUM_OID
}
}
Registe the codec
You may need change runtimeOnly("io.r2dbc:r2dbc-postgresql") to implementation("io.r2dbc:r2dbc-postgresql")
#Configuration
#EnableR2dbcRepositories
class AppConfig : AbstractR2dbcConfiguration() {
override fun connectionFactory(): ConnectionFactory = PostgresqlConnectionConfiguration.builder()
.port(5432) // Add your config here.
.codecRegistrar { _, allocator, registry ->
registry.addFirst(MoodCodec(allocator))
Mono.empty()
}.build()
.let { PostgresqlConnectionFactory(it) }
}
I used the below for Spring boot 2.6.4 + r2dbc-postgresql 0.8.11 by adding a customizer rather than creating the connection factory myself.
Thanks #Hantsy for pointing EnumCodec out. I added it to a customizer therefore it can play nicely with existing autoconfigure procedure. Also, the spring-data keeps converting my enum to string until I added the converter.
Hopefully these can provide a little help to others.
Register EnumCodec to builder customizer as extensions
It is possible to register multiple enum, just repeat the withEnum() call.
/**
* Use the customizer to add EnumCodec to R2DBC
*/
#Bean
public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryOptionsBuilderCustomizer() {
return builder -> {
builder.option(Option.valueOf("extensions"),
List.of(EnumCodec.builder()
.withEnum("enum_foo", FooEnum.class)
.withRegistrationPriority(RegistrationPriority.FIRST)
.build()));
logger.info("Adding enum to R2DBC postgresql extensions: {}", builder);
};
}
Implement spring data converter by extending EnumWriteSupport
public class FooWritingConverter extends EnumWriteSupport<Foo> {
}
Register converters so that spring data won't always convert enum to string.
This step is a slightly enhanced version of R2dbcDataAutoConfiguration in spring-boot-autoconfigure project.
/**
* Register converter to make sure Spring data treat enum correctly
*/
#Bean
public R2dbcCustomConversions r2dbcCustomConversions(DatabaseClient databaseClient) {
logger.info("Apply R2DBC custom conversions");
R2dbcDialect dialect = DialectResolver.getDialect(databaseClient.getConnectionFactory());
List<Object> converters = new ArrayList<>(dialect.getConverters());
converters.addAll(R2dbcCustomConversions.STORE_CONVERTERS);
return new R2dbcCustomConversions(
CustomConversions.StoreConversions.of(dialect.getSimpleTypeHolder(), converters),
List.of(
new FooWritingConverter()
));
}
Step 1 and 3 can be added to your application class or any other valid configuration.
Check my article about Postgres specific features supported in R2dbc.
There are two options.
use custom Postgres enum type and Java enum type, and register EnumCodec in the connection factory builder.
use a textual type as data type(such as varchar), and Java Enum type, Spring data r2dbc will convert them directly.

How to write C# implementation for a Q# operation with intrinsic body?

I have created a library in C# to be used in Q# programs. The library has two scripts, a C# class library called "Class1.cs" and a matching Q# script called "Util.qs", I share the code snippet of each here:
Class1.cs:
using System;
using Microsoft.Quantum.Simulation.Common;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace MyLibrary {
class Class1 : QuantumSimulator {
static void Method_1 (string str) { ... }
.
.
.
}
}
Util.qs:
namespace MyLibrary {
operation Op_1 (str : String) : Unit { body intrinsic; }
}
There is another Q# program in a different namespace that uses the namespace "MyLibrary" so after adding reference, in this Q# program I have:
namespace QSharp
{
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open MyLibrary;
operation TestMyLibrary() : Unit {
Op_1("some string");
}
}
When I execute "dotnet run" in the terminal I receive this message:
Unhandled Exception: System.AggregateException: One or more errors
occurred. (Cannot create an instance of MyLibrary.Op_1 because it is
an abstract class.) ---> System.MemberAccessException: Cannot create
an instance of MyLibrary.Op_1 because it is an abstract class.
How can I fix it?
Thanks.
UPDATE:
Following Mariia' answer and also checking Quantum.Kata.Utils, I changed my code as following:
So, I changed Class1 script to:
using System;
using Microsoft.Quantum.Simulation.Common;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace MyLibrary {
class Class1 : QuantumSimulator {
private string classString = "";
public Class1() { }
public class Op_1_Impl : Op_1{
string cl_1;
public Op_1_Impl (Class1 c) : base (c) {
cl_1 = c.classString;
}
public override Func<string, QVoid> Body => (__in) => {
return cl1;
};
}
}
Now the error messages are:
error CS0029: Cannot implicitly convert type 'string' to 'Microsoft.Quantum.Simulation.Core.QVoid'
error CS1662: Cannot convert lambda expression to intended delegate type because some of the return types
in the block are not implicitly convertible to the delegate return type
Having checked Quantum.Kata.Utils, I realised I need to create a field and a constructor for Class1 which is a base class and also I should override Func<string, QVoid> as the Op_1 parameter is string type. But I am not sure if each of these steps individually is done properly?
Second Update:
I have changed the previous c# code in first update to the following one:
using System;
using Microsoft.Quantum.Simulation.Common;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace MyLibrary {
class Class1 : QuantumSimulator {
public Class1() { }
public class Op_1_Impl : Op_1{
Class1 cl_1;
public Op_1_Impl (Class1 c) : base (c) {
cl_1 = c;
}
public override Func<string, QVoid> Body => (__in) => {
return QVoid.Instance;
};
}
}
Now the error message is the same as the very first one:
Unhandled Exception: System.AggregateException: One or more errors
occurred. (Cannot create an instance of MyLibrary.Op_1 because it is
an abstract class.) ---> System.MemberAccessException: Cannot create
an instance of MyLibrary.Op_1 because it is an abstract class.
And also in this new code shouldn't the constructor public Class1() { } have a parameter? if so what datatype?
In your code, there is nothing connecting the Q# operation Op_1 and the C# code that you intend to implement it in Method_1.
Q# operations are compiled into classes. To define a C# implementation for a Q# operation with the intrinsic body, you have to define a class that implements the abstract class into which your Q# operation gets compiled; so you would have something like public class Op_1_Impl : Op_1.
Getting all the piping right can be a bit tricky (it's a hack, after all!) I would recommend looking at the operation GetOracleCallsCount and its C# implementation to see the exact pieces that have to be in place for it to work.
For the updated question, the signature of your method says that it takes string as an input and returns nothing (QVoid), but the implementation tries to return a string cl_1, so you get a Cannot implicitly convert type 'string' to 'Microsoft.Quantum.Simulation.Core.QVoid'.
To provide a custom C# emulation for your Op_1 Q# operation, you'll need to replace your Class1.cs with something like this:
using System;
using Microsoft.Quantum.Simulation.Core;
namespace MyLibrary
{
public partial class Op_1
{
public class Native : Op_1
{
public Native(IOperationFactory m) : base(m) { }
public override Func<String, QVoid> Body => (str) =>
{
// put your implementation here.
Console.WriteLine(str);
return QVoid.Instance;
};
}
}
}
You can then run the Test1Library using the QuantumSimulator.
That being said, as Mariia said, this is kind of hacky, undocumented functionality that might change in the future, may I ask why you need this?

spring cloud stream kafka 2.0 - StreamListener with condition

I'm trying to create a consumer using StreamListener annotation and condition attirbute.However , i'm getting the following exception :
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Integer] for value 'test'; nested exception is java.lang.NumberFormatException: For input string: "test"
TestListener:
#StreamListener(target=ITestSink.CHANNEL_NAME,condition="payload['test'] == 'test'")
public void test(#Payload TestObj message) {
log.info("message is {}",message.getName());
}
TestObj:
#Data
#ToString(callSuper=true)
public class TestObj {
#JsonProperty("test")
private String test;
#JsonProperty("name")
private String name;
}
can someone assist with this issue?
the payload of the message is not yet converted from the wire format (byte[]) to the desired type. In other words, it has not yet gone through the type conversion process described in the Content Type Negotiation.
So, unless you use a SPeL expression that evaluates raw data (for example, the value of the first byte in the byte array), use message header-based expressions (such as condition = "headers['type']=='dog'").
Example:
#StreamListener(target = Sink.INPUT, condition = "headers['type']=='bogey'")
public void receiveBogey(#Payload BogeyPojo bogeyPojo) {
// handle the message
}
Check the Spring documentation here.
From what you show, it should work. I suggest you remove the condition, then set breakpoint to debug. Then you should be able to know which actual type is.

Is there a way to have a get only (no set) in a typescript interface?

I have a case where I want to have just a get in the interface, no set. Is there a way to do that?
If not, we can implement a set and throw an exception if it is called. But it's cleaner if we can have just a get.
At present I have:
export interface IElement {
type : TYPE;
}
export class Element implements IElement {
public get type () : TYPE {
return TYPE.UNDEFINED;
}
public set type (type : TYPE) {
this.type = type;
}
}
I would like to have my interface & class be:
export class Element implements IElement {
public get type () : TYPE {
return TYPE.UNDEFINED;
}
}
TypeScript interfaces cannot currently define a property as read-only. If it's important to prevent, you'll need to throw an exception/error at runtime to prevent sets within the setter for the property.
The compiler doesn't require that you implement the get and a set though. You can just implement the get for example. However, at runtime, it won't be caught.

Adding functionality to Grails restfulcontroller

I'm having a very simple restful controller, which looks like this:
class PersonController extends RestfulController<Person> {
static responseFormats = ['json', 'xml']
PersonController() {
super(Person)
}
}
However, now I want to add a search option to this. What is the Grails way of making this possible?
I thought of adding the following:
def search(Map params) {
println params
}
But that makes Grails (2.3) crash (| Error Fatal error during compilation org.apache.tools.ant.BuildException: Compilation Failed (Use --stacktrace to see the full trace)).
So what is the right way of adding this? I'm looking for some solution which I can call using http://localhost:8080/foo/person/search?q=erik
This is my UrlMappings:
static mappings = {
"/$controller/$action?/$id?(.${format})?"{
constraints {
// apply constraints here
}
}
"/rest/persons"(resources:'Person')
I've changed the above to:
def search() {
println params
}
And that doesn't give the compilation error anymore, but I still get this error:
TypeMismatchException occurred when processing request: [GET] /declaratie-web/rest/medicaties/search - parameters:
q: erik
Provided id of the wrong type for class nl.Person. Expected: class java.lang.Long, got class java.lang.String. Stacktrace follows:
org.hibernate.TypeMismatchException: Provided id of the wrong type for class nl.Person. Expected: class java.lang.Long, got class java.lang.String
I also found out that it doesn't matter how I call the controller:
http://localhost:8080/foo/person/search?q=erik
http://localhost:8080/foo/person/search222?q=erik
http://localhost:8080/foo/person/search39839329?q=erik
All fails with the above error, so it seems my method is ignored (maybe caused by my URLmapping?)
You really aren't being RESTful by doing that. q should just be a parameter for the index action. You can override that method to include your functionality.
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
def c = Person.createCriteria()
def results = c.list(params) {
//Your criteria here with params.q
}
respond results, model:[personCount: results.totalCount]
}
#james-kleeh solution is right, but you can do it more clean by override the listAllResources method which is called by index
#Override
protected List<Payment> listAllResources(Map params) {
Person.createCriteria().list(params) {
// Your criteria here with params.q
}
}