<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Answers to: Can not persist Business Data to Repo after changing data type</title><link>https://answers.axonivy.com/questions/2606/can-not-persist-business-data-to-repo-after-changing-data-type</link><description>&lt;p&gt;Hi all&lt;/p&gt;
&lt;p&gt;I'm using Ivy 6.3 and use ivy.repo api to persist data. When i persits data as this JSON:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;"qualificationMessageResults": [
        {
            "code": "amount",
            "severity": "ORANGE",
            "message": {
                "descriptor": {
                    "content": "/ch/axonivy/fintech/soba/Message/PreQualification/Amount/amountBetweenMinAmountAndMaxAmountForReplacement",
                    "type": "URI"
                },
                "paramDescriptors": [
                    {
                        "descriptor": {
                            "content": "500000",
                            "type": "PLAIN_TEXT",
                            "placeHolder": "{minAmount}"
                        },
                        "paramDescriptors": []
                    }
                ]
            }
        }
    ]
},
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The api say:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; [errorId=15BCE2ED377AD1E0, request=HTTP POST ch/axonivy/fintech/soba/showcase/DemoSobaPersistence/DemoSobaPersistenceProcess.mod/15A1694DAA1C0A9F(9907.9907.17.0), session=1, task=9907, application=102, requestId=4093, executionContext=1, pmv=Portal$soba_test$2, hd=ch.axonivy.fintech.soba.showcase.DemoSobaPersistence, processElement=15A168DC648B6158-f9]
Caused by: ch.ivyteam.ivy.persistence.PersistencyException: Could not create BusinessData.
    at ch.ivyteam.ivy.business.data.store.internal.ElasticSystemDbPersistence.execute(ElasticSystemDbPersistence.java:115)
    at ch.ivyteam.ivy.business.data.store.internal.ElasticSystemDbPersistence.execute(ElasticSystemDbPersistence.java:104)
    at ch.ivyteam.ivy.business.data.store.internal.ElasticSystemDbPersistence.create(ElasticSystemDbPersistence.java:89)
    at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.persist(BusinessDataRepositoryImpl.java:112)
    at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.save(BusinessDataRepositoryImpl.java:96)
    at ch.axonivy.fintech.standard.dossier.persistence.BaseDossierPersistence.persist(BaseDossierPersistence.java:35)
    at ch.axonivy.fintech.soba.dossier.service.SobaDossierService.persist(SobaDossierService.java:155)
    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 ch.ivyteam.ivy.scripting.internal.types.IvyJavaMethod.invokeImpl(IvyJavaMethod.java:73)
    ... 208 more
[errorId=15BCE2ED377AD1E0, request=HTTP POST ch/axonivy/fintech/soba/showcase/DemoSobaPersistence/DemoSobaPersistenceProcess.mod/15A1694DAA1C0A9F(9907.9907.17.0), session=1, task=9907, application=102, requestId=4093, executionContext=1, pmv=Portal$soba_test$2, hd=ch.axonivy.fintech.soba.showcase.DemoSobaPersistence, processElement=15A168DC648B6158-f9]
Caused by: ch.ivyteam.ivy.business.data.store.search.internal.elasticsearch.ElasticsearchException: Elasticsearch update index of document failed because of: {"root_cause":[{"type":"mapper_parsing_exception","reason":"failed to parse [onlineMortgageProgress.qualificationMessageResults.message]"}],"type":"mapper_parsing_exception","reason":"failed to parse [onlineMortgageProgress.qualificationMessageResults.message]","caused_by":{"type":"illegal_argument_exception","reason":"unknown property [descriptor]"}}
    at ch.ivyteam.ivy.business.data.store.search.internal.elasticsearch.JestOperation.checkStatusAndThrow(JestOperation.java:61)
    at ch.ivyteam.ivy.business.data.store.search.internal.elasticsearch.JestOperation.execute(JestOperation.java:39)
    at ch.ivyteam.ivy.business.data.store.search.internal.elasticsearch.JestIndexSynchronizer.execute(JestIndexSynchronizer.java:165)
    at ch.ivyteam.ivy.business.data.store.search.internal.elasticsearch.JestIndexSynchronizer.updateIndex(JestIndexSynchronizer.java:64)
    at ch.ivyteam.ivy.business.data.store.search.internal.ElasticBusinessDataSearchIndex.update(ElasticBusinessDataSearchIndex.java:30)
    at ch.ivyteam.ivy.business.data.store.internal.ElasticSystemDbPersistence.lambda$1(ElasticSystemDbPersistence.java:96)
    at ch.ivyteam.ivy.persistence.base.AbstractPersistencyService.execute(AbstractPersistencyService.java:177)
    at ch.ivyteam.ivy.persistence.base.AbstractPersistencyService.execute(AbstractPersistencyService.java:240)
    at ch.ivyteam.ivy.persistence.base.ClassPersistencyService.execute(ClassPersistencyService.java:694)
    at
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My object QualificationMessageResult has list of Object A, and object A has two properties: a object &lt;strong&gt;descriptor&lt;/strong&gt; and a list of Object A (looped Object) with name: &lt;strong&gt;paramDescriptors&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Can anyone suggest me something?&lt;/p&gt;
&lt;p&gt;Thanks&lt;/p&gt;</description><atom:link href="https://answers.axonivy.com/questions/2606/can-not-persist-business-data-to-repo-after-changing-data-type" rel="self"></atom:link><language>en</language><lastBuildDate>Tue, 04 Jul 2017 08:29:24 -0400</lastBuildDate><item><title>Answer by Reguel Wermelinger</title><link>https://answers.axonivy.com/questions/2606/can-not-persist-business-data-to-repo-after-changing-data-type/2731</link><description>&lt;p&gt;You do not run into this problem if you &lt;strong&gt;just introduce a new attribute for the new type&lt;/strong&gt; instead of re-using the existing attribute that already contains other data. Business Data is explicitly designed to allow simple data migration. So it does not throw any errors for unknown fields.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;However, there is a work around&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you just wrapped the String in a complex object you could work around the problem by influencing the JSON serialization. With Jackson you could for instance store the new complex object also as string and read it back to a complex object. And of course this also allows you to handle legacy serialized objects.&lt;/p&gt;
&lt;p&gt;The rough concept is described here: &lt;a href="http://developer.axonivy.com/doc/latest/DesignerGuideHtml/ivy.datamodeling.html#ivy.businessdata.serialization.module"&gt;http://developer.axonivy.com/doc/latest/DesignerGuideHtml/ivy.datamodeling.html#ivy.businessdata.serialization.module&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A sample implementation could do the following. Here we serialize a complex Person object as a raw String.&lt;/p&gt;
&lt;p&gt;FIRST: Write your own serializer module:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package com.axonivy;

import java.io.IOException;

import org.apache.commons.lang3.StringUtils;

import ch.ivyteam.ivy.environment.Ivy;

import com.axonivy.sample.Person;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;

public class CustomBusinessDataModule extends SimpleModule {

    private static final long serialVersionUID = 1L;
    private static final String SEPARATOR = "|";

    public CustomBusinessDataModule()
    {
        Ivy.log().info("registered custom module!");
        addSerializer(Person.class, new CustomPersonSerializer());
        addDeserializer(Person.class, new CustomPersonDeSerializer());
    }

    @SuppressWarnings("serial")
    private static class CustomPersonSerializer extends StdScalarSerializer&amp;lt;Person&amp;gt;
    {

        public CustomPersonSerializer() {
            super(Person.class);
        }

        @Override
        public void serialize(Person value, JsonGenerator gen,
                SerializerProvider provider) throws IOException {
            gen.writeString(value.getFirstname()+SEPARATOR+value.getLastname());
        }
    }

    @SuppressWarnings("serial")
    private static class CustomPersonDeSerializer extends StdScalarDeserializer&amp;lt;Person&amp;gt;
    {
        public CustomPersonDeSerializer()
        {
            super(Person.class);
        }

        @Override
        public Person deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            String value = p.readValueAs(String.class);
            if (!StringUtils.contains(value, SEPARATOR))
            {
                // old version.... -&amp;gt; take special care!
                return new Person();
            }

            String[] parts = StringUtils.split(value, SEPARATOR);
            Person person = new Person();
            person.setFirstname(parts[0]);
            person.setLastname(parts[1]);
            return person;
        }
    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SECOND: register it via service SPI: &lt;/p&gt;
&lt;p&gt;&lt;img alt="alt text" src="http://answers.axonivy.com/upfiles/registerCustomJacksonModule.png"&gt;&lt;/p&gt;
&lt;p&gt;Here you see the custom serializer in action:&lt;/p&gt;
&lt;p&gt;&lt;a href="/upfiles/businessDataSerializer_66.iar"&gt;businessDataSerializer_66.iar&lt;/a&gt;
&lt;img alt="alt text" src="http://answers.axonivy.com/upfiles/customCreatedJson.png"&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Reguel Wermelinger</dc:creator><pubDate>Tue, 04 Jul 2017 08:29:24 -0400</pubDate><guid>https://answers.axonivy.com/questions/2606/can-not-persist-business-data-to-repo-after-changing-data-type/2731</guid></item></channel></rss>