0

I have created a custom constraint validator which I am using to check validation on a username, the validator is accessing a database and checking if the record already exists and if it complies with a regex. I am getting rather strange error as the validator is working correctly if the username already exists, however when entering a valid input (a username that doesn't exist) It is throwing a NullPointerException.

I have placed a counter and some statements to let me track where the application is crashing which I will include in the stack trace. The application seems to be calling the initialise and isValid method twice, the second time around it is throwing a NullPointer. I have looked at this question which says to add <property name="javax.persistence.validation.mode" value="none"/> to my persistence.xml file, which I have done and has made no change.

I am thinking that maybe I have to disable this somewhere else as I have not used my persistence.xml to configure the application, instead using a jpaContext.xml file.

If anyone has any advise/prior experience on hoot fix/where I should be looking to find a fix I would appreciate it.

custom constraint validator

public class UserNameConstraintValidator implements ConstraintValidator<UserName, String> {
@Autowired
private HouseholdService householdService;

private int counter = 0;


public void initialize(UserName userName) {
    System.out.println("counter inside initialize is at count : " + counter);
}

public boolean isValid(String userName, ConstraintValidatorContext cxt) {
    System.out.println(userName);
    counter ++;
    System.out.println("counter is at count : " + counter);

    if(householdService.checkForUser(userName) || userName == null) {      //line 26
        System.out.println(userName);
        System.out.println("counter inside if statement is at count : " + counter);
        return false;
    }
    else {
        System.out.println(userName);
        System.out.println("counter inside else statement is at count : " + counter);
        return (userName.matches("^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$"));
    }
}
}

StackTrace

        counter inside initialize is at count : 0
        newUser
        counter is at count : 1
        Tue Mar 28 19:18:23 BST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
        Mar 28, 2017 7:18:23 PM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
        INFO: HHH000397: Using ASTQueryTranslatorFactory
        Hibernate: select household0_.id as id1_1_, household0_.password as password2_1_, household0_.userName as userName3_1_ from Households household0_ where household0_.userName like ? limit ?
        Hibernate: select household0_.id as id1_1_, household0_.password as password2_1_, household0_.userName as userName3_1_ from Households household0_ where household0_.userName like ? limit ?
        inside HouseholdRepository, if statement has returned : 0
        newUser
        counter inside else statement is at count : 1
        Tue Mar 28 19:18:24 BST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
        Tue Mar 28 19:18:24 BST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
        Hibernate: select next_val as id_val from hibernate_sequence for update
        Hibernate: update hibernate_sequence set next_val= ? where next_val=?
        counter inside initialize is at count : 0
        newUser
        counter is at count : 1
        Mar 28, 2017 7:18:24 PM org.apache.catalina.core.StandardWrapperValve invoke
        SEVERE: Servlet.service() for servlet [springDispatcherServlet] in context with path [/Bill_Calculator] threw exception [Request processing failed; nested exception is javax.validation.ValidationException: HV000028: Unexpected exception during isValid call.] with root cause
        java.lang.NullPointerException
            at com.chrishammer.view.UserNameConstraintValidator.isValid(UserNameConstraintValidator.java:26)
            at com.chrishammer.view.UserNameConstraintValidator.isValid(UserNameConstraintValidator.java:1)
            at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:446)
            at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:127)
            at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:87)
            at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:73)
            at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:616)
            at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:581)
            at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:527)
            at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:495)
            at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:460)
            at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:410)
            at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:207)
            at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:116)
            at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:80)
            at org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:205)
            at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:82)
            at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:586)
            at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:460)
            at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
            at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
            at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1428)
            at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1414)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298)
            at com.sun.proxy.$Proxy36.flush(Unknown Source)
            at com.chrishammer.repository.HouseholdRepositoryImpl.save(HouseholdRepositoryImpl.java:23)
            at com.chrishammer.service.HouseholdServiceImpl.save(HouseholdServiceImpl.java:24)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
            at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
            at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
            at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
            at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
            at com.sun.proxy.$Proxy41.save(Unknown Source)
            at com.chrishammer.controller.CreateAccountController.submitUser(CreateAccountController.java:34)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
            at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
            at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
            at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
            at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
            at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
            at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
            at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
            at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
            at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
            at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
            at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
            at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
            at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
            at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:495)
            at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
            at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:767)
            at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1347)
            at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
            at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
            at java.lang.Thread.run(Thread.java:745)

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_2_0.xsd"
            version ="2.0" >


<persistence-unit name="punit">
    <property name="javax.persistence.validation.mode" value="none"/>
</persistence-unit>             



</persistence>

jpaContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

<context:annotation-config />
<context:component-scan base-package="com.chrishammer" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />


<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="punit" />
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
        </bean>
    </property>
    <property name ="jpaPropertyMap">
        <map>
            <entry key="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
            <entry key="hibernate.hbm2ddl.auto" value="update" />
            <entry key="hivernate.format_sql" value="true" />
        </map>
    </property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<tx:annotation-driven />

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/testingDb?autoReconnect=true" />
    <property name="username" value="root" />
    <property name="password" value="root" />
</bean>
</beans>

If you need anything else let me know, any help would be much appreciated.

Community
  • 1
  • 1
Chris
  • 103
  • 3
  • 15
  • What is line 26? That's where the NPE is happening. – Christopher Schneider Mar 28 '17 at 18:27
  • line 26 is the if statement which checks to see if the user exists. The user name is passed in the first time, but for some reason it is being called twice and the second time it throws the exception. I will edit the line number in. – Chris Mar 28 '17 at 18:34
  • Does not help to resolve your issue, but you should add the Override annotation to `isValid`. Do you call this `isValid` manually? – Stefan Freitag Mar 28 '17 at 18:44
  • no I don't the documentation states, it is "a method that is guaranteed to be called before any use of this instance for validation." – Chris Mar 28 '17 at 18:52
  • the only way to get an NPE at that line is when `householdService` is null, it seems like it's executing different instances of the validator, one instantiated by Spring and the other somewhere else – jorgegm Mar 28 '17 at 19:06

1 Answers1

0

I have fixed this issue. While looking through the documents on hibernate bean validation found here, I noticed that the <property> tag in the persistence.xml file was surrounded by a <properties> tag. Simply adding this to my persistence.xml file solved my issue.

Chris
  • 103
  • 3
  • 15