Search code examples
javaspringstack-overflow

hashCode() causes java.lang.StackOverflowError


I've a form in which I've

<form:form method="post" commandName="post" htmlEscape="false">
    <form:input cssClass="input-field" path="postTitle" placeholder="Post title"/>            
    <form:textarea id="editor" placeholder="Post" path="postBody"/>
    <input type="hidden" id="tagQuery" type="text" placeholder="tags" class="input-field"/><br> 
    <ul id="mytags"></ul><br><br>          
    <form:select style="visibility : hidden;" id="tags" path="tags">
    </form:select>
    <input type="submit" value="Save Post"/>    
</form:form>

I get tags using tagit lib, as I have configured it

select = document.querySelector("select[name='tags']");    
jQuery(document).ready(function() {
    jQuery("#mytags").tagit({
        singleField: true,
        singleFieldNode: $('#tagQuery'),
        allowSpaces: true,
        minLength: 2,
        removeConfirmation: true,
        tagSource: function( request, response ) {
            //console.log("1");
             $.getJSON("/app/getTags", request, function(result) {
                response($.map(result, function(item) {
                    return {
                        // following property gets displayed in drop down
                        label: item.tagTitle,
                        // following property gets entered in the textbox
                        value: item.tagTitle,
                        // following property is added for our own use
                        tag_url: "http://" + window.location.host + "/" + item.tagId + "/" + item.tagTitle
                    }
                }));
            });              
        },
        afterTagAdded : function(event, ui) {
             var option = document.createElement("option");
      console.log(ui);
      console.log(idValue);
                option.value = ui.tagLabel;
                option.text =  ui.tagLabel;
                option.selected = 'selected';
                select.appendChild(option);
        },
        afterTagRemoved : function(event, ui) {
            select.removeChild(select.querySelector('[value="'+ui.tagLabel+'"]'));
        }
        });
    });

and finally I have Controller stuff as

public class PostController {

    @Autowired
    private BlogService serviceImplementation;

    @ModelAttribute("post")
    public Post constructPost() {
        return new Post();
    }
    @ModelAttribute("tag")
    public Tag constructTag() {
        return new Tag();
    }

    @InitBinder
    public void initBinderOne(WebDataBinder binder) {
        binder.registerCustomEditor(Tag.class,
                new PropertyEditorSupport() {
                    @Override
                    public void setAsText(String text) {
                        Tag tag = serviceImplementation.getTagById(Long
                                .parseLong(text));
                        setValue(tag);
                    }
                });     
    }           

    @RequestMapping(value = "/new", method = RequestMethod.GET)
    public String createPost(Model model) {     
        return "new-post";
    }

    @RequestMapping(value = "/new", method = RequestMethod.POST)
    public String savePost(Model model, @ModelAttribute("post") Post post) {

        serviceImplementation.savePost(post);
        return "redirect:/";
    }
}

when I save a post I get error

the request sent by the client was syntactically incorrect

I figured out that happens when ever I save post it sends tags as

option.value = ui.tagLabel;
option.text =  ui.tagLabel;
option.selected = 'selected';
select.appendChild(option);

this sets suppose value as ui.tagLabel, as

<option value="Android">Android</option>

I was changing

select = document.querySelector("select[name='tags']");
var idValue; //HERE I ADDED var to get 
jQuery(document).ready(function() {
    jQuery("#mytags").tagit({
        singleField: true,
        singleFieldNode: $('#tagQuery'),
        allowSpaces: true,
        minLength: 2,
        removeConfirmation: true,
        tagSource: function( request, response ) {
            //console.log("1");
             $.getJSON("/app/getTags", request, function(result) {
                response($.map(result, function(item) {
                    idValue = item.tagId; // HERE I ADDED var to get id to set as value in option *
                    return {
                        // following property gets displayed in drop down
                        label: item.tagTitle,
                        // following property gets entered in the textbox
                        value: item.tagTitle,
                        // following property is added for our own use
                        tag_url: "http://" + window.location.host + "/" + item.tagId + "/" + item.tagTitle
                    }
                }));
            });              
        },
        afterTagAdded : function(event, ui) {
             var option = document.createElement("option");
      console.log(ui);
      console.log(idValue);
                option.value = idValue;//HERE When I add idValue to option I always get the id of last tag, let say there are 6 tags in ajax response, idValue is always 6. 
                option.text =  ui.tagLabel;
                option.selected = 'selected';
                select.appendChild(option);
        },
        afterTagRemoved : function(event, ui) {
            select.removeChild(select.querySelector('[value="'+ui.tagLabel+'"]'));
        }
        });
    });

then set the ajax respose settings to prior script

 option.value = ui.tagLabel;
 option.text =  ui.tagLabel;
 option.selected = 'selected';
 select.appendChild(option);

and I changed initBinder()

@InitBinder
    public void initBinderOne(WebDataBinder binder) {
        binder.registerCustomEditor(Tag.class,
                new PropertyEditorSupport() {
                    @Override
                    public void setAsText(String text) {                            
                        Tag tag = serviceImplementation.getTagByName(text);
                        setValue(tag);
                    }
                });     
    }       

and

public Tag getTagByName(String tagTitle) {
        // TODO Auto-generated method stub
        return em.createQuery("from Tag t where t.tagTitle = :tagTitle", Tag.class)
                .setParameter("tagTitle", tagTitle).getSingleResult();
    }

at this point I get a endless stack trace some lines are...

HTTP Status 500 - Handler processing failed; nested exception is java.lang.StackOverflowError

type Exception report

message Handler processing failed; nested exception is java.lang.StackOverflowError

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.StackOverflowError
    org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1303)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:977)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause

java.lang.StackOverflowError
    java.nio.CharBuffer.<init>(Unknown Source)
    java.nio.HeapCharBuffer.<init>(Unknown Source)
    java.nio.CharBuffer.wrap(Unknown Source)
    sun.nio.cs.StreamEncoder.implWrite(Unknown Source)
    sun.nio.cs.StreamEncoder.write(Unknown Source)
    java.io.OutputStreamWriter.write(Unknown Source)
    java.io.BufferedWriter.flushBuffer(Unknown Source)
    java.io.PrintStream.write(Unknown Source)
    java.io.PrintStream.print(Unknown Source)
    java.io.PrintStream.println(Unknown Source)
    org.apache.tomcat.util.log.SystemLogHandler.println(SystemLogHandler.java:264)
    org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:111)
    org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:94)
    org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:181)
    org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:160)
    org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.prepareQueryStatement(AbstractLoadPlanBasedLoader.java:257)
    org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeQueryStatement(AbstractLoadPlanBasedLoader.java:201)
    org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:137)
    org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)
    org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:100)
    org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:693)
    org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:92)
    org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1897)
    org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:558)
    org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:260)
    org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
    org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
    org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:447)
    com.rhcloud.app.entity.Tag.hashCode(Tag.java:77)
    java.util.HashMap.put(Unknown Source)
    java.util.HashSet.add(Unknown Source)
    java.util.AbstractCollection.addAll(Unknown Source)
    org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:344)
    org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:251)
    org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:238)
    org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:211)
    org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:168)
    org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:255)
    org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:218)
    org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:140)
    org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:138)
    org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)
    org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:100)
    org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:693)
    org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:92)
    org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1897)
    org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:558)
    org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:260)
    org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
    org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
    org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:447)
    com.rhcloud.app.entity.Post.hashCode(Post.java:92)
    java.util.HashMap.put(Unknown Source)
    java.util.HashSet.add(Unknown Source)
    java.util.AbstractCollection.addAll(Unknown Source)
    org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:344)
    org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:251)
    org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:238)
    org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:211)
    org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:168)
    org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:255)
    org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:218)
    org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:140)
    org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:138)
    org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)
    org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:100)
    org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:693)
    org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:92)
    org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1897)
    org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:558)
    org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:260)
    org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
    org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)

I want to figure out why this hashCode() causes java.lang.StackOverflowError in my Spring Web App Post hashCode() is

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((postBody == null) ? 0 : postBody.hashCode());
        result = prime * result + ((postId == null) ? 0 : postId.hashCode());
        result = prime * result
                + ((postTitle == null) ? 0 : postTitle.hashCode());
        result = prime * result + ((tags == null) ? 0 : tags.hashCode());
        return result;
    }

Tags hashCode() is

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((posts == null) ? 0 : posts.hashCode());
        result = prime * result
                + ((tagDescription == null) ? 0 : tagDescription.hashCode());
        result = prime * result + ((tagId == null) ? 0 : tagId.hashCode());
        result = prime * result
                + ((tagTitle == null) ? 0 : tagTitle.hashCode());
        return result;
    }

Solution

  • posts.hashCode() calls tags.hashCode(), which calls posts.hashCode(), etc ....

    You seem to have an infinite loop there.