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

jsonContext.toJson(o, generator, path) can not apply path on @Transient field that is an entity bean #502

Closed
icode opened this issue Dec 18, 2015 · 26 comments
Assignees
Labels
Milestone

Comments

@icode
Copy link
Contributor

icode commented Dec 18, 2015

class Model {
String a;
@Transient
List<ModelB> list;
}
Model model = findById(1);
model.list = find(ModelB.class).select("oneField").findList();
//path -> (a,list(oneField))
jsonContext.toJson(o, generator, path)
//-> {"a":"a",list:[{"oneField":1,"twoField":null}]} should not show `twoField`
@icode
Copy link
Contributor Author

icode commented Dec 21, 2015

Hello @rbygrave ?

@rbygrave
Copy link
Member

Hello
On 21 Dec 2015 5:55 pm, "icode" notifications@github.com wrote:

�Hello @rbygrave https://github.com/rbygrave ?


Reply to this email directly or view it on GitHub
#502 (comment)
.

@icode
Copy link
Contributor Author

icode commented Dec 22, 2015

Haha, you are funny! @rbygrave This is a bug or issue?

@rbygrave
Copy link
Member

I had a quick look and it didn't make sense to me. If you want to update it so that it makes more sense I'll have another look.

@icode
Copy link
Contributor Author

icode commented Dec 23, 2015

on jax-rs , i give a fields params (a,list(oneField)), but can not filter Transient field

@icode
Copy link
Contributor Author

icode commented Dec 23, 2015

jackson module call jsonContext.toJson(o, generator, path) i give it path

@icode
Copy link
Contributor Author

icode commented Dec 23, 2015

Or other function filter @Transient field?

@icode
Copy link
Contributor Author

icode commented Dec 28, 2015

@rbygrave Are you understand ?

@rbygrave
Copy link
Member

rbygrave commented Jan 4, 2016

No, this does not make sense. There is no explanation of what 'twoField' is nor "oneField" ... neither are in the model where you are trying to explain the issue.

@rbygrave
Copy link
Member

rbygrave commented Jan 4, 2016

o, generator and path ... are also not defined in your example code.

@rbygrave rbygrave closed this as completed Jan 4, 2016
@rbygrave rbygrave reopened this Jan 4, 2016
@icode
Copy link
Contributor Author

icode commented Jan 5, 2016

@Test
public void testTransientPath() throws Throwable {
    ModelA modelA = Ebean.find(ModelA.class, 1);
    modelA.list = Ebean.createQuery(ModelB.class).select("oneField").findList();
    String json = Ebean.json().toJson(modelA, PathProperties.parse("(a,list(oneField))"));
    Assert.assertEquals(json, "{\"a\":\"a\",\"list\":[{\"oneField\":1}]}");
 }

@Entity
class ModelA {
    String a;
    @Transient  // it's not has mapping, but client need result
    List<ModelB> list;
}

@Entity
class ModelB {
    Integer oneField;
    Integer twoField;
}

@icode
Copy link
Contributor Author

icode commented Jan 5, 2016

@rbygrave please see test case, understand ?

@rbygrave
Copy link
Member

rbygrave commented Jan 5, 2016

Very close. You now just need to state:

  1. which assert fails
  2. what your expectation is ... "I expected json to contain <...> but what I instead saw was that it instead contained <...>"

@icode
Copy link
Contributor Author

icode commented Jan 5, 2016

I want this Assert.assertEquals(json, "{\"a\":\"a\",\"list\":[{\"oneField\":1}]}"); success.
twoField should not in json string

@icode
Copy link
Contributor Author

icode commented Jan 5, 2016

now , @Transient field not apply PathProperties in toJson.

@rbygrave
Copy link
Member

rbygrave commented Jan 5, 2016

It would be clear if you state exactly what the value of json is. Specifically the first assertNotEquals() passing is confusing me.

@icode
Copy link
Contributor Author

icode commented Jan 5, 2016

ok, i change it. are you understand?

@rbygrave
Copy link
Member

rbygrave commented Jan 5, 2016

It would be clear if you state exactly what the value of json is.

@icode
Copy link
Contributor Author

icode commented Jan 5, 2016

//path -> (a,list(oneField))

json {"a":"a","list":[{"oneField":1}]}

@rbygrave
Copy link
Member

rbygrave commented Jan 5, 2016

What is wrong with that? It is the same as the assertEquals ... so you are saying the assert does not fail?

Assert.assertEquals(json, "{\"a\":\"a\",\"list\":[{\"oneField\":1}]}");

@icode
Copy link
Contributor Author

icode commented Jan 5, 2016

I get {"a":"a",list:[{"oneField":1,"twoField":null}]}

@icode
Copy link
Contributor Author

icode commented Jan 5, 2016

import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.EbeanServerFactory;
import com.avaje.ebean.config.DataSourceConfig;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.text.PathProperties;
import com.google.common.collect.Lists;
import org.avaje.agentloader.AgentLoader;
import org.h2.Driver;
import org.junit.Assert;
import org.junit.Test;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import java.io.IOException;
import java.lang.instrument.IllegalClassFormatException;
import java.util.List;

/**
 * @author icode
 */
public class EbeanTest {

    @Test
    public void JsonTest() throws IOException, IllegalClassFormatException, ClassNotFoundException {
        AgentLoader.loadAgentFromClasspath("avaje-ebeanorm-agent", "debug=5");
        final ServerConfig config = new ServerConfig();
        config.setClasses(Lists.<Class<?>>newArrayList(ModelA.class, ModelB.class));
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setUrl("jdbc:h2:file:./db");
        dataSourceConfig.setDriver(Driver.class.getName());
        dataSourceConfig.setUsername("sa");
        dataSourceConfig.setPassword("");
        config.setDataSourceConfig(dataSourceConfig);
        config.setName("default");
        config.setDdlGenerate(true);
        config.setDdlRun(true);
        config.setDefaultServer(true);
        EbeanServer server = EbeanServerFactory.create(config);
        ModelA a = new ModelA();
        a.setId(1);
        a.setA("a");
        server.save(a);
        ModelB b = new ModelB();
        b.setOneField(1);
        b.setTwoField(1);
        server.save(b);
        ModelA sa = server.find(ModelA.class, 1);
        sa.setList(server.find(ModelB.class).findList());
        String json = Ebean.json().toJson(sa, PathProperties.parse("(a,list(oneField))"));
        Assert.assertEquals(json, "{\"a\":\"a\",\"list\":[{\"oneField\":1}]}");
    }

    @Entity
    public static class ModelA {
        @Id
        int id;
        String a;
        @Transient  // it's not has mapping, but client need result
                List<ModelB> list;

        public String getA() {
            return a;
        }

        public void setA(String a) {
            this.a = a;
        }

        public List<ModelB> getList() {
            return list;
        }

        public void setList(List<ModelB> list) {
            this.list = list;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }
    }

    @Entity
    public static class ModelB {
        Integer oneField;
        Integer twoField;

        public Integer getOneField() {
            return oneField;
        }

        public void setOneField(Integer oneField) {
            this.oneField = oneField;
        }

        public Integer getTwoField() {
            return twoField;
        }

        public void setTwoField(Integer twoField) {
            this.twoField = twoField;
        }
    }
}

this is clear test case! thanks test it!

@icode
Copy link
Contributor Author

icode commented Jan 7, 2016

can fix it? @rbygrave thanks

@rbygrave
Copy link
Member

Running this test produces:

org.junit.ComparisonFailure:
Expected :{"a":"a","list":[{"oneField":1,"twoField":1}]}
Actual :{"a":"a","list":[{"oneField":1}]}

Hmm, there is no null there.

@rbygrave
Copy link
Member

BeanPropertyAssocMany line 891. transient properties written via the Jackson ObjectMapper ... so that means there is for example no check that the target type is actually an entity bean. This is probably the issue.

@rbygrave rbygrave changed the title jsonContext.toJson(o, generator, path) can not apply path on @Transient field jsonContext.toJson(o, generator, path) can not apply path on @Transient field that is an entity bean Jan 13, 2016
@rbygrave rbygrave added this to the 6.15.2 milestone Jan 13, 2016
@rbygrave rbygrave self-assigned this Jan 13, 2016
rbygrave added a commit that referenced this issue Jan 13, 2016
@rbygrave
Copy link
Member

Right, the fix was that for transient ToMany properties to also check the targetDescriptor to see if they are entity beans (in which case we can keep processing with the built in JSON processing rather than use Jackson ObjectMapper).

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

No branches or pull requests

2 participants