Blog SAPienteSAPiente
RAP

Auxiliary Class no RAP

SAPiente10 de jul. de 2026· 7 min read

O problema: lógica repetida entre behavior pools

Seu BO cresceu. A entidade raiz tem um behavior pool, as filhas têm os seus, e espalhados por eles há uma validation que checa consistência de crédito, um determination que recalcula o mesmo total e uma action que precisa da mesmíssima verificação. Três lugares, uma regra — o instinto de qualquer desenvolvedor é fatorar isso numa classe comum e chamar de todos os pontos.

Aí você cria a ZCL_CREDIT_HELPER, um método estático, e tenta ler o buffer do BO lá de dentro:

METHOD check_credit.
  " dentro de uma classe ABAP comum:
  READ ENTITIES OF ZI_SalesOrder IN LOCAL MODE 
    ENTITY SalesOrder FIELDS ( CreditProfile ) WITH CORRESPONDING #( keys )
    RESULT DATA(orders).
ENDMETHOD.

E toma o erro: IN LOCAL MODE não é permitido fora de uma classe habilitada para o RAP BO. A adição IN LOCAL MODE — que pula verificações de feature/autorização ao acessar o próprio BO — é um direito privilegiado, e uma classe ABAP qualquer não o tem. A lógica pode até ser movida para lá se você passar tudo por parâmetro, mas no instante em que ela precisa tocar o buffer do BO, a classe comum trava.

É exatamente esse buraco que a ABP auxiliary class preenche.

O que é uma auxiliary class

Uma auxiliary class é uma classe global que você declara na BDEF e que passa a ter direitos de acesso privilegiados ao RAP BO — os mesmos direitos de um behavior pool. A definição da documentação é enxuta: são classes que fornecem métodos reutilizáveis para implementar comportamentos, permitindo terceirizar funcionalidade e simplificar o trabalho concorrente (times mexendo no mesmo BO sem colidir num único pool gigante). E o ponto central: elas oferecem direitos de acesso ampliados ao BO referenciado, o que significa que você pode usar IN LOCAL MODE e PRIVILEGED nas EML lá dentro.

Duas características técnicas que a doc crava:

  • São implicitamente FINAL e globais — e referenciam um RAP business object via FOR BEHAVIOR OF.

  • Só podem ser instanciadas ou invocadas pelo ambiente de runtime ABAP (a VM) — como os behavior pools, você não faz NEW nelas a partir de código arbitrário.

Auxiliary class × behavior pool, em uma linha: o behavior pool é onde os métodos handler/saver vivem (é lá que FOR MODIFY, FOR VALIDATE, save etc. são implementados — e só lá). A auxiliary class é onde a lógica reutilizável mora, para os pools delegarem tarefas a ela. Handler e saver não podem ser implementados numa auxiliary class; mas podem chamá-la à vontade.

Como declarar e implementar

1. Registrar na BDEF

No header da behavior definition, após a implementação, você lista a(s) auxiliary class(es) com auxiliary class ... unique. Pode declarar uma ou várias, em lista separada por vírgula:

managed implementation in class zbp_i_salesorder unique;
auxiliary class zcl_salesorder_aux unique;   // <- a auxiliary class
strict ( 2 );

define behavior for ZI_SalesOrder alias SalesOrder
persistent table zsalesorder
lock master
authorization master ( instance )
{
  create;
  update;
  delete;

  validation validateCredit on save { create; field CreditProfile; }
  determination calcTotals    on modify { create; }
  action       reevaluate     result [1] $self;
}

2. A classe global

A classe usa a adição FOR BEHAVIOR OF <bdef> — a mesma família do FOR BEHAVIOR OF do behavior pool. Ela nasce praticamente vazia; os métodos reutilizáveis são seus, com a assinatura que você quiser:

CLASS zcl_salesorder_aux DEFINITION
  PUBLIC ABSTRACT FINAL
  FOR BEHAVIOR OF ZI_SalesOrder.

  PUBLIC SECTION.
    " método reutilizável: recebe chaves, devolve os inválidos
    CLASS-METHODS get_invalid_credit
      IMPORTING keys          TYPE TABLE FOR VALIDATION ZI_SalesOrder~validateCredit
      RETURNING VALUE(result) TYPE tt_invalid_keys.
ENDCLASS.

CLASS zcl_salesorder_aux IMPLEMENTATION.
  METHOD get_invalid_credit.
    " IN LOCAL MODE funciona aqui
    READ ENTITIES OF ZI_SalesOrder IN LOCAL MODE
      ENTITY SalesOrder FIELDS ( CreditProfile SoldToParty )
        WITH CORRESPONDING #( keys )
      RESULT DATA(orders).

    result = VALUE #( FOR o IN orders
                      WHERE ( CreditProfile IS INITIAL )
                      ( %tky = o-%tky ) ).
  ENDMETHOD.
ENDCLASS.

3. Delegar do behavior pool

Agora os métodos handler — em qualquer pool do BO — chamam a auxiliary class em vez de repetir a lógica:

METHOD validateCredit.        " no behavior pool
  DATA(invalid) = zcl_salesorder_aux=>get_invalid_credit( keys ).
  LOOP AT invalid INTO DATA(bad).
    APPEND VALUE #( %tky = bad-%tky ) TO failed-salesorder.
    APPEND VALUE #( %tky = bad-%tky
                    %msg = new_message_with_text(
                             severity = if_abap_behv_message=>severity-error
                             text     = 'Perfil de crédito inválido' ) )
           TO reported-salesorder.
  ENDLOOP.
ENDMETHOD.

METHOD reevaluate.            " outra operação, possivelmente outro pool
  DATA(invalid) = zcl_salesorder_aux=>get_invalid_credit( CORRESPONDING #( keys ) ).
  " ... reusa a MESMA lógica, sem duplicar uma linha
ENDMETHOD.

Uma regra de verdade, um ponto de manutenção, chamada de quantos pools o BO tiver.

O superpoder e por que ele existe

O que separa a auxiliary class de um helper comum é a enhanced access rights. Dentro dela você pode:

  • IN LOCAL MODE — ler e modificar o BO pulando feature control e autorização, porque você é o provider chamando a si mesmo (e não um consumidor externo que precisa ser barrado).

  • PRIVILEGED — acesso em modo privilegiado ao BO, útil em cenários de processamento interno onde os checks de instância atrapalhariam.

Esses dois são exatamente os direitos que um behavior pool tem e uma classe ABAP comum não tem. A auxiliary class é, no fundo, "um pedaço de behavior pool que pode ser reusado" — herda os privilégios do provider sem ser o lugar onde os handlers moram.

A recomendação explícita da SAP: não terceirize completamente as implementações de handler e saver para auxiliary classes — isso gera overhead desnecessário. A auxiliary class é para lógica reutilizável compartilhada, não para virar o "verdadeiro" pool com um pool-casca vazio na frente. Os handlers ficam no behavior pool; o que é comum a vários deles desce para a auxiliary class.

Um tipo que só existe aqui dentro

Vale conhecer um detalhe que reforça o parentesco com o behavior pool: certos BDEF derived types só podem ser usados dentro de classes de implementação e auxiliary classes — não fora delas. A lista inclui FOR CHANGE, FOR DETERMINATION, FOR VALIDATION, FOR ... FEATURES e FOR ... AUTHORIZATION. Foi por isso que, no exemplo acima, o parâmetro keys pôde ser tipado com TABLE FOR VALIDATION ZI_SalesOrder~validateCredit: esse tipo compila na auxiliary class. Numa classe comum, nem isso seria possível — mais uma confirmação de que a auxiliary class está "do lado de dentro" do BO.

Quando usar — e quando não

Situação

Auxiliary class?

Por quê

Lógica que toca o buffer do BO e é usada em ≥2 operações/pools

Sim

Precisa dos direitos privilegiados + reuso — o caso canônico

BO grande com vários devs trabalhando em paralelo

Sim

Fatiar o comportamento em pools + auxiliary reduz conflito de merge

Lógica reutilizada, mas tudo cabe num único pool

Talvez

Um método privado no próprio pool já resolve — auxiliary só quando cruza pools

Reuso dentro do mesmo BO, invisível para fora, sem tocar buffer

Considere internal action/function

Se a reutilização é uma operação do BO, o artefato pode ser uma internal action

Lógica pura (cálculo, formatação) sem acessar o BO

Não

Classe utilitária comum basta — não desperdice o mecanismo

Compartilhar lógica entre BOs diferentes

Não diretamente

Auxiliary é ligada a UM bdef; para cross-BO, veja cross-BO handling / classe comum com dados passados por parâmetro

A régua: auxiliary class é para lógica que precisa dos privilégios do provider E é compartilhada entre pontos do mesmo BO. Faltou o "toca o buffer/privilégios"? Classe comum. Faltou o "compartilhada entre pools"? Método privado no pool. É uma ferramenta específica para uma dor específica.

Auxiliary class vs. as alternativas

Mecanismo

Direitos do BO?

Reuso

Onde brilha

Auxiliary class

Sim (LOCAL MODE, PRIVILEGED)

Entre pools do mesmo BO

Helper privilegiado compartilhado

Internal action/function

Sim (é operação do BO)

Via EML, dentro do BO

Quando o reuso É uma operação (passo do processo)

Método privado no pool

Sim (está no pool)

Só dentro daquele pool

Reuso local, um pool só

Classe utilitária comum

Não

Qualquer lugar

Lógica pura, sem tocar o BO

Boas práticas consolidadas

  1. Auxiliary para o compartilhado, pool para o handler. A divisão da própria doc: métodos handler/saver no pool; lógica comum a vários deles na auxiliary. Não inverta.

  2. Não esvazie o pool. Pool-casca vazio + auxiliary fazendo tudo é o anti-pattern que a SAP alerta — overhead sem ganho.

  3. Tipagem forte com os derived types. Aproveite que TABLE FOR VALIDATION/DETERMINATION/CHANGE compila aqui — assinaturas tipadas evitam conversões e erros.

  4. Métodos coesos, nome de negócio. get_invalid_credit, não helper1. A auxiliary é biblioteca do BO; trate como API interna.

  5. PRIVILEGED com parcimônia. Pular checks é poder — use quando o cenário interno realmente exige, não por preguiça de tratar autorização.

  6. Uma auxiliary por preocupação, se fizer sentido. A BDEF aceita várias; um BO grande pode ter ..._aux_credit, ..._aux_pricing — coesão acima de um baldão único.

Perguntas frequentes

Posso implementar uma validation ou action direto na auxiliary class?

Não. Métodos handler e saver (FOR VALIDATE, FOR MODIFY, save etc.) só podem ser implementados no behavior pool. A auxiliary class recebe a delegação desses métodos — o handler continua no pool e chama a auxiliary.

Preciso instanciar a auxiliary class com NEW?

Não — como os behavior pools, ela só é instanciada/invocada pelo runtime ABAP. Na prática, você chama métodos estáticos (ou o padrão que o time adotar), sem gerenciar o ciclo de vida do objeto.

Uma auxiliary class serve para vários BOs?

Ela é declarada com FOR BEHAVIOR OF apontando para um BDEF, então os direitos privilegiados valem para aquele BO. Para lógica genuinamente cross-BO, o caminho é uma classe comum recebendo os dados por parâmetro, ou os mecanismos de cross-BO transactional handling do RAP.

Qual a diferença para uma internal action?

Ambas reusam lógica com direitos do BO. A internal action é uma operação do BO (chamada via EML, aparece na BDEF como ação interna) — ideal quando o reuso é um passo do processo. A auxiliary class é um método de classe (chamada ABAP normal) — ideal quando o reuso é uma função utilitária privilegiada. Se você pensa "isto é uma etapa do meu BO", internal action; se pensa "isto é um helper que vários pontos usam", auxiliary class.

Auxiliary class tem a ver com o with friends das extensões?

São coisas diferentes com um tema comum (direitos de acesso). with friends dá a uma BDEF extension acesso irrestrito ao BO original que ela estende. A auxiliary class dá a uma classe sua os direitos do provider do seu próprio BO. Uma é sobre extensão de BO alheio; a outra, sobre organização do seu.

Isso funciona em managed e unmanaged?

Sim — o mecanismo é do BDEF, independente do tipo de implementação. Tanto o managed quanto o unmanaged podem declarar auxiliary classes e delegar a elas.

Conclusão

A auxiliary class resolve uma dor precisa: reusar, entre os vários behavior pools de um BO, lógica que precisa dos direitos privilegiados do provider — os mesmos IN LOCAL MODE e PRIVILEGED que uma classe comum não alcança. Declarada na BDEF com auxiliary class, definida com FOR BEHAVIOR OF, ela é o "pedaço reutilizável de behavior pool": não é onde os handlers moram, é onde o que eles compartilham descansa. Use quando a lógica cruza pools e toca o BO; para o resto, um método privado, uma internal action ou uma classe utilitária comum fazem o serviço. É organização de código com os privilégios certos — nada mais, e nada menos.

Referências oficiais

TagsClean CoreBO InterfaceBDEFEMLEclipseDesenvolvedor
Avalie este conteúdo
para avaliar
SAPiente
@sapiente

Blog sobre SAP, ABAP, BTP, Fiori e tudo que envolve o ecossistema SAP.

Ver perfil →
FacebookInstagramYouTubeTwitter

Comentários 0

Entre na conversa

Faça login para deixar seu comentário neste artigo.

Ainda sem comentários

Seja o primeiro a comentar este artigo.