Code Monkey home page Code Monkey logo

Comments (7)

webermich avatar webermich commented on June 2, 2024

Hi Sean,

thanks for reporting your issue.
I think the easiest solution for your probem is to provide a custom IdGenerator - although you seem to have issues implementing it. I just do not understand, why this should not be possible in your scenario?
Can you send a simple test-example?

Here is how I would implement it:

If you have an @Id(collectible=true, value = CustomIdGenerator.class)) annotated field the implematation of Pojo.java could be as follows:

public class Pojo {
    @Id(collectible = true, value = CustomIdGenerator.class)
    CustomId id;
}

And the CustomIdGenerator Code looks like:

public class CustomIdGenerator implements IdGenerator<CustomId> {
    @Override
    public CustomId generate() {
        //whatever logic you ned to generate the customId
        return new CustomId();
    }
}

Would that work for you?

As an alternative you can simply skip the test by annotationg your Id-field as follows:
@Id(collectible = true, value = ObjectIdGenerator.class)

But if your id-field itself is not of type ObjectId this will throw exceptions when the ObjectIdGenerator tries to generate an Id and assigns that to the field.

I wonder why your code priviously worked?

Let me know, if I misunderstand your point.

Michael

from polymorphia.

webermich avatar webermich commented on June 2, 2024

Btw. I just recall your issue #6

In polymorphia 2.0.0 I changed the mechanism to resolve codecs.
Prior to polymorphia 2.0.0 the PojoCodecProvider was asked first for a codec to be found.
From polymorphia 2.0.0 onward the CodecRegistry chain will be asked for a codec. This implies, that if you register different codec providers with the CodecRegistry these will be asked in order of occurence.
This is only true for types of Class. All other types (probably more complex, e.g. GenericType) are handled directly form the PojoCodecProvider as otherwise the type information would be lost when resolving the codec.

The key take away for you is: You could move your Id.class back to your domain model package.

One more thing:
From reading through the issue #6 it seems that the id of your domain model is not actually created within the java applicaton but rather in the mongo database itself?! Is that really your intention?
If you just need to map a field of your pojo to the _id property in the database, I guess you should rather use the Annotation @CodecToBeUsed(IdCodec.class) and not use an @Id annotation at all.

from polymorphia.

webermich avatar webermich commented on June 2, 2024

Hi Sean,

please let me know, if the test https://github.com/axelspringer/polymorphia/blob/master/src/test/java/de/bild/codec/idexternal/ExternalIdCodecProviderTest.java solves your issue?

Explanation:
The Id-class ist a custom class with a singel String-property.
https://github.com/axelspringer/polymorphia/blob/master/src/test/java/de/bild/codec/idexternal/model/CustomId.java

A CustomIdGenerator is being used to generate an ObjectId and retrieve its String-representation to be set within CustomId.

Michael

from polymorphia.

clixtec avatar clixtec commented on June 2, 2024

Thanks for your work on this Michael. Unfortunately, the project in which the Pojo is located cannot reference any MongoDB or BSON things because of the GWT restriction. That means since the CustomIdGenerator would have to do something like new ObjectId() which is in the BSON library, we cannot place it in that project. In turn that means the annotation you suggested cannot be put on occurrences of our custom Id class.

You said "If you just need to map a field of your pojo to the _id property in the database, I guess you should rather use the Annotation @CodecToBeUsed(IdCodec.class) and not use an @id annotation at all." I don't quite understand that. Do you mean that my IdCodec class would then be responsible for putting out the _id name as well as the ObjectId value? That would not be suitable for my situation because we use the Id <-> ObjectId mapping for other fields, not just _id.

At present (with version 2.3.0) we have @id only on fields that are meant to be mapped to the document's "_id" field - all of those fields have our custom type Id. We also have many other fields of type Id with different names, that are translated to ObjectId values by our IdCodec. These are mainly used for "foreign key" reference fields. We have a DAO software layer that sets the object's main Id field (mapped to _id) to a String.valueOf(new ObjectId()), then as it is being saved the IdCodec translates that back to a real ObjectId.

This worked in 2.3.0 because the @id annotation did not require the field to be ObjectId, and the IdCodec took care of the translations.

Now I notice that the failing check can be avoided if the collectible flag in the @id annotation is false... what would be the impact of that?

Cheers,
Sean

from polymorphia.

webermich avatar webermich commented on June 2, 2024

Hi Sean,

I am not familiar with the GWT architecture, so its a bit hard for me to understand all implications.
You say, you cannot use any MongoDB or BSON things in your project? That implies you are not able to reference the CustomIdGenerator if it internally creates a new ObjectId?! Ok, I think I got this now.

What I wrote about the @CodecToBeUsed(IdCodec.class) was unfortunatly not feasable. You are absolutely right. The codec would need to write the "_id" field but this is not how the Codec works. So this won't help to fix your issue.

Let me explain the purpose of the @Id annotation.
First, if a field is annotation with @Id the following line makes sure the field is encoded to the MongoDB under property name "_id" -

public String getMappedFieldName() {

Second, if you want your application to generate an id for the pojo rather than the MongoDB itself generating the Id, you can set collectible=true and choose a strategy or generator to create application Ids
Class<? extends IdGenerator> value() default DefaultIdGenerator.class;

If you set collectible to false (what is the default), and a pojo with an empty (null) id will be written out to MongoDB, MongoDB will add a field "_id" for you. This field will always be an ObjectId. So you loose control, if you need a more specific _id (you could have a compound _id or use an integer as _id, whatever suits you. You could even choose to use a diffenrent type for the _id within a MongoDB collection for different entities.)
Additionally, if you use collectible=false, after having persisted your pojo to the database, the @Id annotated field will still be null (if it was null while encoding) as MongoDB (mybe I am wrong here) won't return the _id of the freshly created entitiy. So that means you do not have a reference (since your @Id annotated field is still null) to that pojo after you persisted it. In some situations you might not care, but sometimes, you need to have the correct reference to further use it.

Instead of using collectible=true, you can still generate your _id's within your application and I guess this is what you actually do in your project. Your IdCodec or your application code will assign an ObjectId to your pojos before encoding to the database. In that case, MongoDB won't overwrite it.

Conclusion:
I guess in your scenario it should be possible to simply use:

 @Id
 Id id;

Just check your application pojos id after you have inserted it into the database. If the _id in the database matches your pojos _id, all is good.

Hope this helps?

from polymorphia.

webermich avatar webermich commented on June 2, 2024

Sean,

can I close the ticket?
Michael

from polymorphia.

clixtec avatar clixtec commented on June 2, 2024

Hi Michael, sorry for the long delay. Thanks for the detailed explanation! I think we can make do with collectible = false because every domain object goes through a DAO on its way to the database, so we always can set its Id value (_id field).

Yes please close the ticket. :)

from polymorphia.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.