def get_application(appn_id):
    cursor = connect(cursor_factory=psycopg2.extras.DictCursor)

    # locked = lock_application(cursor, appn_id)
    # if locked is None:
    #     # Selected application already locked or no longer on work list
    #     complete(cursor)
    #     return Response(status=404)
    # else:
    try:
        logging.audit("Retrieve application")
        appn = get_application_by_id(cursor, appn_id)
    finally:
        complete(cursor)

    return Response(json.dumps(appn), status=200, mimetype='application/json')
def update_application(appn_id):
    # TODO: validate
    action = 'store'
    if 'action' in request.args:
        action = request.args['action']

    logging.debug(request.headers)

    data = request.get_json(force=True)
    cursor = connect(cursor_factory=psycopg2.extras.DictCursor)
    # store fee info for later use. Quick fix because of data structure in rectifications
    if 'fee_details' in data:
        fee_ind = True
        fee_details = data['fee_details']
    else:
        fee_ind = False
        fee_details = {}

    try:
        if action == 'store':
            logging.info(format_message("Store application"))
            logging.audit(format_message("Store application"))
            # logging.debug(data)
            # update_application_details(cursor, appn_id, data)
            store_application(cursor, appn_id, data)
            appn = get_application_by_id(cursor, appn_id)
        elif action == 'complete':
            logging.info(format_message("Complete registration"))
            logging.audit(format_message("Complete application"))
            appn = complete_application(cursor, appn_id, data)
        elif action == 'amend' or action == 'rectify':
            logging.info(format_message("Complete update"))
            logging.audit(format_message("Complete update application"))
            appn = amend_application(cursor, appn_id, data)
        elif action == 'cancel':
            logging.info(format_message("Complete cancellation"))
            logging.audit(format_message("Complete cancellation application"))
            appn = cancel_application(cursor, appn_id, data)
        elif action == 'renewal':
            logging.info(format_message("Complete renewal"))
            logging.audit(format_message("Complete renewal application"))
            appn = renew_application(cursor, appn_id, data)
        elif action == 'correction':
            logging.info(format_message("Complete correction"))
            logging.audit(format_message("Complete correction"))
            appn = correct_application(cursor, data)
        else:
            return Response("Invalid action", status=400)
        # sort out the fee
        # everything but searches
        if fee_ind is True:
            logging.debug("fee selected" + json.dumps(fee_details))
            if fee_details['type'] == 'wf' or  fee_details['type'] == 'nf':
                save_request_fee(str(appn['request_id']), str(0))
            else:
                # build the fee details to pass to legacy_adapter
                build_fee_data(data, appn, fee_details, action)
        complete(cursor)
        status = 200
    except ValidationError as e:
        rollback(cursor)
        error_str = str(e)
        error_dict = json.loads(error_str[1:-1])  # Exception seems to add quotes, annoyingly
        appn = {"ValidationError": error_dict}
        status = 400
    except:
        rollback(cursor)
        raise
    return Response(json.dumps(appn), status=status)