I've recently started expirementing with Kotlin and started a Spring Boot pet project using Kotlin.
I'm trying to integrate a custom User domain object to Spring Security and thus want to implement the UserDetails inteface.
Given my domain User object below:
import org.springframework.data.annotation.Id as DocumentId
import org.springframework.data.mongodb.core.mapping.Document
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.AuthorityUtils
import org.springframework.security.core.userdetails.UserDetails
#Document
data class User(#DocumentId val id: String? = null,
val username: String = "",
val password: String = "",
val email: String = "",
val name: String? = null,
val surname: String? = null) : UserDetails {
override fun isCredentialsNonExpired(): Boolean = true
override fun isAccountNonExpired(): Boolean = true
override fun isAccountNonLocked(): Boolean = true
override fun getAuthorities(): MutableCollection<out GrantedAuthority> = AuthorityUtils.createAuthorityList("USER")
override fun isEnabled(): Boolean = true
}
I get the following errors:
Accidental override: The following declarations have the same JVM
signature (getUsername()Ljava/lang/String;): public final fun < get-username>(): Kotlin.String, public abstract fun getUsername(): Kotlin.String!
Accidental override: The following declarations have the same JVM
signature (getPassword()Ljava/lang/String;): public final fun < get-password>(): Kotlin.String, public abstract fun getPassword(): Kotlin.String!
Since my User class already has a method getUsername(): Kotlin.String also implement the method getUsername(): Kotlin.String! ?
How am I supposed to resolve such an error, other than using the #JvmName on the property's getter and setter?
The problem here is that it's impossible for a property getter to override a function from a supertype, from Kotlin's point of view. To workaround it, you can prevent the compiler from generating getters by making your properties private and implement required methods from supertypes manually, for example:
data class User(
private val username: String = ""
...
): UserDetails {
override fun getUsername() = username
...
}
Related
There is nameof operator in C#, it allows to get property name at compile time:
var name = nameof(User.email);
Console.WriteLine(name);
//Prints: email
It is not possible to use reflection in flutter and I do not want to hardcode names of properties i.e. to be used for querying SQLite tables. Is there any workaround?
***Currently I'm using built_value library.
For the archives, I guess, this isn't possible as Dart doesn't store the names of variables after compiling, and as you mentioned, Flutter doesn't support reflection.
But you can still hardcode responsibly by grouping your properties as part of the object that they belong to, like with JSON:
class User {
final String email;
final String name;
const User({required this.email, required this.name});
Map toJson() => {
"email": email,
"name": name,
};
}
Instead of remembering to type out "email" and "name" whenever you use User, just call User.toJson(). Then, when you want to rename your variables, you can use your IDE's "rename all", or just skim over your User class to quickly change all of the names without missing any.
I'm currently monitoring the progress on the dart:mirrors package, which offers some neat reflective properties and methods, though, I hadn't found a simple way to just get the name of a symbol like nameof() does.
Example:
import 'dart:mirrors';
class User {
final String email;
final String name;
const User({required this.email, required this.name});
}
void main() {
reflectClass(User).declarations.forEach((key, value) {
print(value.simpleName);
});
}
Output:
Symbol("email")
Symbol("name")
Symbol("User")
These are of type Symbol.
More here: https://api.dart.dev/stable/2.4.0/dart-mirrors/dart-mirrors-library.html
So, until they develop a nameof, I've created an extension on symbol:
extension SymbolExtensions on Symbol {
String get nameof =>
RegExp(r'"(.*?)"').firstMatch(toString())!.group(1).toString();
}
So, you could do:
print(reflectClass(User)
.declarations[#email)]!
.simpleName
.nameof);
Output:
email
It's a start. Dart is still growing.
You can use code generation.
The basic idea is to create a nameof annotation class and mark parts of your code with it. You also need to create a code generator that handles your annotated code. Look at the json_serializable package for an example and create your own code generator.
If you do not want to create your own generator, use a ready-made package nameof: https://pub.dev/packages/nameof
Short how-to with this package.
Mark your class with nameof annotation.
#nameof
class Car {
final double price;
final double weigth;
final int year;
final String model;
Car(this.price, this.weigth, this.year, this.model);
Car.sedan(double price, double weigth, int year)
: this(price, weigth, year, 'Sedan');
}
Run the code generator.
flutter pub run build_runner build
Then use the generated class, which will look something like this.
/// Container for names of elements belonging to the [Car] class
abstract class NameofCar {
static const String className = 'Car';
static const String constructor = '';
static const String constructorSedan = 'sedan';
static const String fieldPrice = 'price';
static const String fieldWeigth = 'weigth';
static const String fieldYear = 'year';
static const String fieldModel = 'model';
}
You can implement your own nameOf function:
String? nameOf(dynamic o) {
if (o == null) return "null";
try {
if (o is List) {
var first = o.length > 0 ? o[0] : null;
if (first != null) {
var elementType = nameOf(first)!;
Log.debug("nameOf: List<$elementType>");
if (!isMinified(elementType))
return "List<$elementType>";
}
} else {
Function? getTypeName = o.getTypeName;
if (getTypeName != null) return getTypeName();
}
} catch (e) {
Log.debug("ignored nameOf error: $e, falling back to o.runtimeType: ${o.runtimeType}");
}
return o.runtimeType.toString();
}
bool isMinified(String type) => type.startsWith("minified:");
I'm currently trying to create a GlobalExtension for my Geb-Spock framework. So far here is my extension:
class OnFailureListener extends AbstractRunListener {
private final String id
private final SauceREST sauceREST
public OnFailureListener(String id, String username, String accessKey) {
this.id = id
this.sauceREST = new SauceREST(username, accessKey)
}
def void error(ErrorInfo error) {
println error;
this.sauceREST.updateJobInfo(this.sessionIdProvider.getSessionId(), "failed")
}
}
class ResultExtension extends AbstractGlobalExtension {
protected final String username = System.getenv("SAUCE_USERNAME")
protected final String accesskey = System.getenv("SAUCE_ACCESS_KEY")
protected final String sessionId
#Override
void visitSpec(SpecInfo specInfo) {
specInfo.addListener(new OnFailureListener(sessionId, username, accesskey))
}
}
My issue is that the sesssionId value gets assigned in the GebSpec base class I'm using for other specs, and cannot be assigned directly in the extension class. Beyond using some gnarly reflection approaches, is there a way to access the sessionId value assigned in the base class in the extension? I'd also like to avoid using an AnnotationExtension since I'd like to apply this globally without modifying any spec code (similar to a JUnit TestWatcher pattern).
The easiest way for you would be to write the sessionId into a shared ThreadLocal that can be accessed by your listener and the spec, otherwise you'll have to implement an org.spockframework.runtime.extension.IMethodInterceptor so that you can gain access to the actual test instance to extract the field value.
I was wondering how to accomplish an active record like (not with core data, but with rest, but this part I don't think will be an issue).
The issue its that don't understand well the reflection in swift, and my goal its to have a base class called Collection like (just prototype not really working code here):
public class Collection
{
public var Id: String
public static func Name () -> String
{
// accomplished but not with static method
}
public static func Find () -> [ChildClass] // the child class how can I obtain dynamically?
{
// restful things
return [ChildClass, ChildClass, ...] // rest result maped from json
}
public static func FindById (id : String) {}
// also Save && Delete methods
}
This kind of things I accomplish in c# with WSD-Data exactly in this class
So the usage maybe will:
public class User : Collection
{
public var FirstName: String
public var LastName: String
}
or c# like (dunno if this can be done in swift)
public class User : Collection<User> // we pass user as reference class c# like
{
public var FirstName: String
public var LastName: String
}
I hear also other alternatives to get this done, because don't know so well swift and the way that things are done with it.
I am porting some Java-code to Dart and it heavily uses these kinds of maps:
Map<Class<? extends SomeClass>, SomeOtherClass> map = new HashMap<>();
At the moment this seems to be impossible in dart. I am aware that there is a proposal to introduce first level types: http://news.dartlang.org/2012/06/proposal-for-first-class-types-in-dart.html which would introduce
class Type {
#native String toString();
String descriptor(){...} // return the simple name of the type
}
So until this proposal gets implemented I have created following class:
class Type {
final String classname;
const Type(this.classname);
String descriptor() => classname;
}
and the classes where I need it have a simple get-method
abstract Type get type();
That way I can use my Type just like I would use the real Type and to switch later I'd just have to delete my workaround.
My question: Is there some dart-way of doing this kind of mapping (which I am not seeing) or is the way I do it a reasonable workaround until the real Type class gets introduced?
Update for Dart 1.0
It can be done this way:
var map = new Map<Type, SomeOtherClass>();
// either
map[SomeOtherClass] = new SomeOtherClass();
// or
var instance = new SomeOtherClass();
map[instance.runtimeType] = instance;
Update: this construction is not currently doable in Dart
Map<Class<? extends SomeClass>, SomeOtherClass>
you will have to wait for .type/.class to arrive for an elegant solution to this (lots of us Dartisans are hoping that this will arrive sooner rather than later). However for the simpler case
Map<? extends SomeClass, SomeOtherClass>
You can just do
Map<SomeClass, SomeOtherClass> aMap;
as in Dart any class that extends SomeClass is also going to be a valid SomeClass. For example if you run the following code in checked mode:
main() {
Map<Test, String> aMap = new HashMap<Test, String>();
var test = new Test("hello");
var someTest = new SomeTest("world");
var notATest = new NotATest();
aMap[test] = test.msg;
aMap[someTest] = someTest.msg;
aMap[notATest] = "this fails";
}
class Test implements Hashable {
Test(this.msg);
int hashCode() => msg.hashCode();
final String msg;
}
class SomeTest extends Test {
SomeTest(String message): super(message);
}
class NotATest implements Hashable {
int hashCode() => 1;
}
then you you will get the error:
type 'NotATest' is not a subtype of type 'Test' of 'key'.
I'm new to Guice and here is a naive question. I learned that we could bind String to a particular value through:
bind(String.class)
.annotatedWith(Names.named("JDBC URL"))
.toInstance("jdbc:mysql://localhost/pizza");
But what if I want to bind String to any possible characters?
Or I think it could be described this way:
How can I replace "new SomeClass(String strParameter)" with Guice?
You first need to annotate the constructor for SomeClass:
class SomeClass {
#Inject
SomeClass(#Named("JDBC URL") String jdbcUrl) {
this.jdbcUrl = jdbcUrl;
}
}
I prefer to use custom annotations, like this:
class SomeClass {
#Inject
SomeClass(#JdbcUrl String jdbcUrl) {
this.jdbcUrl = jdbcUrl;
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.PARAMETER})
#BindingAnnotation
public #interface JdbcUrl {}
}
Then you need to provide a binding in your Module:
public class SomeModule extends AbstractModule {
private final String jdbcUrl; // set in constructor
protected void configure() {
bindConstant().annotatedWith(SomeClass.JdbcUrl.class).to(jdbcUrl);
}
}
Then an time Guice creates SomeClass, it will inject the parameter. For instance, if SomeOtherClass depends on SomeClass:
class SomeOtherClass {
#Inject
SomeOtherClass(SomeClass someClass) {
this.someClass = someClass;
}
Often, when you think you want to inject a String, you want to inject an object. For instance, if the String is a URL, I often inject a URI with a binding annotation.
This all assumes there is some constant value you can define at module creation time for the String. If the value isn't available at module creation time, you can use AssistedInject.
This might be off-topic, but Guice makes configuration much easier than writing an explicit binding for every String you need. You can just have a config file for them:
Properties configProps = Properties.load(getClass().getClassLoader().getResourceAsStream("myconfig.properties");
Names.bindProperties(binder(), configProps);
and voilĂ all your config is ready for injection:
#Provides // use this to have nice creation methods in modules
public Connection getDBConnection(#Named("dbConnection") String connectionStr,
#Named("dbUser") String user,
#Named("dbPw") String pw,) {
return DriverManager.getConnection(connectionStr, user, pw);
}
Now just create your Java properties file myconfig.properties at the root of your classpath with
dbConnection = jdbc:mysql://localhost/test
dbUser = username
dbPw = password
or merge authorization information from some other source into the properties and you're set.
I was able to inject a string through Named annotation.
#Provides
#Named("stage")
String stage() {
return domain;
}
class SomeClass {
#Inject
#Named("stage")
String stageName;
}
I find a solution in the FAQ of Guice:
http://code.google.com/docreader/#p=google-guice&s=google-guice&t=FrequentlyAskedQuestions
In addition to define an annotation and a String attribute in MyModule, I need to write below line to get a instance of SomeClass:
SomeClass instance = Guice.createInjector(new MyModule("any string i like to use")).getInstance(SomeClass.class);
But I remembered that Injector.getInstance() should not be used except for the root object, so is there any better way to do this?