remondis-it / remap Goto Github PK
View Code? Open in Web Editor NEWA declarative mapping library to simplify testable object mappings.
License: Apache License 2.0
A declarative mapping library to simplify testable object mappings.
License: Apache License 2.0
Hello
I'm facing this error : ClassNotFoundException: org.objectweb.asm.Type
Need libraries update ?
List of possible API Improvements. They are collected in this Issue, because they are breaking changes and should be implemented together in a single release.
com.remondis.remap.ReplaceCollectionAssertBuilder.andTest(Transform<RS, RD>)
and com.remondis.remap.ReplaceAssertBuilder.andTest(Transform<RS, RD>)
should be renamed so that the method name indicates that the test is performed againstnull
input.The following example shows that private getter methods in static classes are not proxied by the InvocationSensor
. The call on the proxy object calls the real method:
import org.junit.Test;
import com.remondis.remap.Mapper;
import com.remondis.remap.Mapping;
public class StaticClassMapperTest {
public static class A {
public A() {
super();
}
private String getMessage() {
throw new RuntimeException("Original method was called.");
}
}
public static class B {
private String message;
public B() {
super();
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
@Test
public void multiMapping() {
Mapper<A, B> mapper = Mapping.from(A.class)
.to(B.class)
.reassign(A::getMessage) // This is where the "real" method of the proxy is called.
.to(B::getMessage)
.mapper();
A a = new A();
B b = mapper.map(a);
}
}
This effect only ocurrs on static classes (non-static inner classes are not supported due to the missing no-arguments constructor) with private getter-methods.
Possibly this is nothing that must be fixed, but throwing a MappingException
pointing out whats happening would be nice.
remap 4.0.0 pulls asm 6.0 jar which is in java 9 format:
[DEBUG] com.remondis:remap:jar:4.0.0:compile
[DEBUG] cglib:cglib:jar:3.2.6:compile
[DEBUG] org.ow2.asm:asm:jar:6.0:compile
This is causing problems with other tools in our build pipeline, so I just wanted to ask whether java 9 is an official requirement.
Thanks for the great declarative mapper. When there is Child class that extends Parent class, how can I define mappers for them so that mapping for parent is not duplicated in child mapper?
Great work!
Two messages that made it hard to pinpoint the cause:
When a mapper is missing it would be nice to mention the property name for which this is needed:
No mapper found for type mapping from java.lang.Float to java.lang.Double
When the same mapper is accidentally assigned twice by calling mapping.useMapper(mapper)
:
A mapper mapping the type A to type B was already registered.
(with A and B being the types of the mapping, not of the mapper, which was additionally confusing for me)
Hi! I'm using this to map my Entities and DTOs in the server side.
I'd like to do the same in my Android app.
I've written the code, and test for it all pass. But when I run the app I get this exception:
Caused by: java.lang.UnsupportedOperationException: can't load this type of class file
at java.lang.ClassLoader.defineClass(ClassLoader.java:591)
Looking over the internet I get to this StackOverflow answer.
Could you please provide a way to make it work on Android?
Thanks!
My use case is:
Source: Person with fields firstName, lastName, languageId
Destination: PersonDto with fields firstName, lastName, languageName
Can I somehow call mapper.map(person, languageNameByLanguageIdHashMap/producer of map) and define mapping for languageId -> languageName to get language name from this HashMap?
I can do it when creating mapping but I in my case, I create mapping when Spring starts and the HashMap needs to be created right before calling mapper.map( ) so that it contains latest data, because I am using it for something more dynamic than language.
See #102
To provide a comfortable way to map results of a Spring JPA Repository it would be nice to overload the method com.remondis.remap.Mapper.map()
to support mapping on Iterable<S>
.
Resulting API extension would be a method Iterable<D> com.remondis.remap.Mapper.map(Iterable<S>)
. Under the hood we can use a simple LinkedList
to get the resulting iterator from.
I'm implementing reMap in every Entity <-> DTO conversion. I also use a DTO when updating an Entity, and thus I would expect to read the original Entity from the DB and update the values when mapping.
Let me show you a dummy example:
public class User {
private String name;
private String lastname;
private Integer age;
}
public class User_updateDTO {
private String name;
private String lastname;
private Integer age;
}
What I would normally do is (without reMap):
User existingUser = readUserDB();
if (null != dto.getName()){
existingUser.setName(dto.getName());
}
// ... and the same for the other attributes
I was thinking in something like this:
Mapper< User_updateDTO, User > mapper = Mapping.from(User_updateDTO.class)
.to(User.class)
.replace(User_updateDTO::getName, User::getName)
.withSkipWhenNull(value -> value)
.replace(User_updateDTO::getLastname, User::getLastname)
.withSkipWhenNull(value -> value)
.replace(User_updateDTO::getAge, User:: getAge)
.withSkipWhenNull(value -> value)
.mapper;
The problem of course is the mapper creates a new User instance.
Maybe you could guide me in other direction in order to use reMap when updating. I appreciate any guidance. How do you work with updates? My idea of the DTO is to restrict the attributes allowed for update
Hello
ReMap throw always exception on Boolean field
Caused by: com.remondis.remap.MappingException: The method 'getNewsletterSubscribed' in type fr.monbanquet.magni.entity.CustomerEntity is not a valid Java Bean property get-method.
private Boolean newsletterSubscribed;
public Boolean getNewsletterSubscribed() {
return newsletterSubscribed;
}
public void setNewsletterSubscribed(Boolean newsletterSubscribed) {
this.newsletterSubscribed = newsletterSubscribed;
}
And I use it like that
Mapping.from(CustomerEntity.class)
.to(SfContact.class)
.reassign(CustomerEntity::getMail).to(SfContact::getEmail)
.omitInSource(CustomerEntity::getNewsletterSubscribed)
.mapper();
Regards
Hello
Sometime I just need to map some fields and I do not matter for the others and new
It's tedious to omit each field
For exemple I create a "little" object with 6 or 7 fields and need to copie them from an object with 30 or 40 fields -> by using ReMap, it's long and boring to write mapping
What do you think about omitAll() ?
The following code produces an exception although it is a valid mapping (the API confirms that):
Mapper<A, AResource> mapper = Mapping.from(A.class)
.to(AResource.class)
.replace(A::getStrings, AResource::getStrings)
.with(list -> {
List<String> newList = new LinkedList<>();
for (String s : list) {
newList.add(s + MODIFIER);
}
return newList;
})
.mapper();
Produces the following error:
java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List
at com.remondis.remap.ReplaceTransformation.lambda$2(ReplaceTransformation.java:58)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.remondis.remap.ReplaceTransformation.performTransformation(ReplaceTransformation.java:59)
at com.remondis.remap.Transformation.performTransformation(Transformation.java:124)
at com.remondis.remap.Mapping.map(Mapping.java:503)
at com.remondis.remap.Mapper.map(Mapper.java:39)
at com.remondis.remap.test.ReplaceOnCollectionsTest.test(ReplaceOnCollectionsTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
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.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:539)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)
Hi
I tend to use chained setters quite a lot and was wondering if it would be difficult to allow them, either by default or through configuration.
I wouldn't mind cooking up a PR if i think it would be a good idea (and if it is not too complex).
I did do a search through the issues to see if this is a duplicate, but did not find anything.
Best regards Jens
It would be nice to have a bidirectional mapper API that allows to bundle two mapper object for easier access. This would reduce the number of auto-wiring dependencies for Spring also.
Say that I have one input transfer object, and have to map it to class association, say jpa entities. These will be joined: there is 1 top level object, which has multiple child objects. Child objects has reference to top level object (currently not doable), and top level object will have reference to list of childs(current doable). We can do this by having mapping inside of mapping, but child cannot access toplevel object, because that one did call .mapper() yet. I'm not sure if I'm describing that in understandable manner, but mapping jpa entities association should be self descriptive.
Hi
While inspecting the dependency tree in my local project I noticed that you have the hamcrest library as a transitive dependency, should it not be in test scope?
Best regards Jens
When mapping from boolean
to Boolean
and vice-versa, then implicit mappings fail initialization due to 'incompatible types'.
This applies to all primitive types, because auto(un)boxing is currently not taken into account when analyzing primitive type mappings.
Is it possible to tell mapper to throw an exception if some of the fields is not mentioned in mapping? I am using mapper to copy some fields between objects of the same class and want to detect when a new field is added to the class so that I can decide whether to omit it during copying or not.
Hello
Sometime mapping cannot be do, so why not enable a custom mapping like this
Mapper<AccountEntity, SfAccount> mapperToSf =
Mapping.from(AccountEntity.class)
.to(SfAccount.class)
.map((source, destination) -> {
if (source.getBillingAddress() != null) {
destination.setBillingStreet(source.getBillingAddress().getStreet());
destination.setBillingCity(source.getBillingAddress().getCity());
destination.setBillingPostalCode(source.getBillingAddress().getZip());
destination.setBillingState(source.getBillingAddress().getState());
destination.setBillingCountry(source.getBillingAddress().getCountry());
if (source.getBillingAddress().getLocation() != null) {
destination.setBillingLatitude(source.getBillingAddress().getLocation()[0]);
destination.setBillingLongitude(source.getBillingAddress().getLocation()[1]);
}
}
})
.omitInSource(AccountEntity::getBillingAddress)
.omitInDestination(SfAccount::getBillingStreet)
.omitInDestination(SfAccount::getBillingCity)
.omitInDestination(SfAccount::getBillingPostalCode)
.omitInDestination(SfAccount::getBillingState)
.omitInDestination(SfAccount::getBillingCountry)
.omitInDestination(SfAccount::getBillingLatitude)
.omitInDestination(SfAccount::getBillingLongitude)
.mapper();
The method com.remondis.remap.ReplaceCollectionAssertBuilder.andTestButSkipWhenNull(Transform<RS, RD>)
requires one parameter which is not used in the code.
This parameter should be removed. The same issue like #25 but for replaceCollection
.
I have a class with a list of objects:
class Foo {
private List<Bar> bars;
// getters and setters
}
Now I add a custom getter to return a filtered part of the bars
list:
class Foo {
private List<Bar> bars;
public List<Bar> getFilteredBars(){
return this.bars.stream()
.filter(...)
.collect(Collectors.toList());
}
// more getters and setters
}
I want this getter to be ignored in mappings.
However, if I use omitInSource(Foo:getBars)
, I get the following exception:
Caused by: com.remondis.remap.MappingException: The get-method for property '...' in type ... is not a valid Java Bean property.
This makes it impossible to add custom "helper" getters, which is kind of a hard restriction.
Since property path < 0.1.0 is not compatible with JDK8 (due to a JDK 8 bug) ReMap needs an update to the latest version.
TODO: Find out if this could be done backwards-compatible.
I was trying out remap as a replacement for our mappers. The test by specification would be extremely useful to us.
My question is: We've got the case where we want to map a property of type List<ADTO>
to a property of type Set<A>
. Is this even supported?
I tried a combination of replaceCollection
and useMapper(TypeMapping.from(List.class).to(Set.class).applying(HashSet::new))
which results in the exception com.remondis.remap.MappingException: Invoking access method for property...
.
Currently, we're creating Mapper
instances in Spring Java Configurations like this:
@Configuration
public class MapperConfiguration {
@Bean
Mapper<MyClass1, MyClass2> myMapper() {
return Mapping.from(...)
// ...
.mapper();
}
}
We can then inject the mapper into other beans. However, this way, it's hard to find where the mapper is used within the codebase. I would have to search for "Mapper<MyClass1, MyClass2>" to find where it's injected.
It would be great if there was support for wrapping a Mapper into it's own class (or interface). It would look like this:
@Configuration
public class MapperConfiguration {
@Bean
MyMapper myMapper() {
return ...;
}
}
In the IDE, we could then just search for occurrences of MyMapper
to know where it's used.
It would be great if reMap supported "wrapper" classes like MyMapper
in the example above.
When having a mapper with a reassing that is used for a type mapping (B -> BResource
),...
.to(AResource.class)
.reassign(A::getB)
.to(AResource::getbResource)
.useMapper(bMapper)
.mapper();
...then the corresponding test using the Assert API produces a compiler error:
AssertMapping.of(aMapper)
.expectReassign(A::getB)
.to(AResource::getbResource)
.ensure();
This is because the support for different types for reassing was not reflected in the Assert API.
Fixed in #90
Possible API improvements would be:
com.remondis.remap.Mapper.mapOptional(T t)
Maps t
if non-null
, otherwise returns null
.com.remondis.remap.Mapper.mapOrDefault(T t, T default)
Maps t
if non-null
, otherwise returns default
.Hello!
Java 9 introduced the module system. If a non-modular JAR is used in a modular app, Java creates a so-called automatic module from it, whose name is derived from the JAR name (by default).
It is very important for modules to have stable names (just like packages), because changing it later may lead to the compilation errors and module hell. If you don't want to migrate to Java 9 yet, you can add the following entry to the MANIFEST file for forward compatibility:
Automatic-Module-Name: com.remondis.remap
It is neutral for older Java versions, and Java 9 will use it as the name of the automatic module, so that I could do the following thing in my application, without worrying about the future:
module com.example.foo {
requires com.remondis.remap;
}
(note: the official recommendation is to name the module from the root package, and use reverse-DNS style).
After introducing #45 an unmapped read-only property causes an NPE.
This bug is currently blocking the release of 3.0.5.
If a property of type Set<A>
needs to be mapped to a property of type List<B>
, a mapping from A to B is demanded, but not applied. Elements will be copied 1:1, which means you'll end up with A instances in the destination List<B>
This is a feature proposal.
I have Pet, Dog and Cat entity classes. Dog and Cat classes extend Pet. I also have the equivalent PetDTO, DogDTO and CatDTO.
I would like to map a PetDTO entity and get a Dog or a Cat entity in return.
Very similar to this in mapstruct: mapstruct/mapstruct#366
Hello
With OpenJDK 11
Remap 4.0.2
When I run my application I have this error :
2018-11-05 11:24:12,255 WARN [main] [] o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext.log | Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through field 'productMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'productMapper' defined in file [/home/mario/dev/product/product-app/target/classes/fr/app/product/mapper/ProductMapper.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [fr.app.product.mapper.ProductMapper]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/objectweb/asm/Type
An idea ?
Sometimes you have fields with types you don't want to 'map' field by field but to 'convert'. For instance, when you have a field of type Calendar
that should be mapped to a field of type Date
. I.e. when you have fields with types that do not follow the Java Bean conventions.
I currently don't see a way to create a mapper that does that. And I think this is a feature that will be needed sooner than later.
I came upon this while trying to add ReMap to the performace test suite for this blog post. In order to make the mapper competetive, we need this feature. Only when this feature is implemented can we ask to have the mapper included in the blog post :).
Upgrade to new Cglib and Asm version. Evaluate if this is has side effects.
Hello
I have a field that is a generated message from some fields in source object
I would like to do something like this
Mapping.from(ActivityEntity.class)
.to(ActivityDto.class)
.set(ActivityDto::getMessage).with(this::getMessage)
.omitInSource(ActivityEntity::getId)
.mapper();
private String getMessage(ActivityEntity entity) {
switch (entity.getAction()) {
case ORDER_SHOP_ADD:
return "Supplier added " + entity.getShop();
case ORDER_ATTRIBUTED:
return "Attributed to " + entity.getAttributeTo();
case ORDER_CLONED:
return entity.getClone() == null ? "" : entity.getClone().getFirst() + " clone to " + entity.getClone().getSecond();
}
}
I'm mapping generated AVRO file to say JPA entity. But generated AVRO has Strings as CharSequence, for which there is no Mapper for. OK, so we useMapper
:
.useMapper(Mapping.from(CharSequence.class).to(String.class).mapper())
but ... that won't work, since there is not (reasonable) properties to map and string is immutable. So we need to be able to replace whole class to define such mapper. Currently I don't see such option.
The javadoc states
In a future release this method may allow to test the transformation function.
so there just seems some functionality missing?
The mapping of enumeration values currently results in an exception because a primitive type mapping is detected and an identity mapping is created. This results in an exception because an enum type does not meet the Java bean requirements.
The method com.remondis.remap.Transformation.isValidPrimitiveMapping(Class<?>, Class<?>)
should be renamed to isValidReferenceMapping
because it returns true
whenever a reference mapping should be used - except of enumerations. This method also should return true
of the involved types are enumerations.
Workaround for this issue: Let gender
be defines by an enumeration - the following snippet avoids the mapping exception when mapping enums:
.replace(Person::getGender, PersonResource::getGender)
.withSkipWhenNull(g -> g)
Like Mapper.omitAll()
, that adds omit declarations for unmapped fields, it may be useful to have this feature also in the Assert API. A method like AssertMapping.expectOthersToBeOmitted()
can be implemented to assert that all fields not mentioned by the asserts are expected to be omitted.
Hello
I have an suggestion because sometime I populate an object that exists before (loaded from database for update operations for exemple)
private static final Mapper<SfContact, CustomerEntity> mapperToEntity =
Mapping.from(SfContact.class)
.to(CustomerEntity.class)
.mapper();
public static CustomerEntity toEntity(CustomerEntity entity, SfContact sfContact) {
return mapperToEntity.map(sfContact); <-----
}
I would like to have someting like :
return mapperToEntity.with(entity).map(sfContact);
or (update)
return mapperToEntity.map(entity, sfContact);
What do you think about it ?
In Transform<D, S> should be refactored to Transform<S, D> so that the source type is first and the destination type is second.
This change breaks the API, however!
The mapper creates property names from the get- or set-method transforming the first letter to lower case.
static String toPropertyName(Method method) {
String name = method.getName();
if (isBoolGetter(method)) {
return firstCharacterToLowerCase(name.substring(2, name.length()));
} else {
if (isGetterOrSetter(method)) {
return firstCharacterToLowerCase(name.substring(3, name.length()));
} else {
throw new IllegalArgumentException("The specified method is neither a getter nor a setter method.");
}
}
}
In case of properties like 'aProp' with a getter 'getAProp' the PropertyDescripter does not convert the first character to lower case. The rule is no conversion, if the first two characters of the name are both uppercase.
So the mapper failed getting the PropertyDescripter because of no matching property name and the property will be marked as invalid java bean property.
static PropertyDescriptor getPropertyDescriptorOrFail(Target target, Class<?> type, String propertyName) {
Optional<PropertyDescriptor> property;
property = Properties.getProperties(type, target)
.stream()
.filter(pd -> pd.getName()
.equals(propertyName))
.findFirst();
if (property.isPresent()) {
return property.get();
} else {
throw notAProperty(type, propertyName);
}
}
Even if a type mapping is registered, the mapping of maps is unsupported. See #87
Hi,
Is the latest version of mapper compatible with JDK 10?
Just bumped my project and can see this exception caused by Remap.
Caused by: java.lang.IllegalArgumentException: null
at org.objectweb.asm.ClassReader.(ClassReader.java:160) ~[asm-6.0.jar:6.0]
at org.objectweb.asm.ClassReader.(ClassReader.java:143) ~[asm-6.0.jar:6.0]
at org.objectweb.asm.ClassReader.(ClassReader.java:418) ~[asm-6.0.jar:6.0]
at net.sf.cglib.proxy.BridgeMethodResolver.resolveAll(BridgeMethodResolver.java:69) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.emitMethods(Enhancer.java:1132) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:630) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) ~[cglib-3.2.6.jar:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305) ~[cglib-3.2.6.jar:na]
at com.remondis.remap.InvocationSensor.(InvocationSensor.java:54) ~[remap-4.0.0.jar:na]
at com.remondis.remap.Mapping.getTypedPropertyFromFieldSelector(Mapping.java:353) ~[remap-4.0.0.jar:na]
at com.remondis.remap.Mapping.reassign(Mapping.java:157) ~[remap-4.0.0.jar:na]
Thanks
Property path mappings can be specified for replace operations. A property path for set operation would be helpful.
Currently a workaround can be used: Use property path as function for set operation.
Given the following scenario:
public class A {
public String multiMapped;
// Getters & Setters...
}
public class AResource {
public String multiMapped1;
public String multiMapped2;
public String multiMapped3;
public String omitted;
}
public class MapperTest {
@Test
public void shouldMap() {
Mapping.from(A.class)
.to(AResource.class)
.omitInDestination(AResource::getOmitted)
.replace(A::getMultiMapped, AResource::getMultiMapped1)
.withSkipWhenNull(Function.identity())
.replace(A::getMultiMapped, AResource::getMultiMapped2)
.withSkipWhenNull(Function.identity())
.replace(A::getMultiMapped, AResource::getMultiMapped3)
.withSkipWhenNull(Function.identity())
.mapper();
}
}
...the Mapper will throw an NPE. This is because com.remondis.remap.Mapping.denyAlreadyOmittedProperty(PropertyDescriptor)
erroneously relies on not having an omitInDestination
in the mapping configuration.
When creating a mapper for generic type like this:
MyType<R> {
R getResult();
}
in remap 4.2.0 the following exception is thrown:
Caused by: java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
at com.remondis.remap.GenericParameterContext.init(GenericParameterContext.java:46)
at com.remondis.remap.GenericParameterContext.<init>(GenericParameterContext.java:29)
at com.remondis.remap.ReassignTransformation.validateTransformation(ReassignTransformation.java:182)
at com.remondis.remap.MappingConfiguration.validateMapping(MappingConfiguration.java:444)
at com.remondis.remap.MappingConfiguration.mapper(MappingConfiguration.java:365)
It is working without problems in remap 4.1.12
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.