I'm using kotlin to store in a database a class from a library. The problem is that this class, haven't got a constructor with no arguments(It is a Java class). When I retrieve the object from the database, I get the following error, as It has no constructor:
java.lang.NoSuchMethodException: org.springframework.security.oauth2.core.OAuth2AccessToken.<init>()
The only solutions I think It will solve the problem, are the following:
Change the class where I retrieve the object to Java.
Store a different object instead of org.springframework.security.oauth2.core.OAuth2AccessToken class
Any more thoughts on how to solve this problem?
This is my class in the database:
#Document(collection = "authorizedClient")
data class AuthorizedClientDatabase(
#Id
var id: ObjectId = ObjectId.get(),
var name: String? = null,
var clientRegistration: ClientRegistration,
var accessToken: OAuth2AccessToken,
var refreshToken: OAuth2RefreshToken? = null
)
This is the repository class:
#Repository
interface AuthorizedClientDatabaseRepository : MongoRepository<AuthorizedClientDatabase, ObjectId> {
}
This is the OAuth2AccessToken
And I'm simply making a:
authorizedClientDatabaseRepository.findById(...)
OAuth2AccessToken class does not have a non-argument constructor that you are attempting to call. You need to change your code to use one of the two existing constructors:
public OAuth2AccessToken(TokenType tokenType, String tokenValue,
Instant issuedAt, Instant expiresAt) {
// ...
}
or
public OAuth2AccessToken(TokenType tokenType, String tokenValue,
Instant issuedAt, Instant expiresAt, Set<String> scopes) {
// ...
}
I finally changed the OAuth2AccessToken class and created a custom one:
data class DatabaseOauth2AccessToken(
val tokenValue: String,
val issuedAt: Instant?,
val expiredAt: Instant?,
val scopes: MutableSet<String>
)
AFAIK, this is the most viable solution I have found.
In addition to Karol Dowbecki's answer; if you don't specify a constructor either way all classes provide you with an empty constructor (no params) and no body in it.
Your problem could be one of these:
The empty constructor is private hence not visible to the bit of code that is trying to create an instance
It just has not an empty constructor. There are already other constructors but no "empty" constructor specified. This could be what Karol Dowbecki mentions
It is specified but is private hence we're back to point 1.
A data class should have no effect on this. Data classes just take care of wrapping properties with a backing field and providing you with getters and setters Thanks Alexey for correcting. Kotlin does that with all properties. Besides that, they write the implementation of the toString, equals and hashCode methods and adds a nice method to generate copies of the same object called copy
Related
I have a service call that returns a JSON response which is then passed through a data manager that transforms the data if service is success or creates an error body if the call is a failure.
The data manager is written in kotlin and the particular line of
code i am interested in is this
val mutableList = mutableListOf<Address>()
return Result.error(errorTransformation(serviceErrors, mutableList))
My errorTransformation class is basically an Exception call and this is written java. The constructor for the exception class is
ExceptionClass(ServiceErrors serviceError ,List<Address> address){
// initiialize fields here
}
Now When i try to initialize my exception class it says appropriate constructor is found and it is showing me a suggestion to generate one with syntax
ExceptionClass(ServiceErrors serviceError ,List<? extends Address> address){
// initiialize fields here
}
Why is this happening? I only want List<Address>, not List<? extends Address>.
It's kotlin specific behavior to implicitly use List<? extends Address> instead of List<Address>. You can force kotlin generate exactly what you need using #JvmSuppressWildcards annotation
val mutableList = mutableListOf<#JvmSuppressWildcards Address>()
Suppose I have a base class (which i'm simplifying):
public class GenericException extends Exception {
private Map<String,Object> map;
//...
public GenericException(String message, String[] params, Object... values) {
super(message);
map = createMap(params, values);
}
//... other stuff
public String getType() {
getClass().getName();
}
}
This class may be extended by clients but there is no point in adding members to any of its sub-classes, because the class and its sub-classes, when thrown, will result in some Json streamed to some client, containing only the map, the type, and the message
A typical sub-class may be something like
public class Exception1 extends GenericException {
private String message = "something";
private String params = new String[] {"foo", "bar"};
//...
public Exception1(Object... values) {
super(message, params, values);
}
//... other stuff
}
At some other point in the code there is a need to take the Json representation of any GenericException (or its sub-class) and create an instance of that class. The type attribute may be used to figure out which class needs to be instantiated, and the map is in the Json representation so the params and values can be obtained.
If every sub-class could be forced to implement a constructor having the parameters
String message, String[] params, Object... values
then it would be easy.
But every sub-classs, although eventually it must call the constructor in GenericException, may have various unknown constructors.
I'm looking for some magic that would allow me to inject such a [virtual] constructor into every sub-class of GenericException,
so that the code that needs to create the exeption from Json
can call this "virtual" constructor perhaps by reflection...
Is it possible to create this magic by somehow annotating the class and doing some Spring Aspect annotation? (Spring is used in this project))
Or is there some other way to do it?
Additional information added 10/16/2018
Thanks to all the commenters. I guess I need to add more information:
1) I'm using Spring Boot
2) i don't want to add setters. I think exceptions should be immutable. Let's not argue about that.
3) sure there could be directive that you must implement some additional constructor in every extension of the base class. But i prefer not to do that.
4) I know I need to use AspectJ. But how is that done?
So think about it this way: people are writing sub-classes of GenericExceptions and i don't have any control over their code. I own GenericException and i am responsibile for some infrastructure code which is supposed to reconstruct any sub-class of GenericExceptions which is in the classpath but does not have any setters.
Problem Statement
I want to enforce such a situation that whenever the instance of the immutable pojo is to created all the mandatory variables must be passed in as parameters.
Let's Suppose I have Pojo like this
public class pojo {
private final String str;
private int number;
}
Now, As I said the pojo is immutable, I am using Lombok's Builder and Getter annotation.
Something Like,
#Getter
#Builder
public class pojo {
private final String str;
private int number;
}
Now, In this pojo the variable str is mandatory, and any instance of class pojo without a valid value of str is of no requirement.
Now, Object of class Pojo can be constructed using Builder in such a way
pojo obj = pojo.builder().build();
But the field str is mandatory and the above statement will create an object with str = null and number = 0. Now i can make use of #NonNull over
str to ensure that Object creation throws a Null pointer Exception at runtime if someone tries to build the object of pojo without specifying str.
But I want to enforce this check at compile time, Is there a way to stop object creation if str is not given as paramter?
You can do this if you write your Builder by hand. Have your builder() factory method return a class like UnreadyBuilder which doesn't have a build() method. Then the setName() setter (or whatever it's called) on UnreadyBuilder can return a ReadyBuilder object which does have a build() method.
That said: do you really need this to be checked at compile time? It's a lot of extra code for a pretty marginal benefit.
I have following classes
class A {
private Long id
private List<B> listB;
private C c;
...
}
class B {
private Long id
private A a;
private List<D> listD;
...
}
class C {
private Long id
private A a;
...
}
class D {
private Long id
private B b;
...
}
I need a copy of A, include all of it's properties except all id column.
I have 2 solutions:
1. Clone each object and set all of the ids null;
2. Make a constructor like this:
public A (A a){
//copy all properties except id
this.xxx = a.xxx;
...
}
But i need write so much code for this function, any one has some better method to implement this function?
Thanks a lot.
When you are saying Deep cloning of the object particularly the one of type Class A where you have an instance variable of a container type, you have below two widely known ways:
1) You Serialize and Deserialize the object.
2) You traverse through each method and call clone explicitely.
For first implementation, you may mark the id fields as transient and that should solve your purpose.
For second approach, you may override the clone method in each class where you set the id field as 0/-1) and call super.clone()
You can use Mapstruct , it's a powerful mapping library where you can configure all the fields exclusions for your specific class or nested class, without having to write all the getters/setters manually.
I personally use it for deep cloning jpa entities excluding ids or auditable fields.
Ex:
#Mapping(target="id",ignore=true")
EntityA cloneEntityAWithoutId(EntityA origin);
Mapstruct will generate for you the implementations using getters and setters of the EntityA, excluding the id field.
Obviously is a lot configurable, see the documentation I shared above.
I've got a Kotlin class, similar to
data open class MyDto (
var property: String? = null
// ...
)
and a Java class extending this class, similar to
class MySpecificDto extends MyDto {
private String field;
// getter/setter for "field"
public MySpecificDto(final MyDto prototype)
{
super(prototype);
}
}
What is missing in Kotlin's DTO for the "super(prototype)" statement to compile?
MyDto's constructor takes a single parameter of type String, and you are trying to pass it a MyDto.
I think you are looking for --
super(prototype.getProperty());
Data classes seem a like logical base for a hierarchy of DTOs. Unfortunately, they do not play well with inheritance, so doing so is not a good idea. See this answer.
Update to address comment --
For a Kotlin side solution, you need to remember Kotlin classes only allow for a single constructor. For data classes, the format of that constructor is already defined, so you cannot just pass an object and have it work, or define a different constructor. Also, as noted by #bashor in comment to your original question, there is no copy constructor. You can, however, create a separate function to initialize your object if you want --
data open class MyDto (var property: String? = null //...) {
fun init(dto: MyDto) {
property = dto.property
//... rest of the properties
}
}
and the in your Java constructor call init instead of super.
public class MySpecificDto extends MyDto {
private String field;
public MySpecificDto(final MyDto prototype)
{
init(prototype);
}
}
The caveat on this solution is that your data class must provide default values for all of its properties because there is an implicit call to the constructor with zero parameters.