Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception while extracting child ValueObject (stored as Map value) #247

Closed
floresek opened this issue Nov 10, 2015 · 7 comments
Closed

Exception while extracting child ValueObject (stored as Map value) #247

floresek opened this issue Nov 10, 2015 · 7 comments

Comments

@floresek
Copy link

Hi,

I have classes:

class Master {
    @Id
    String id;

    Map<String, Detail> details = new HashMap();

    public Master(String id) {
        this.id = id;
    }
}

@ValueObject
class Detail {
    String data;

    public Detail(String data) {
        this.data = data;
    }
}

and test code:

        Master master = new Master("1");
        master.details.put("key1", new Detail("detail-1"));
        master.details.put("key2", new Detail("detail-2"));
        javers.commit("anonymous", master);

Data are successfully committed to repository, but
while I read changes:

        List<Change> changes = javers
                .findChanges(QueryBuilder.byValueObjectId("1", Master.class, "detail")
                        .withNewObjectChanges(true)
                        .build());

I got an exception:

JaversException: CANT_EXTRACT_CHILD_VALUE_OBJECT JaVers runtime error - error while extracting child ValueObject from 'dto.Master.details', invalid property type, expected ValueObjectType or ContainerType<ValueObjectType>, got 'MapType{baseType:'java.util.Map<java.lang.String, dto.Detail>'}'
    at org.javers.core.metamodel.type.TypeMapper.getChildValueObject(TypeMapper.java:183)
    at org.javers.repository.jql.ValueObjectIdDTO.create(ValueObjectIdDTO.java:34)
    at org.javers.repository.jql.ValueObjectIdDTO.create(ValueObjectIdDTO.java:14)
    at org.javers.core.metamodel.object.GlobalIdFactory.createFromDto(GlobalIdFactory.java:77)
    at org.javers.repository.jql.QueryRunner.fromDto(QueryRunner.java:106)
    at org.javers.repository.jql.QueryRunner.queryForChanges(QueryRunner.java:74)
    at org.javers.core.JaversCore.findChanges(JaversCore.java:114)

Are you planning to add ValueObject as map value support?
It is very useful if you want to attach VO data to specific keys (identifying what has been changed).

Cheers
Mariusz

@bartoszwalacik
Copy link
Member

it is supported, you need to add map key to path attribute in ValueObjectId,
use / as a separator

byValueObjectId("1", Master.class, "detail/key1")

I need to add docs for that ...

@bartoszwalacik
Copy link
Member

@floresek
Copy link
Author

I wrote following test:

package test

import org.javers.core.JaversBuilder
import org.javers.repository.jql.QueryBuilder
import org.junit.Test

import javax.persistence.Id

class JaversTest {

    @Test
    void testMap() {
        def javers = JaversBuilder.javers().build()
        def obj = new Employee(
                name: '1',
                addressMap: [home:new Address(
                        city: 'city1'
                )]
        )

        javers.commit('test', obj)

        javers.findChanges(QueryBuilder.byValueObjectId(obj.name, Employee.class, "addressMap/home")
                .build());
    }

}

class Employee {
    @Id String name;
    Map<String,Address> addressMap;
}

class Address {
    String city;
}

and it fails :(:

DEBUG JaversBuilder - starting up JaVers ...
INFO  PropertyScannerModule - using FIELD mappingStyle
INFO  JaversBuilder - using fake InMemoryRepository, register actual implementation via JaversBuilder.registerJaversRepository()
INFO  JaversBuilder - JaVers instance is up & ready
INFO  TypeFactory - javersType of class test.Employee inferred as EntityType
INFO  TypeFactory - javersType of [class java.lang.String] inferred as ValueType, it's used as id-property type
INFO  TypeFactory - javersType of java.util.Map<java.lang.String, test.Address> inferred as MapType from prototype MapType{baseType:'interface java.util.Map'}
INFO  TypeFactory - javersType of class test.Address inferred as ValueObjectType
DEBUG ObjectGraphBuilder - live graph assembled, object nodes: 2, entities: 1, valueObjects: 1
DEBUG InMemoryRepository - 2 snapshot(s) persisted
INFO  Javers - Commit(id:1.0, snapshots:2, author:test, changes - NewObject:2)

JaversException: CANT_EXTRACT_CHILD_VALUE_OBJECT JaVers runtime error - error while extracting child ValueObject from 'test.Employee.addressMap', invalid property type, expected ValueObjectType or ContainerType<ValueObjectType>, got 'MapType{baseType:'java.util.Map<java.lang.String, test.Address>'}'
    at org.javers.core.metamodel.type.TypeMapper.getChildValueObject(TypeMapper.java:170)
    at org.javers.repository.jql.ValueObjectIdDTO.create(ValueObjectIdDTO.java:34)
    at org.javers.repository.jql.ValueObjectIdDTO.create(ValueObjectIdDTO.java:14)
    at org.javers.core.metamodel.object.GlobalIdFactory.createFromDto(GlobalIdFactory.java:72)
    at org.javers.repository.jql.QueryRunner.fromDto(QueryRunner.java:103)
    at org.javers.repository.jql.QueryRunner.queryForChanges(QueryRunner.java:73)
    at org.javers.core.JaversCore.findChanges(JaversCore.java:115)
    at org.javers.core.Javers$findChanges$0.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at test.JaversTest.testMap(JaversTest.groovy:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

I use 1.3.20 javers version

@bartoszwalacik
Copy link
Member

right, sth is wrong here

@bartoszwalacik
Copy link
Member

fix is done in v 1.3.21, tomorrow morning it will be released to Central

@bartoszwalacik
Copy link
Member

@floresek
Copy link
Author

Excellent, thx ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants