Persisting super column family Object with List<String> property causes LuceneIndexingException #65

Closed
rsumibcay opened this Issue May 16, 2012 · 7 comments

Comments

Projects
None yet
5 participants

Hello,

Please help me understand what I am doing wrong. Thanks!

persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="cassandra_pu">
<provider>com.impetus.kundera.KunderaPersistence</provider>
<properties>
<property name="kundera.nodes" value="localhost"/>
<property name="kundera.port" value="9160"/>
<property name="kundera.keyspace" value="UserTest"/>
<property name="kundera.dialect" value="cassandra"/>
<property name="kundera.client.lookup.class" value="com.impetus.client.cassandra.pelops.PelopsClientFactory" />
<property name="kundera.cache.provider.class" value="com.impetus.kundera.cache.ehcache.EhCacheProvider"/>
<property name="kundera.cache.config.resource" value="/ehcache-test.xml"/>
<property name="index_home_dir" value="/Users/ronel/Cassandra/indexes"/>
</properties>
</persistence-unit>
</persistence>

Column family creation:

CREATE COLUMN FAMILY users
WITH comparator = UTF8Type
AND key_validation_class=UTF8Type
AND default_validation_class=BytesType
AND subcomparator=BytesType
AND column_type=Super;

User.java:

@entity
@table(name = "users", schema = "UserTest@cassandra_pu")
public class User
{
@id
protected String userId;

@Column
protected String firstName = "";

@Column
protected String lastName = "";

@Embedded
protected UserAddress userAddress;

@Column
protected List<String> promoCodes = new ArrayList<String>(); //This causes LuceneIndexingException

public User() {}

public void setPromoCodes( List<String> p) {
    promoCodes = p;
}

public List<String> getPromoCodes() {
    return promoCodes;
}

public String getUserId()
{
    return userId;
}
public void setUserId(String userId)
{
    this.userId = userId;
}
public String getFirstName()
{
    return firstName;
}
public void setFirstName(String firstName)
{
    this.firstName = firstName;
}
public String getLastName()
{
    return lastName;
}
public void setLastName(String lastName)
{
    this.lastName = lastName;
}

}

UserAddress.java:

@embeddable
public class UserAddress {

@Column
public String address1 = "";
@Column
public String address2 = "";
@Column
public String city = "";
@Column
public String state = "";
@Column
public String zip = "";

}

Persistence Code:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("cassandra_pu");
EntityManager em = emf.createEntityManager();

User user = new User();
user.setUserId( java.util.UUID.randomUUID().toString() );
user.setFirstName( "Ronel");

java.util.ArrayList promos = new java.util.ArrayList();
promos.add("promo1");
promos.add("promo2");
user.setPromoCodes( promos );

em.persist( user );

em.close();
emf.close();

Exception Stacktrace:

2012-05-16 16:08:15,478 [ERROR] [tomcat-http--8] com.impetus.kundera.index.DocumentIndexer - Error in accessing field:java.lang.IllegalArgumentException: Can not set java.util.List field com.mycricket.webcart.schemas.User.promoCodes to java.lang.String
com.impetus.kundera.KunderaException: com.impetus.kundera.index.LuceneIndexingException: Error in accessing field:promoCodes
at com.impetus.client.cassandra.pelops.PelopsClient.persist(PelopsClient.java:390)
at com.impetus.kundera.lifecycle.states.ManagedState.handleFlush(ManagedState.java:153)
at com.impetus.kundera.graph.Node.flush(Node.java:478)
at com.impetus.kundera.persistence.PersistenceDelegator.flush(PersistenceDelegator.java:290)
at com.impetus.kundera.persistence.PersistenceDelegator.persist(PersistenceDelegator.java:148)
at com.impetus.kundera.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:191)
at com.mycricket.webcart.service.GetCartService.saveCart(GetCartService.java:244)
at com.mycricket.webcart.endpoint.GetCartEndpoint.saveCart(GetCartEndpoint.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.ws.server.endpoint.MethodEndpoint.invoke(MethodEndpoint.java:132)
at org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter.invokeInternal(DefaultMethodEndpointAdapter.java:229)
at org.springframework.ws.server.endpoint.adapter.AbstractMethodEndpointAdapter.invoke(AbstractMethodEndpointAdapter.java:53)
at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:231)
at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:172)
at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88)
at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:59)
at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:221)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.traceNextValve(HttpRequestOperationCollectionValve.java:112)
at com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:94)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:279)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:300)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
Caused by: com.impetus.kundera.index.LuceneIndexingException: Error in accessing field:promoCodes
at com.impetus.kundera.index.DocumentIndexer.addFieldToDocument(DocumentIndexer.java:315)
at com.impetus.kundera.index.DocumentIndexer.indexSuperColumn(DocumentIndexer.java:182)
at com.impetus.kundera.index.LuceneIndexer.indexDocument(LuceneIndexer.java:499)
at com.impetus.kundera.index.LuceneIndexer.index(LuceneIndexer.java:402)
at com.impetus.kundera.index.IndexManager.update(IndexManager.java:92)
at com.impetus.kundera.client.ClientBase.indexNode(ClientBase.java:129)
at com.impetus.client.cassandra.pelops.PelopsClient.persist(PelopsClient.java:386)
... 41 more
Caused by: com.impetus.kundera.property.PropertyAccessException: java.lang.IllegalArgumentException: Can not set java.util.List field com.mycricket.webcart.schemas.User.promoCodes to java.lang.String
at com.impetus.kundera.property.PropertyAccessorHelper.getObject(PropertyAccessorHelper.java:143)
at com.impetus.kundera.index.DocumentIndexer.addFieldToDocument(DocumentIndexer.java:299)
... 47 more
Caused by: java.lang.IllegalArgumentException: Can not set java.util.List field com.mycricket.webcart.schemas.User.promoCodes to java.lang.String
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
at java.lang.reflect.Field.get(Field.java:358)
at com.impetus.kundera.property.PropertyAccessorHelper.getObject(PropertyAccessorHelper.java:139)
... 48 more

@ghost ghost assigned kkmishra May 17, 2012

Collaborator

mevivs commented May 17, 2012

Assigned Kuldeep to look into this.

Contributor

kkmishra commented May 17, 2012

Hi rsumibcay

Problem is with the following attribute in your entity class:

@column
protected List promoCodes = new ArrayList();

A collection of String (or primitive/ wrapper) is not supported by Kundera.
If you want to store your promo codes as super column, Create an @embeddable class (say PromoCode) and define attribute inside it. It should look something like this:

@embeddable
public class PromoCode {
@column(name = "promoCode_id")
private String promoCodeId;

@Column(name = "promoCode_name")
private String promoCodeName;

    //Getters/ setters here

}

In your User entity class, declare it as:

@elementcollection
private List promoCodes = new ArrayList();

This will be stored in User column family as super columns.

You can find an example here where Tweet class is an ElementCollection inside User:
https://github.com/impetus-opensource/Kundera-Examples/wiki/Twitter

Thanks
-Kuldeep

Got it. I've done what you've suggested and it all works now. Thanks Kuldeep!

Collaborator

mevivs commented May 18, 2012

Great! closing this issue.

@mevivs mevivs closed this May 18, 2012

Contributor

georgkoester commented May 24, 2012

Hi there,

I tested this and I get an exception:
com.impetus.kundera.query.QueryHandlerException: column type is null for: name
at com.impetus.client.cassandra.query.CassQuery.getBytesValue(CassQuery.java:332)
at com.impetus.client.cassandra.query.CassQuery.prepareIndexClause(CassQuery.java:195)
at com.impetus.client.cassandra.query.CassQuery.populateEntities(CassQuery.java:104)
at com.impetus.kundera.query.QueryImpl.getResultList(QueryImpl.java:147)

It blows when I query against an EMPTY keyspace:
return userDao.getFirst("select u from User u where u.name = :name",
Collections.singletonMap("name", name));

When I simply comment the @elementcollection annotation it works again.

Hint: u.name is a secondary index, not the rowkey!

I'm on Cassandra 1.1.0

Sorry if I'm not getting it - it seems to work for some?

Georg

Code:

@entity
@table(...)
public class User extends AbstractEntity {
...
@elementcollection
private List someIds = new ArrayList();
...
}

@embeddable
public class StringId {
...
@column(name = "id")
private String id;
...
}

@xamry xamry reopened this May 25, 2012

Contributor

xamry commented May 25, 2012

Hi Georg,

Could you please elaborate more on what you mean by empty keyspace.

Also, Any @elementcollection attribute must be a collection of object whose class is embeddable (like List of Address, Set of Department etc where Address and Department classes are annotated with @embeddable). A List or List of String won't simply work. For an example, visit: https://github.com/impetus-opensource/Kundera-Examples/wiki/Twitter

Regards,
Amresh

Also,

Collaborator

mevivs commented Jul 24, 2012

Closing on this, as not received any further input.

@mevivs mevivs closed this Jul 24, 2012

mevivs added a commit that referenced this issue Jan 24, 2013

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