I have wsimport-ed Java classes with standard bean conventions:
public class Request {
protected String vin;
public String getVin() {
return vin;
}
public void setVin(String value) {
this.vin = value;
}
}
I expected to use this class in Kotlin using nice property syntax:
override fun search(request: Request): Response {
log.info("search(vin={})", request.vin);
...
but this code does not compile:
Error:(59, 64) Kotlin: Cannot access 'vin': it is 'protected/*protected and package*/' in 'SmvSearchRequest'
request.getVin() works, of course, but that doesn't look better than Java. Is there some way to treat those classes as property holders?
This was missing pre-M13, it is now fixed in M13, see Youtrack
Related
I'm trying to figure out what happens with internal classes when seen from Java's perspective.
Found this in the docs:
Members of internal classes go through name mangling, to make it harder to accidentally use them from Java and to allow overloading for members with the same signature that don’t see each other according to Kotlin rules
So I was very curious to see how it looks like in practice.
I created a simple Kotlin class:
internal class Foo(i : Int) {}
Built a project, unpacked the jar and used javap to have a look at the actual class... and it displayed a standard public class with the original name:
Compiled from "Foo.kt"
public final class Foo {
public Foo(int);
}
Am I missing something? or is it just the docs that are misleading?
Docs mention members of internal classes, but I tried that as well:
internal class Foo(someInt : Int) {
var someString : String
get() {
TODO()
}
set(value) {}
fun foo() { }
class Bar { }
}
And got the expected output:
Compiled from "Foo.kt"
public final class Foo {
public Foo(int);
public final java.lang.String getSomeString();
public final void setSomeString(java.lang.String);
public final void foo();
}
and:
Compiled from "Foo.kt"
public final class Foo$Bar {
public Foo$Bar();
}
I have a number of Java bean interfaces like this:
public interface Dog
{
String getName();
void setName( final String value );
}
I also auto-generate bean implementations like this:
public final class DogImpl implements Dog
{
public String getName()
{
return m_name;
}
public void setName( final String value )
{
m_value = value;
}
private volatile String m_value;
}
ObjectMapper works perfectly except when I start nesting these beans like this:
public interface Dog
{
String getName();
void setName( final String value );
Dog getParent();
void setParent( final Dog value );
}
I get this error:
abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
It's complaining because the bean definition is an interface and not the concrete type. My question is if there is a way for me to define the mapping of interface types to concrete types for the ObjectMapper via a module or something?
Specifically, I can get a Map< Class< ? >, Class< ? > > of api type to implementation concrete type, but have no idea how to "give this" to the ObjectMapper so it understands how to look up the concrete types from the api types so it can instantiate them. How do I accomplish this?
This can be done using a SimpleAbstractTypeResolver.
This link shows you how to add the mappings to the resolver: Jackson - How to specify a single implementation for interface-referenced deserialization?
And this is how you add the resolver to an ObjectMapper:
final SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();
for ( final Class< ? > api : apis )
{
resolver.addMapping( api, getConcreteImpl( api ) );
}
final SimpleModule module = new SimpleModule();
module.setAbstractTypes( resolver );
mapper.registerModule( module );
I have the following code:
Works around a limitation in Spring where #ConfigurationProperties classes need to follow the JavaBeans convention with mutable properties.
Instead of inject the mutable TokenConfigurationConfig we inject the interface.
public interface TokenAuthenticationConfig {
public fun apiKey() : String
}
#Component
#ConfigurationProperties(prefix = "service.api")
public open class TokenAuthenticationConfigImpl : TokenAuthenticationConfig
{
public var apiKey : String
constructor() {
this.apiKey = ""
}
override fun apiKey(): String
{
return this.apiKey
}
}
It works ok, but just wondering:
Is it possible in Kotlin to define an interface with an immutable property, that is implemented by class with a mutable property.
Uses of the interface would see the property as immutable, while users of the class would see it as mutable.
Yes, it definitely is possible to define such an interface and a class.
Any (publicly visible) property x in Kotlin means a pair of methods getX() and setX(..), generated by the compiler to satisfy the Java convention. That said, it is consistent that you can override getX in a class and add setX.
Here is an example:
interface SomethingImmutable {
val Somevar: String
}
class MyClass: SomethingImmutable {
override var Somevar: String = "Initial Value"
}
I am trying to find a way to have a factory class / method that would take in an object or some kind of identifier (string or type) then based off the input parameter determine which implementation of the interface to create and return.
how do I setup my factory method and register the dependency for the interface? following is what I have roughly.
public class ISampleFactory
{
public ISample GetSample(Type type)
{
// do something here to return an implementation of ISample
}
}
public class SampleA : ISample
{
public void DoSomething();
}
public class SampleB : ISample
{
public void DoSomething();
}
public interface ISample
{
void DoSomethin();
}
Have a look at ninject Contextual Bindings Documentation:
You can either use Named Bindings:
this.Bind<ISample>().To<SampleA>().Named("A");
this.Bind<ISample>().To<SampleB>().Named("B");
or a conditional binding with any of the already available extensions or write your own:
this.Bind<ISample>().To<SampleA>().When(...);
this.Bind<ISample>().To<SampleB>().When(...);
see https://github.com/ninject/ninject/wiki/Contextual-Binding
I am trying to bind a repository to property using Ninject but always get null reference of binding object. I will explain the problem using code below.
public interface IServiceRepository
{
User GetUser(string email);
IQueryable<Statistic> GetStatisticForCurrentMonth(string ip);
void InsertStatistic(ConversionModel conversionModel);
class ServiceRepository : IServiceRepository
{
//Implementation of the Interface
}
I am would like to bind the repository above to class below while the class is created. Unfortunately Repository object is always null. Maybe I have misunderstood how Ninject is working? How to solve the problem?
public class Converter
{
[Inject]
public static IServiceRepository Repository { get; set; }
private static Converter _converter;
public static Converter Instance
{
get { return _Converter ?? (_Converter = new Converter ());
}
}
Ninject activator code
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IServiceRepository>().ToMethod(context => Converter.Repository);
}
Update
I have tried to rewrite code like this
public class Converter
{
private readonly IServiceRepository _repository;
public Converter(IServiceRepository repository)
{
_repository = repository;
}
//skip code
}
The test...
[TestMethod]
public void ConverterInstanceCreated()
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
Assert.IsNotNull(kernel.Get<Converter>());
}
}
gives exception
Test method PC.Tests.NinjectTest.ConverterInstanceCreated threw exception:
Ninject.ActivationException: Error activating IServiceRepository
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IServiceRepository into parameter repository of constructor of type Converter
1) Request for Converter
I just lost, I am trying to understand how Ninject is working for about week without any success. In my case why this exception is thrown?
Also please someone post working example with one repository injection to singleton class.
Ninject does not inject statics. Change the coynverter to a non-static class and configure it as Singleton in ninject. Also use constructor injection and make the repo a private field.
Now you can inject the converter to the constructors where you need it.
Even though you are using Property injection and not Constructor injection I think it would still be
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
}
As ninject still just needs to know what concrete type to map to the Interface
I haven't tested this so apologies if it's wrong.