Manager conceito

O Manager no Jasap não é uma pessoa — é a infraestrutura que monta e acompanha cada requisição. RootManager, ModuloManager e AppManager são nomes de níveis, não entidades separadas. Na hora da requisição, existe um único objeto manager do início ao fim.

Resumo rápido
  • A hierarquia Root → Módulo → App existe para organizar a montagem, não para criar gerentes diferentes
  • Cada nível tem um escopo: o que faz sentido configurar ali (filtros globais, actions do módulo, actions do CRUD)
  • Na hora da requisição, o Jasap cria uma instância só do manager que registrou a action — e essa instância já herda tudo dos níveis acima
  • Se fosse tudo num arquivo só, funcionaria igual — mas seria impossível de manter

A hierarquia de classes

No projeto de estudo, a cadeia completa é:

AppManager              (Jasap — base abstrata)
 └── JasapRootManager   (Jasap — configuração de filtros globais)
      └── RootManager   (br.xt — registra módulos)
           └── PnlManager   (br.xt.app.painel — painel de controle)
                └── DepartamentoManager   (br.xt.app.departamento — seu módulo)

Cada classe herda tudo da anterior. Quando o Jasap cria um new DepartamentoManager(), esse objeto já é um PnlManager, já é um RootManager, já é um AppManager — tudo junto numa instância só.

Os nomes diferentes existem pelo mesmo motivo que endereço tem País, Estado e Rua — são níveis de organização do mesmo ponto:

NívelClasseO que configura
RaizRootManagerFiltros globais (DataBaseFilter, AAFilter...), registra os módulos
MóduloPnlManager / DepartamentoManagerActions e permissões do módulo, filtros adicionais
App/CRUDAppManager (menor nível)Actions do CRUD específico — não registra outros managers

Dois momentos completamente diferentes

O Manager aparece em dois momentos da vida do sistema, com papéis diferentes em cada um:

Momento 1 — Configuração (servidor iniciando)

Quando o Tomcat inicia, o RootManager.config() é chamado uma única vez. Ele cria instâncias temporárias de cada ModuloManager só para registrar as actions:

// RootManager.config() — roda UMA VEZ na inicialização
public void config() throws Exception {
    new PnlManager().config();              // instância temporária
    new DepartamentoManager().config();     // instância temporária — registra e descarta
}

Cada config() chama regAction(), que grava num XML global: "esta action pertence a este manager".

<!-- Mapa gerado pelo regAction — fica na memória do servidor -->
<url action="br.xt.app.departamento.DepartamentoHome"
     manager="br.xt.app.departamento.DepartamentoManager"/>

Depois que o config() termina, essas instâncias temporárias são descartadas. Serviram apenas para montar o mapa.

Momento 2 — Requisição (usuário clicou algo)

Quando uma requisição chega, o JasapController.service() faz o trabalho real:

// JasapController.service() — roda A CADA REQUISIÇÃO
public void service(HttpServletRequest request, HttpServletResponse response) {

    // 1. Consulta o XML: qual manager registrou essa action?
    Element eURL = mapURL.getElementById(actionURL);
    String clsManager = eURL.getAttribute("manager");   // "DepartamentoManager"
    String clsAction  = eURL.getAttribute("action");    // "DepartamentoHome"

    // 2. Cria UMA instância nova do manager certo
    AppManager manager = Class.forName(clsManager).newInstance();

    // 3. Importa os filtros globais do RootManager
    manager.importGlobalFilters(rootManager.getGlobalFilters());

    // 4. Configura o manager com o contexto da requisição
    manager.setInput(new Input(request));
    manager.setOutput(new Output(response));
    manager.setSession(new Session(request.getSession()));

    // 5. Cria a action e conecta ao manager
    JasapAct action = Class.forName(clsAction).newInstance();
    action.setManager(manager);   // O BINDING — action e manager conectados

    // 6. Executa
    manager.invokeAction(action);
}
PassoO que acontece
1. ConsultaO Jasap olha o mapa XML e descobre: "essa URL foi registrada pelo DepartamentoManager"
2. InstânciaCria um new DepartamentoManager() — que por herança já é PnlManager + AppManager
3. FiltrosCopia os filtros globais (DataBaseFilter, AAFilter...) para este manager
4. ContextoInjeta request, response e session — agora o manager conhece o usuário e pode responder
5. BindingCria a action e conecta ao manager — a partir daqui, action.getManager() retorna este manager
6. ExecuçãoO manager executa os filtros na ordem e depois chama action.execute()

Por que nomes diferentes se é um só?

Porque são níveis de organização, não entidades separadas.

Se todo o código de configuração ficasse num arquivo só — filtros globais, permissões de todos os módulos, actions de todos os CRUDs — funcionaria. Mas seria um arquivo com milhares de linhas, impossível de manter.

A separação em níveis permite:

BenefícioComo funciona
ModularidadeCada módulo tem seu próprio Manager com suas actions — adicionar ou remover um módulo é mexer em um arquivo
Escopo claroFiltros globais ficam no Root, permissões do módulo ficam no Módulo — cada coisa no seu lugar
Herança JavaO DepartamentoManager herda regAction() e regFun() sem reimplementar nada

Na requisição, a herança garante que a instância criada tem tudo:

DepartamentoManager manager = new DepartamentoManager();
// manager É um PnlManager   → tem regFun(), mapFUN
// manager É um AppManager    → tem regAction(), setInput(), setOutput()
// manager É um RootManager   → tem configGlobalFilters()
// Tudo numa instância só — a herança Java faz o merge automaticamente

O que regAction() realmente faz

Quando DepartamentoManager.config() chama regAction(DepartamentoHome.class), o que acontece internamente é:

// AppManager.mapURL() — dentro do regAction
public void mapURL(String call, Class actionClass) throws Exception {
    Element url = JasapController.mapURL.newElement("url");
    url.setAttribute("id", call);                                    // URL hasheada
    url.setAttribute("action", actionClass.getName());               // "br.xt...DepartamentoHome"
    url.setAttribute("manager", this.getClass().getName());          // "br.xt...DepartamentoManager"
    JasapController.mapURL.getRootElement().appendChild(url);
}

O ponto chave é o this.getClass().getName() — o método grava qual manager está chamando. Como quem chama é o DepartamentoManager, fica registrado "br.xt.app.departamento.DepartamentoManager".

Depois, na requisição, o JasapController lê esse atributo e sabe exatamente qual classe instanciar com Class.forName().

Fluxo completo: do clique à resposta

USUÁRIO clica em "Departamento" no menu
    ↓
BROWSER envia requisição HTTP para "a1b2c3d4.jsap"
    ↓
JASAPCONTROLLER.service()
    ↓
CONSULTA mapURL → action: DepartamentoHome, manager: DepartamentoManager
    ↓
NEW DepartamentoManager() — instância com tudo herdado
    ↓
importGlobalFilters() — copia DataBaseFilter, AAFilter, etc.
    ↓
setInput(request), setOutput(response), setSession(session)
    ↓
NEW DepartamentoHome() — action criada
    ↓
action.setManager(manager) — BINDING
    ↓
manager.invokeAction(action)
    ↓
FILTROS executam na ordem → action.execute() → monta a tela
    ↓
RESPONSE enviada ao browser