The UserOcppController does not gracefully handle DB data validation constraints, causing system alerts from the uncaught exception ERROR log messages. For example the saveChargePoint method which generates exceptions like this:
[2022-07-18 09:51:42.363] ERROR [http-nio-9081-exec-4422 ] n.s.c.w.s.WebServiceControllerSupport DataIntegrityViolationException in request uri=/solaruser/api/v1/sec/user/ocpp/chargers?: org.springframework.dao.DataIntegrityViolationException: ### Error updating database. Cause: org.postgresql.util.PSQLException: ERROR: null value in column "model" violates not-null constraint ### The error may exist in URL [jar:file:/workspace/WEB-INF/lib/solarnet-ocpp-1.0.0.jar!/net/solarnetwork/central/ocpp/dao/mybatis/map/CentralChargePoint.xml] ### The error may involve net.solarnetwork.central.ocpp.domain.CentralChargePoint.insert-CentralChargePoint-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO solarev.ocpp_charge_point ( id , user_id , node_id , enabled , reg_status , conn_count , ident , vendor , model , serial_num , box_serial_num , fw_vers , iccid , imsi , meter_type , meter_serial_num ) VALUES ( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ) ### Cause: org.postgresql.util.PSQLException: ERROR: null value in column "model" violates not-null constraint ; ERROR: null value in column "model" violates not-null constraint [2022-07-18 09:51:42.465] WARN [http-nio-9081-exec-4422 ] n.s.c.w.s.WebServiceControllerSupport Root SQLException from ### Error updating database. Cause: org.postgresql.util.PSQLException: ERROR: null value in column "model" violates not-null constraint ### The error may exist in URL [jar:file:/workspace/WEB-INF/lib/solarnet-ocpp-1.0.0.jar!/net/solarnetwork/central/ocpp/dao/mybatis/map/CentralChargePoint.xml] ### The error may involve net.solarnetwork.central.ocpp.domain.CentralChargePoint.insert-CentralChargePoint-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO solarev.ocpp_charge_point ( id , user_id , node_id , enabled , reg_status , conn_count , ident , vendor , model , serial_num , box_serial_num , fw_vers , iccid , imsi , meter_type , meter_serial_num ) VALUES ( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ) ### Cause: org.postgresql.util.PSQLException: ERROR: null value in column "model" violates not-null constraint ; ERROR: null value in column "model" violates not-null constraint org.postgresql.util.PSQLException: ERROR: null value in column "model" violates not-null constraint at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675) ~[postgresql-42.3.3.jar:42.3.3] at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365) ~[postgresql-42.3.3.jar:42.3.3] at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:355) ~[postgresql-42.3.3.jar:42.3.3] at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:490) ~[postgresql-42.3.3.jar:42.3.3] at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:408) ~[postgresql-42.3.3.jar:42.3.3] at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:166) ~[postgresql-42.3.3.jar:42.3.3] at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:155) ~[postgresql-42.3.3.jar:42.3.3] at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44) ~[HikariCP-4.0.3.jar:na] at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java) ~[HikariCP-4.0.3.jar:na] at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:47) ~[mybatis-3.5.7.jar:3.5.7] at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74) ~[mybatis-3.5.7.jar:3.5.7] at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50) ~[mybatis-3.5.7.jar:3.5.7] at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) ~[mybatis-3.5.7.jar:3.5.7] at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) ~[mybatis-3.5.7.jar:3.5.7] at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:194) ~[mybatis-3.5.7.jar:3.5.7] at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:181) ~[mybatis-3.5.7.jar:3.5.7] at jdk.internal.reflect.GeneratedMethodAccessor192.invoke(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na] at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427) ~[mybatis-spring-2.0.6.jar:2.0.6] at com.sun.proxy.$Proxy89.insert(Unknown Source) ~[na:na] at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:272) ~[mybatis-spring-2.0.6.jar:2.0.6] at net.solarnetwork.central.dao.mybatis.support.BaseMyBatisGenericDaoSupport.handleInsert(BaseMyBatisGenericDaoSupport.java:292) ~[solarnet-common-1.3.5.jar:1.3.5] at net.solarnetwork.central.dao.mybatis.support.BaseMyBatisGenericDaoSupport.save(BaseMyBatisGenericDaoSupport.java:163) ~[solarnet-common-1.3.5.jar:1.3.5] at net.solarnetwork.central.dao.mybatis.support.BaseMyBatisGenericDaoSupport$$FastClassBySpringCGLIB$$9036fad1.invoke(<generated>) ~[solarnet-common-1.3.5.jar:1.3.5] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.16.jar:5.3.16] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.16.jar:5.3.16] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.16.jar:5.3.16] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) ~[spring-aop-5.3.16.jar:5.3.16] at net.solarnetwork.central.ocpp.dao.mybatis.MyBatisCentralChargePointDao$$EnhancerBySpringCGLIB$$50261e0f.save(<generated>) ~[solarnet-ocpp-1.0.0.jar:1.0.0] at net.solarnetwork.central.user.ocpp.biz.dao.DaoUserOcppBiz.saveChargePoint(DaoUserOcppBiz.java:246) ~[solarnet-user-ocpp-1.0.0.jar:1.0.0] at net.solarnetwork.central.user.ocpp.biz.dao.DaoUserOcppBiz$$FastClassBySpringCGLIB$$a5319b19.invoke(<generated>) ~[solarnet-user-ocpp-1.0.0.jar:1.0.0] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:58) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:58) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.16.jar:5.3.16] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.16.jar:5.3.16] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.16.jar:5.3.16] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.16.jar:5.3.16] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) ~[spring-aop-5.3.16.jar:5.3.16] at net.solarnetwork.central.user.ocpp.biz.dao.DaoUserOcppBiz$$EnhancerBySpringCGLIB$$16f122b5.saveChargePoint(<generated>) ~[solarnet-user-ocpp-1.0.0.jar:1.0.0] at net.solarnetwork.central.reg.web.api.v1.UserOcppController.saveChargePoint(UserOcppController.java:182) ~[classes/:na]