Bug 833393 - "Example 1.7. Using JPA to create and execute a search" java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Date
Summary: "Example 1.7. Using JPA to create and execute a search" java.lang.ClassCastE...
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: JBoss Enterprise WFK Platform 2
Classification: Retired
Component: doc-Hibernate-Search-Guide
Version: 2.0.0.GA
Hardware: Unspecified
OS: Unspecified
unspecified
high
Target Milestone: GA
: 2.1.0
Assignee: WFK Docs Team
QA Contact: Marek Schmidt
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2012-06-19 11:53 UTC by Marek Schmidt
Modified: 2013-06-27 12:17 UTC (History)
4 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2013-06-27 12:17:08 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
source code of the example (85.71 KB, application/x-gzip)
2012-06-19 12:04 UTC, Marek Schmidt
no flags Details


Links
System ID Private Priority Status Summary Last Updated
Red Hat Bugzilla 870932 0 low CLOSED Aggregator for WFK 2.1 Hibernate Search Guide issues 2021-02-22 00:41:40 UTC

Internal Links: 870932

Description Marek Schmidt 2012-06-19 11:53:38 UTC
Description of problem:

Recreating a simple hibernate search application based "JavaEE Web Project" and "Example 1.7. Using JPA to create and execute a search" in the Hibernate Search guide

http://documentation-stage.bne.redhat.com/docs/en-US/JBoss_Web_Framework_Kit/2/html-single/Hibernate_Search/index.html#id3910797

doesn't work properly.

I have added the hibernate search annotations to the Member entity and created a new field to verify the @DateBridge:

@Entity
@XmlRootElement
@Table(uniqueConstraints = @UniqueConstraint(columnNames = "email"))
@Indexed
public class Member implements Serializable {
   /** Default value included to remove warning. Remove or modify at will. **/
   private static final long serialVersionUID = 1L;

   @Id
   @GeneratedValue
   private Long id;

   @NotNull
   @Size(min = 1, max = 25)
   @Pattern(regexp = "[A-Za-z ]*", message = "must contain only letters and spaces")
   @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
   private String name;

   @NotNull
   @NotEmpty
   @Email
   @Field(index=Index.YES, analyze=Analyze.NO, store=Store.NO)
   private String email;

   @NotNull
   @Size(min = 10, max = 12)
   @Digits(fraction = 0, integer = 12)
   @Column(name = "phone_number")
   @Field(index=Index.YES, analyze=Analyze.NO, store=Store.NO)
   private String phoneNumber;
   
   @Field(index=Index.YES, analyze=Analyze.NO, store=Store.YES)
   @DateBridge(resolution=Resolution.DAY)
   private Date dateOfBirth;
...

and created a search method as described in the example from the Hibernate Search guide:

public List<Member> search(String queryString) {
      FullTextEntityManager fullTextEntityManager = 
            org.hibernate.search.jpa.Search.getFullTextEntityManager(em);

        // create native Lucene query unsing the query DSL
        // alternatively you can write the Lucene query using the Lucene query parser
        // or the Lucene programmatic API. The Hibernate Search DSL is recommended though
        QueryBuilder qb = fullTextEntityManager.getSearchFactory()
            .buildQueryBuilder().forEntity( Member.class ).get();
        org.apache.lucene.search.Query query = qb
          .keyword()
          .onFields("name", "email", "dateOfBirth")
          .matching(queryString)
          .createQuery();

        // wrap Lucene query in a javax.persistence.Query
        javax.persistence.Query persistenceQuery = 
            fullTextEntityManager.createFullTextQuery(query, Member.class);

        // execute search
        List<Member> result = (List<Member>)persistenceQuery.getResultList();

        return result;
   }


The following exception is shown when searching for "John", as the QueryBuilder.createQuery fails with ClassCastException:

java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Date
	org.hibernate.search.bridge.builtin.DateBridge.objectToString(DateBridge.java:88)
	org.hibernate.search.bridge.builtin.impl.TwoWayString2FieldBridgeAdaptor.objectToString(TwoWayString2FieldBridgeAdaptor.java:48)
	org.hibernate.search.bridge.util.impl.ContextualExceptionBridgeHelper$TwoWayConversionContextImpl.objectToString(ContextualExceptionBridgeHelper.java:146)
	org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.objectToString(DocumentBuilderIndexedEntity.java:373)
	org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.objectToString(DocumentBuilderIndexedEntity.java:743)
	org.hibernate.search.query.dsl.impl.ConnectedMultiFieldsTermQueryBuilder.buildSearchTerm(ConnectedMultiFieldsTermQueryBuilder.java:141)
	org.hibernate.search.query.dsl.impl.ConnectedMultiFieldsTermQueryBuilder.createQuery(ConnectedMultiFieldsTermQueryBuilder.java:95)
	org.hibernate.search.query.dsl.impl.ConnectedMultiFieldsTermQueryBuilder.createQuery(ConnectedMultiFieldsTermQueryBuilder.java:81)
	org.jboss.tools.examples.service.MemberSearch.search(MemberSearch.java:39)


Also, searching for an empty string or a string that is analysed as an empty query (such as stoplist words "a","an","and",..) will throw a org.hibernate.search.SearchException: Try to search with an empty string: name

The example in the documentation should be fixed to show how to use the QueryBuilder properly.

Comment 1 Marek Schmidt 2012-06-19 12:04:28 UTC
Created attachment 592927 [details]
source code of the example

attaching the example (Java EE Web Project + Hibernate Search pieces from the Hibernate Search docs)

Comment 2 Marek Schmidt 2012-06-19 12:17:19 UTC
Sanne, could you please take a look and check whether this is an actual Hibernate Search bug, or if the example should be fixed and how?

Comment 3 Marek Schmidt 2012-06-19 12:31:58 UTC
(note that you need to uncomment the "dateOfBirth" in the  org.jboss.tools.examples.service.MemberSearch class and change the hibernate.search.default.indexBase property in persistence.xml to reproduce the issue in the attached example)

Comment 4 Sanne Grinovero 2012-06-19 13:22:03 UTC
Marek, great catch. Indeed, the example is wrong.

The expected type of the argument for the matching(V) method should match the fields it's targeting *unless* _ignoreAnalyzer()_ is set as well.

So we have these options to fix the example:

1)
org.apache.lucene.search.Query query = qb
          .keyword()
          .onFields("name", "email")
          .matching(queryString)
          .createQuery();

2)
org.apache.lucene.search.Query query = qb
          .keyword()
          .onFields("name", "email", "dateOfBirth")
          .ignoreAnalyzer()
          .matching(queryString)
          .createQuery();

3) Make the example more complex by specifying a bool() Query using _should_ to provide different options to the String fields and the Date field.

I'd sugges solution 1) as it's simpler, and this is the introduction chapter.
The full boolean syntax is explained already in 5.1.2.6. Combining queries.

Thanks, I'll fix the example in the community docs.

Comment 5 Marek Schmidt 2012-06-20 07:34:07 UTC
Note to Bec, (since my example is a bit different than the exact one in the docs)

the lines

.onFields("title", "subtitle", "authors.name", "publicationDate")

should be changed to

.onFields("title", "subtitle", "authors.name")


in the 1.5. Searching chapter, 
"Example 1.6. Using Hibernate Session to create and execute a search"
and
"Example 1.7. Using JPA to create and execute a search"

Comment 6 lpearce 2012-11-13 01:11:11 UTC
Marek - Those changes should be done now.

Comment 8 Marek Schmidt 2012-11-26 08:43:36 UTC
Verified for WFK 2, Revision 2-0


Note You need to log in before you can comment on or make changes to this bug.