To override the default error handler one can extend the  DCErrorHandlerImpl. In this you can process the exceptions or can choose to suppress them. In this post i will explain a way to suppress the RowValException message and display only the detail entity attribute level exception ie AttrValException.

In ADF the exceptions are grouped and raised together as a single object. For example let's say that 2 of the attributes fail the mandatory validation then the exceptions raised for them will be 2 individual AttrValException these are then attached as detail objects into a RowValException and if there are many such RowValException they will be attached and raised together as a TxnValException.

So now to handle the aforementioned task we need to recursively  process the exceptions and suppress the RowValException message. The snippet below shows that :-

public class MyErrorHandler extends DCErrorHandlerImpl {
    private static final ADFLogger logger = ADFLogger.createADFLogger(VleAdminErrorHandler.class);
    private static ResourceBundle rb = ResourceBundle.getBundle("mypackage.myBundle");
    public MyErrorHandler() {
        super(true);
    }

    public MyErrorHandler(boolean setToThrow) {
        super(setToThrow);
    }

    public void reportException(DCBindingContainer bc, java.lang.Exception ex) {
        disableAppendCodes(ex);
        logger.info("entering reportException() method");
        BindingContext ctx = bc.getBindingContext();
        String err_code;
        err_code = null;
        if(ex instanceof NullPointerException){
              logger.severe(ex); 
              JboException e = new JboException(rb.getString("STANDARD_ERROR_MESSAGE"));
              super.reportException(bc, e);
            }
        else if(ex instanceof RowValException){
          
          Object[] exceptions= ((RowValException)ex).getDetails();
          if(exceptions!=null){
            for(int i=0;i<exceptions.length;i++){
                  if(exceptions[i] instanceof RowValException){
                       this.reportException(bc, (Exception)exceptions[i]);                                 
                  }
                  else if(exceptions[i] instanceof AttrValException){
                super.reportException(bc, (Exception)exceptions[i]);
                  }
              }
          }
            else{
            this.reportException(bc, ex);
            }
            
        }
       else if (ex instanceof TxnValException) {
          Object[] exceptions= ((TxnValException)ex).getDetails();
          if(exceptions!=null){
          for(int i=0;i<exceptions.length;i++){
              if(exceptions[i] instanceof RowValException){
                   this.reportException(bc, (Exception)exceptions[i]);                                 
              }
              else{
            super.reportException(bc, (Exception)exceptions[i]);
              }
          }
          }
          else {
                super.reportException(bc, ex);
              }
        }
      
       else if (ex instanceof oracle.jbo.DMLException) {
           JboException e = new JboException(rb.getString("STANDARD_ERROR_MESSAGE"));
            super.reportException(bc, e);
        }
       else if(ex instanceof javax.xml.ws.WebServiceException){
            JboException e=new JboException(rb.getString("WEB_SERVICE_EXCEPTION"));
            super.reportException(bc, e);
            }
       
        else if (ex instanceof JboException) {
            super.reportException(bc, ex);
        }

    }


    public static FacesMessage getMessageFromBundle(String key, FacesMessage.Severity severity) {
        ResourceBundle bundle = ResourceBundle.getBundle("sahaj.apps.vleadministration.view.resources.VLEAdministrationUIBundle");
        String summary = JSFUtil.getStringSafely(bundle, key, null);
        String detail = JSFUtil.getStringSafely(bundle, key + "_detail", summary);
        FacesMessage message = new FacesMessage(summary, detail);
        message.setSeverity(severity);
        return message;
    }
  private void disableAppendCodes(Exception ex) {
      if (ex instanceof JboException) {
        JboException jboEx = (JboException) ex;
        jboEx.setAppendCodes(false);
        Object[] detailExceptions = jboEx.getDetails();
        if ((detailExceptions != null) && (detailExceptions.length > 0)) {
          for (int z = 0, numEx = detailExceptions.length; z < numEx; z++) {
            disableAppendCodes((Exception) detailExceptions[z]);
          }
        }
      }
  }
  @Override  
    protected boolean skipException(Exception ex) {  
      if (ex instanceof JboException) {  
        return false;  
      } else if (ex instanceof SQLIntegrityConstraintViolationException) {  
        return true;  
      }  
      return super.skipException(ex);  
    }

    @Override
    public String getDisplayMessage(BindingContext bindingContext,
                                    Exception exception) {
        return super.getDisplayMessage(bindingContext, exception);
    }

    @Override
    public DCErrorMessage getDetailedDisplayMessage(BindingContext bindingContext,
                                                    RegionBinding regionBinding,
                                                    Exception exception) {
        
        
    return super.getDetailedDisplayMessage(bindingContext, regionBinding, exception);
    }
} 

In this snippet i am recursively processing TxnValException->RowValException -> AttrValException. The AttrValException is being passed in the super call to the DCErrorHandlerImpl to process and display the message.