Datastore "checkNotNull" Error

46 views
Skip to first unread message

Kat

unread,
Aug 14, 2017, 4:38:57 PM8/14/17
to Google App Engine
I AM LOSING MY F***ING MIND OVER THIS.

For over a year now I've been learning web development using Google Cloud Platform and studying online resources. I've gone through an excruciating amount of trial and error over the past year, but no matter what formidable brick wall I ran into, I always managed to find a solution without making any new forum posts or asking for help. But this is just killing me.

I am trying to get a basic user login system set up for a basic website. Right now I am not worrying too much about security, I am just trying to lay the foundation for a custom user database that I can use for authorization on this site. For the sake of simplicity and understanding in the beginning stages of building this auth system, I have based my user entity creation template on the same template that I'm using for the creation of posts, albums, and photos, a template found in the Java Bookshelf App tutorial. My application has no problem creating post, album, and photo entities, and since my user entity is created with the same exact template as those entities, I DO NOT UNDERSTAND WHY IT IS NOT WORKING!!!

I am using Datastore on App Engine Java using JSPs and Servlets. My project is built with Maven, and my local development server is run with Jetty.

My JSP signup form:

<form method="POST" action="${destination}" enctype="multipart/form-data">
        
            <div class="form-group">
                <label for="email">Email</label>
                <input class="form-control" type="text" id="email" name="email" placeholder="Email"/>
            </div>
            <div class="form-group">
                <label for="password">Password</label>
                <input class="form-control" type="password" id="password" name="password" placeholder="Password"/>
            </div>
            <div class="form-group">
                <label for="username">Display Name</label>
                <input class="form-control" type="text" id="username" name="username" placeholder="Display Name"/>
            </div>
            <div class="form-group">
                <label for="file">Profile Image</label>
                <input class="form-control" type="file" id="file" name="file"/>
            </div>

            <div class="form-group hidden">
                <label for="imageUrl">Image URL</label>
                <input type="text" name="imageUrl" id="imageUrl" value="${fn:escapeXml(imageUrl)}" class="form-control" />
            </div>
            
            <br/><br/>
        
<button class="btn" type="submit" id="signup" name="signup">Sign Up</button>
        
        </form>

...which submits a POST request to my signup servlet:

public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
     IOException {

         String state = new BigInteger(130, new SecureRandom()).toString(32); // prevent request forgery
         req.getSession().setAttribute("state", state);

         if (req.getAttribute("loginDestination") != null) {
         req
         .getSession()
         .setAttribute("loginDestination", (String) req.getAttribute("loginDestination"));
         logger.log(
         Level.INFO, "logging destination " + (String) req.getAttribute("loginDestination"));
         } else {
         req.getSession().setAttribute("loginDestination", "/Home");
         logger.log(Level.INFO, "logging destination /Home");
         }
        
         CloudStorageHelper storageHelper =
         (CloudStorageHelper) req.getServletContext().getAttribute("storageHelper");
         String imageUrl =
         storageHelper.getImageUrl(
         req, resp, getServletContext().getInitParameter("skelly.bucket"));
        
            UserDao dao = (UserDao) this.getServletContext().getAttribute("userDao");
            
            byte[] salt = new SecureRandom().generateSeed(32);
            byte[] hash = hashPassword(req.getParameter("password").toCharArray(), salt, 27, 256);
            String saltS = salt.toString();
            String hashS = hash.toString();
            String email = req.getParameter("email");

            User user = new User.Builder()
                .email(email)
                .hash(hashS)
                .salt(saltS)
                .imageUrl(imageUrl)
                .build();

            try {
                dao.createUser(user);

                byte[] key = (byte[]) req.getSession().getAttribute("state");
                Date date = new Date();
                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.add(Calendar.HOUR, 12);
                Date exp = cal.getTime();
                String iss = req.getScheme() + "://" +
                            req.getServerName() + ":" +
                            req.getServerPort();
                String sub = (String) req.getAttribute("email");            
        
                String jwt =
                    Jwts.builder().setIssuer(iss)
                        .setSubject(sub)
                        .setExpiration(exp)
                        .claim("scope", "self api/buy")
                        .signWith(SignatureAlgorithm.HS256, key)
                        .compact();

                req.getSession().setAttribute("token", jwt);
                req.getSession().setAttribute("userEmail", req.getParameter("email"));
                req.getSession().setAttribute("userImage", imageUrl);
                resp.sendRedirect("/Home");
            } catch(Exception e) {
                throw new ServletException(e.getMessage(), e);
            }

     }

...which calls the createUser() method in my UserDatastore servlet:

public Long createUser(User user) throws SQLException, IOException {

        IncompleteKey key = keyFactory.newKey(); // Key will be assigned once written
        FullEntity<IncompleteKey> incUserEntity = Entity.newBuilder(key) // Create the Entity
     .set(User.EMAIL, user.getEmail())
     .set(User.SALT, user.getSalt())
            .set(User.HASH, user.getHash())
            .set(User.IMAGE_URL, user.getImageUrl())

            .build(); // <---- THIS IS WHERE THE ERROR OCCURS!!! \\

        Entity userEntity = datastore.add(incUserEntity); // Save the Entity
        return userEntity.getKey().getId();
    }

...which leads to this 500 Server Error:

HTTP ERROR 500

Problem accessing /SignupEmail. Reason:

    Server Error

Caused by:

javax.servlet.ServletException: javax.servlet.ServletException
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:138)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.Server.handle(Server.java:564)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
	at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:122)
	at org.eclipse.jetty.util.thread.strategy.ExecutingExecutionStrategy.invoke(ExecutingExecutionStrategy.java:58)
	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:201)
	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:133)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
	at java.lang.Thread.run(Thread.java:748)
Caused by: javax.servlet.ServletException
	at com.example.getstarted.auth.SignupEmail.doPost(SignupEmail.java:137)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1634)
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:206)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1621)
	at com.example.getstarted.util.DatastoreSessionFilter.doFilter(DatastoreSessionFilter.java:109)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1613)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:541)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1593)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1239)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:481)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1562)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1141)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:118)
	... 14 more
Caused by: java.lang.NullPointerException
	at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:770)
	at com.google.common.collect.NaturalOrdering.compare(NaturalOrdering.java:36)
	at com.google.common.collect.NaturalOrdering.compare(NaturalOrdering.java:25)
	at com.google.common.collect.ByFunctionOrdering.compare(ByFunctionOrdering.java:43)
	at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
	at java.util.TimSort.sort(TimSort.java:220)
	at java.util.Arrays.sort(Arrays.java:1512)
	at com.google.common.collect.ImmutableSortedMap.fromEntries(ImmutableSortedMap.java:390)
	at com.google.common.collect.ImmutableSortedMap.fromEntries(ImmutableSortedMap.java:362)
	at com.google.common.collect.ImmutableSortedMap.copyOfInternal(ImmutableSortedMap.java:346)
	at com.google.common.collect.ImmutableSortedMap.copyOf(ImmutableSortedMap.java:237)
	at com.google.cloud.datastore.BaseEntity.<init>(BaseEntity.java:458)
	at com.google.cloud.datastore.FullEntity.<init>(FullEntity.java:47)
	at com.google.cloud.datastore.FullEntity$Builder.build(FullEntity.java:42)
	at com.example.getstarted.daos.UserDatastore.createUser(UserDatastore.java:115)
	at com.example.getstarted.auth.SignupEmail.doPost(SignupEmail.java:111)
	... 38 more

Normally I am able to diagnose the problem by looking at the errors, locating the problem, researching the problem, and finding a solution. But this error is different than anything I have ever experienced for several reasons:

1. It is a NullPointerException, but through testing I have not been able to find where there is a null value.

2. It is thrown by the method checkNotNull which I have found little discussions about, none of which helped me understand my specific dilemma.

3. The method that is throwing this error (createUser) is nearly IDENTICAL to my other methods (createPost, createAlbum, createPhoto) that work just fine, so this method should be working as well.

I have jumped dozens of complicated troubleshooting hurdles in the past year, but I'm completely stumped on this one. I cannot find any reason whatsoever that this error is being thrown.

Kenworth (Google Cloud Platform)

unread,
Aug 14, 2017, 10:15:32 PM8/14/17
to google-a...@googlegroups.com

A thread like this is off-topic for Google Groups, and should be posted to StackOverflow. While I'd like to help you, this isn't the place to do it. This forum isn't meant for specific 1-on-1 technical issues, but for general discussion of the platform and its services. With StackOverflow, which we also monitor, you'll be in touch with a much larger user-base of people who are going to help you, and in a format which is designed for that purpose. Check out our community support page for the list of tags we monitor.


I also recommend you take a look on Google’s User Authentication Options that will simplify your application’s login flow. The Users API, for example, uses App Engine's built-in Users API service to authenticate Google and Google Apps accounts.


Good luck and happy coding.



Reply all
Reply to author
Forward
0 new messages