Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    How to perform validations before update when overriding SQLDataSource.execute()

    Most of our server side code consists of subclasses of SQLDataSource which override the execute() method. In most cases we code our validations manually and, when the request is an "add" or "update" we call our validation methods and return an appropriate response to the client when any of the validations fail.

    But we've discovered that the "automatic" validations specified in the ds.xml are not being applied automagically. I suppose that is because we are overriding execute() which means we need to call the standard ds.xml coded validations first. The question is, how to do that?

    We are using sparseUpdates in most cases, so to provide a full set of field values to the validators this is what I've done so far.
    Code:
    Map oldAndNew = new HashMap(req.getOldValues());
    oldAndNew.putAll(req.getValues());
    ErrorReport errorReport = super.validate(oldAndNew, true);
    if (!errorReport.isEmpty()) {
    	DSResponse resp = new DSResponse();
    	resp.setErrorReport(errorReport);
    	resp.setStatus(DSResponse.STATUS_VALIDATION_ERROR);
    	return resp;
    }
    The ds.xml in this case includes a few serverCustom validators. Here is an example.
    Code:
    <field name="ISBN" title="ISBN" type="text" length="10" tableName="IPITHDR" canEdit="true" detail="true">
           <validators>  
                  <validator type="serverCustom">  
                      <serverObject lookupStyle="new" className="com.islandpacific.gui.server.customDataSource.ISBNValidatorDMI"/>  
                      <errorMessage>$ErrorMessage</errorMessage>  
                  </validator>  
              </validators>  
    </field>
    After adding the call to super.validate I'm getting this exception which seems to be related to one of the serverCustom validators, but I can't tell which one.
    Code:
    === 2011-02-18 09:32:00,281 [l0-0] WARN  RequestContext - dsRequest.execute() failed: 
    java.lang.NullPointerException
    	at com.isomorphic.util.DefaultValidators$serverCustom.callServerObject(DefaultValidators.java:1131)
    	at com.isomorphic.util.DefaultValidators$serverCustom.validate(DefaultValidators.java:1073)
    	at com.isomorphic.util.DefaultValidators.processValidator(DefaultValidators.java:264)
    	at com.isomorphic.util.DefaultValidators.validateField(DefaultValidators.java:230)
    	at com.isomorphic.datasource.SimpleType.validateValue(SimpleType.java:89)
    	at com.isomorphic.datasource.SimpleType.create(SimpleType.java:65)
    	at com.isomorphic.datasource.BasicDataSource.validateFieldValue(BasicDataSource.java:1046)
    	at com.isomorphic.datasource.BasicDataSource.validateFieldValue(BasicDataSource.java:993)
    	at com.isomorphic.datasource.BasicDataSource.toRecord(BasicDataSource.java:671)
    	at com.isomorphic.datasource.BasicDataSource.toRecords(BasicDataSource.java:586)
    	at com.isomorphic.datasource.DataSource.validate(DataSource.java:1750)
    	at com.islandpacific.gui.server.customDataSource.PoItemDS.execute(PoItemDS.java:452)
    	at com.isomorphic.application.AppBase.executeDefaultDSOperation(AppBase.java:721)
    	at com.isomorphic.application.AppBase.executeAppOperation(AppBase.java:658)
    	at com.isomorphic.application.AppBase.execute(AppBase.java:491)
    	at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:1465)
    	at com.isomorphic.servlet.IDACall.handleDSRequest(IDACall.java:173)
    	at com.islandpacific.gui.server.customDataSource.IpIDACall.handleDSRequest(IpIDACall.java:40)
    	at com.isomorphic.servlet.IDACall.processRPCTransaction(IDACall.java:130)
    	at com.isomorphic.servlet.IDACall.processRequest(IDACall.java:95)
    	at com.isomorphic.servlet.IDACall.doPost(IDACall.java:54)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    	at com.isomorphic.servlet.BaseServlet.service(BaseServlet.java:152)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    	at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
    	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1097)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
    	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    	at com.islandpacific.gui.security.IpConcurrentSessionFilter.doFilter(IpConcurrentSessionFilter.java:55)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
    	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
    	at com.isomorphic.servlet.CompressionFilter.doFilter(CompressionFilter.java:259)
    	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088)
    	at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
    	at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    	at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
    	at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
    	at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
    	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    	at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
    	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    	at org.mortbay.jetty.Server.handle(Server.java:324)
    	at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
    	at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
    	at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
    	at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
    	at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
    	at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
    	at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
    I then tried calling super.validateDSRequest() passing the incoming update DSRequest from the client. That method isn't documented so I'm pretty sure that is not the way to go, but I thought I would give it a try anyway. The call executes but the DSResponse that is returned is null.

    What is the correct way to invoke the standard ds.xml based validations in our server side execute() methods before continuing with our own custom validations and add/update processing?

    #2
    P.S. - I've also tried calling validate() on the incoming DSRequest as well. That returns a null ErrorReport just like the call to super.validateDSRequest(). And in my test I've set up a situation that should be generating an error.

    Comment


      #3
      The best practices tell you to override executeFetch/Update/Add/Remove instead of overriding execute() - if you do so, your code will be running after the built-in validations.

      It does look like we have a bug where a "serverCustom" validator won't work if you call validate(), essentially because we don't have all the information needed to run such a validator (no DSRequest, etc). We'll fix this, but you shouldn't need this method given the above (and we'd need an additional signature to make it work as expected anyway).

      Comment

      Working...
      X