I am trying to execute a transaction on a Redis instance from within Spring Boot application written in Kotlin. I have followed the recommendation in Spring Doc on the best practice to achieve this.
I am struggling with the Kotlin implementation, however. Specifically, I don't know how to implement the Java generic interface with a generic method to make it work in the Kotlin code:
redisTemplate.execute(object : SessionCallback<List<String>> {
override fun <K : Any?, V : Any?> execute(operations: RedisOperations<K, V>): List<String>? {
operations.multi()
operations.opsForValue().set("key", "value")
return operations.exec()
}
})
The code above complains that the set method expects parameters with types K and V respectively but String is found instead.
Is there an elegant way how to inline the interface implementation in Kotlin without having to use unchecked casting or other convoluted approaches to make this work?
I think you're facing this problem due to poor interface definition for SessionCallback and the framework itself is doing unsafe casts themselves.
You see, if we take a look into the SessionCallback definition over here we can see that it looks as follows:
public interface SessionCallback<T> {
#Nullable
<K,V> T execute(RedisOperations<K,V> operations) throws DataAccessException
}
The generics K,V referring to the type of keys and values from your Redis are not parameters of the SessionCallback interface and that's why the kotlin compiler is having a hard time inferring the type of these: Because the execute function only takes a parameter of type SessionCallback<T> without passing the types of keys and values as parameters to that interface.
Your best-effort might be to provide a nice wrapper around that API using extension functions and inline generic types by doing some controlled unsafe casts.
Something like this might be enough:
inline fun <reified K : Any?, reified V: Any?, reified T> RedisTemplate<K, V>.execute(crossinline callback: (RedisOperations<K,V>) -> T?): T?{
val callback = object : SessionCallback<T> {
override fun <KK, VV> execute(operations: RedisOperations<KK,VV>) = callback(operations as RedisOperations<K, V>) as T?
}
return execute(callback)
}
Which then you can consume by doing:
fun doSomething(redisTemplate: RedisTemplate<String, String>) {
redisTemplate.execute { operations ->
operations.multi()
operations.opsForValue().set("key", "value")
operations.exec() as List<String>
}
}
And yes, you need to cast the .exec() result because nobody bothered using generics and returns a List<Object> as you can see on the official documentation
Related
I've created a function which is polymorphic in the Monad it needs to use, instead it depends on the typeclass instances that exists for this Monad. It looks like this:
fun <M> M.logic(...): Kind<M, String>
where M: MonadReader<M, Dependency>,
M: Effect<M> =
fx.monad() {
val dependency = ask().bind()
val response = effect { ...using dependency here... }.bind()
response
}
I'm using the MonadReader to get a dependency, and I'm using Effect, well, for effects. Now I assumed, that all I need is to use some Monad Transformers to get to this constellation of a Monad "at the end of the world" (i.e. in main()). Something like ReaderT<ForIO, Dependency, Unit>.
However, I can't seem to create a suitable M (or any context) to call this method on. How can I call this method on an exact monad that has the necessary typeclass instances?
This is the code snippet you're after:
fun <M, F> M.logic(): Kind<F, String>
where M: MonadReader<F, String>,
M: Async<F> =
fx.monad {
val dependency = ask().bind()
val response = effect { dependency }.bind()
response
}
object Transformer:
Async<KleisliPartialOf<ForIO, String>> by ReaderT.async(IO.effect()),
KleisliMonadReader<ForIO, String> by ReaderT.monadReader(IO.monad())
Note that Async is what you're after, not the poorly named Effect. And you need two generics, one for the composition and another for the content.
Transformer.run {
logic()
}
The Async instance for Reader was added on January 2020, and will be available on the next release, either 0.10.5 or 0.11.0: https://github.com/arrow-kt/arrow/commit/6aaae6998de612eb0eec948697f1c477649230be
I am still learning the Go way of doing things, coming from a C++ background. I am looking for feedback contrasting OOP inheritance to interface composition.
I have a design situation in a Go program where, if I was implementing in C++, I would solve with an abstract base class.
Suppose I need a base class, which has many implementors. The base class has shared methods that do work on abstract data items. Different Worker implementations provide CRUD operations on different item types, but workers all use the shared methods of the base class for general work.
In C++ I might do it this way
class IItem
{
// virtual methods
};
class IWorker
{
public:
// one of many virtual functions that deal with IItem CRUD
virtual IItem* createItem() = 0;
// concrete method that works on interfaces
void doWork()
{
IItem* item = createItem();
// do stuff with an IItem*
}
};
class Toy : public IItem
{
};
// one of many kinds of workers
class ElfWorker : public IWorker
{
public:
ElfWorker()
{
// constructor implicitly calls IWorker()
}
IItem* createItem() override
{
return new Toy;
}
};
In Go you don't have abstract virtual methods such as IWorker::createItem(). Concrete classes need to supply the base with an interface or function that do the right thing.
So I think it is the case that the Go code the ew.ItemCRUD interface has to be explicitly set with a pointer to an ElfWorker.
The elf knows how to createItem(), which in his case happens to be Toy object. Other workers would implement their own ItemCRUD for their data objects.
type Item interface {
// various methods
}
type ItemCRUD interface {
create() Item
// other CRUD
}
type Worker struct {
ItemCRUD // embedded interface
}
func (w *Worker) doWork() {
item := w.create()
// do stuff with item
}
type Toy struct {
}
type ElfWorker struct {
Worker // embedded
// ..
}
func NewElfWorker() *ElfWorker {
ew := &ElfWorker{}
ew.ItemCRUD = ew // <-- #### set Worker ItemCRUD explicitly ####
return ew
}
func (ew *ElfWorker) createItem() Item {
return &Toy{}
}
// more ElfWorker Item CRUD
func bigFunction(w *Worker) {
// ...
w.doWork()
// ..
}
So the part that I am wrestling a bit with is explicit setting. Seems like the "Go way" of composition does require this explicit step if I want the base Worker class to provide shared methods on Items.
Thoughts?
Beeing new to go myself, this answer is not backed by years of go experience :-)
I don't know, if the way you tackle this is the correct approach.
go allows interfaces to be implemented without explicit declaration. If you have elves, and you need them to do ItemCRUD methods, just implement them.
The method set will then match the interface and you can use the elf as a ItemCRUD where required.
To supply any elf object with a default ItemCRUD Implementation, you should implement an adapter for the ItemCRUD and compose the adapter with your abstract elf. The abstract methods could have a default implementation as log.Fatal("not implemented")
The concrete elves shadow the adapter's methods, this answers your question: It is not required to insert the object during creation.
Yet, since go has no generics, it may not be the right approach to have an ItemCRUD.
Im not entirely clear what the plan is with the above code and without understanding that its hard to suggest specific solutions, what is clear is you are very much coming to the party with an established OOP mindset (I did too) which is rarely helpful in finding the best solution in golang.
In Golang I wouldnt usually embed an interface in an implementation, interfaces are satisfied implicitly in Golang which allows for a nice separation of expectation and implementation which should generally be respected.
A reciever method should expect an interface, the implementation passed at runtime should just satisfy the signature of that interface implicitly.
So perhaps my doWork method needs to be able to createItems then it would be the doWork method that would accept any implementation of ItemCRUD which it could call to create an item. But this is me guessing at what you really want to do here, I suspect if you just separate implementation from interface you will probably answer your own question.
I'd like to change the representation of C# Doubles to rounded Int64 with a four decimal place shift in the serialization C# Driver's stack for MongoDB. In other words, store (Double)29.99 as (Int64)299900
I'd like this to be transparent to my app. I've had a look at custom serializers but I don't want to override everything and then switch on the Type with fallback to the default, as that's a bit messy.
I can see that RegisterSerializer() won't let me add one for an existing type, and that BsonDefaultSerializationProvider has a static list of primitive serializers and it's marked as internal with private members so I can't easily subclass.
I can also see that it's possible to RepresentAs Int64 for Doubles, but this is a cast not a conversion. I need essentially a cast AND a conversion in both serialization directions.
I wish I could just give the default serializer a custom serializer to override one of it's own, but that would mean a dirty hack.
Am I missing a really easy way?
You can definitely do this, you just have to get the timing right. When the driver starts up there are no serializers registered. When it needs a serializer, it looks it up in the dictionary where it keeps track of the serializers it knows about (i.e. the ones that have been registered). Only it it can't find one in the dictionary does it start figuring out where to get one (including calling the serialization providers) and if it finds one it registers it.
The limitation in RegisterSerializer is there so that you can't replace an existing serializer that has already been used. But that doesn't mean you can't register your own if you do it early enough.
However, keep in mind that registering a serializer is a global operation, so if you register a custom serializer for double it will be used for all doubles, which could lead to unexpected results!
Anyway, you could write the custom serializer something like this:
public class CustomDoubleSerializer : BsonBaseSerializer
{
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
var rep = bsonReader.ReadInt64();
return rep / 100.0;
}
public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
var rep = (long)((double)value * 100);
bsonWriter.WriteInt64(rep);
}
}
And register it like this:
BsonSerializer.RegisterSerializer(typeof(double), new CustomDoubleSerializer());
You could test it using the following class:
public class C
{
public int Id;
public double X;
}
and this code:
BsonSerializer.RegisterSerializer(typeof(double), new CustomDoubleSerializer());
var c = new C { Id = 1, X = 29.99 };
var json = c.ToJson();
Console.WriteLine(json);
var r = BsonSerializer.Deserialize<C>(json);
Console.WriteLine(r.X);
You can also use your own serialization provider to tell Mongo which serializer to use for certain types, which I ended up doing to mitigate some of the timing issues mentioned when trying to override existing serializers. Here's an example of a serialisation provider that overrides how to serialize decimals:
public class CustomSerializationProvider : IBsonSerializationProvider
{
public IBsonSerializer GetSerializer(Type type)
{
if (type == typeof(decimal)) return new DecimalSerializer(BsonType.Decimal128);
return null; // falls back to Mongo defaults
}
}
If you return null from your custom serialization provider, it will fall back to using Mongo's default serialization provider.
Once you've written your provider, you just need to register it:
BsonSerializer.RegisterSerializationProvider(new CustomSerializationProvider());
I looked through the latest iteration of the driver's code and checked if there's some sort of backdoor to set custom serializers. I am afraid there's none; you should open an issue in the project's bug tracker if you think this needs to be looked at for future iterations of the driver (https://jira.mongodb.org/).
Personally, I'd open a ticket -- and if a quick workaround is necessary or required, I'd subclass DoubleSerializer, implement the new behavior, and then use Reflection to inject it into either MongoDB.Bson.Serialization.Serializers.DoubleSerializer.__instance or MongoDB.Bson.Serialization.BsonDefaultSerializationProvider.__serializers.
I've just modified a method for handling my DDD commands (previously it had no return type):
public static CommandResult<TReturn> Execute<TCommand, TReturn>(TCommand command)
where TCommand : IDomainCommand
{
var handler = IoCFactory.GetInstance<ICommandHandler<TCommand, TReturn>>();
return handler.Handle(command);
}
The method is fine, and does what I want it to do, however using it creates some fugly code:
CommandResult<Customer> result =
DomainCommands.Execute<CustomerCreateCommand, Customer>
(
new CustomerCreateCommand(message)
);
Before I added the Customer return type TReturn, it was nice and tidy and the method could infer the types from its usage. However that's no longer possible.
Is there any way using any new C# features that I could rewrite the above to make it tidier, i.e. using Func, Action, Expression, etc? I'm probably expecting the impossible, but I'm getting fed up of writing so much code to just call a single method that used to be very simple.
One option to reduce it slightly is to have a static generic type for the type parameter that can't be inferred, allowing you to have a generic method with just one type parameter that can be inferred:
public static class DomainCommands<TReturn>
{
public static CommandResult<TReturn> Execute<TCommand>(TCommand command)
where TCommand : IDomainCommand
{
var handler = IoCFactory.GetInstance<ICommandHandler<TCommand, TReturn>>();
return handler.Handle(command);
}
}
Then:
var result = DomainCommands<Customer>.Execute(new CustomerCreateCommand(msg));
It's not much nicer, but it's slightly better. Of course, if the domain command type itself could be generic, that might help - so CustomerCreateCommand would implement IDomainCommand<Customer> for example. If you still needed a nongeneric IDomainCommand, you could make IDomainCommand<T> derive from IDomainCommand.
I'm using Ninject 1.0 and would like to be able to inject lazy initialisation delegates into constructors. So, given the generic delegate definition:
public delegate T LazyGet<T>();
I'd simply like to bind this to IKernel.Get() so that I can pass a lazy getter into constructors, e.g.
public class Foo
{
readonly LazyGet<Bar> getBar;
public Foo( LazyGet<Bar> getBar )
{
this.getBar = getBar;
}
}
However, I can't simply call Bind<LazyGet<T>>() because it's an open generic type. I need this to be an open generic so that I don't have to Bind all the different lazy gets to explicit types. In the above example, it should be possible to create a generic delegate dynamically that invokes IKernel.Get<T>().
How can this be achieved with Ninject 1.0?
Don't exactly understand the question, but could you use reflection? Something like:
// the type of T you want to use
Type bindType;
// the kernel you want to use
IKernel k;
// note - not compile tested
MethodInfo openGet = typeof(IKernel).GetMethod("Get`1");
MethodInfo constGet = openGet.MakeGenericMethod(bindType);
Type delegateType = typeof(LazyGet<>).MakeGenericType(bindType);
Delegate lazyGet = Delegate.CreateDelegate(delegateType, k, constGet);
Would using lazyGet allow you to do what you want? Note that you may have to call the Foo class by reflection as well, if bindType isn't known in the compile context.
I am fairly certain that the only way to do this (without some dirty reflection code) is to bind your delegate with type params. This will mean it needs to be done for each individual type you use. You could possibly use a BindingGenerator to do this in bulk, but it could get a bit ugly.
If there is a better solution (a clean one) I would love to hear it as I run into this problem from time to time.
From another similar question I answered:
public class Module : NinjectModule
{
public override void Load()
{
Bind(typeof(Lazy<>)).ToMethod(ctx =>
GetType()
.GetMethod("GetLazyProvider", BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(ctx.GenericArguments[0])
.Invoke(this, new object[] { ctx.Kernel }));
}
protected Lazy<T> GetLazyProvider<T>(IKernel kernel)
{
return new Lazy<T>(() => kernel.Get<T>());
}
}