Backend Integration
This page uses your demo repos directly:
- backend reference: convengine-demo
- UI reference: zapper-ui
What each demo proves
- convengine-demo: Spring Boot consumer setup, transport mode config, step hooks, LLM wiring.
- zapper-ui: conversation client, SSE subscription, audit timeline UI.
Enable ConvEngine in backend
Add @EnableConvEngine and provide required beans.
Configure transport mode
Use profile yaml (sse, stomp, both) to switch runtime behavior.
Connect frontend
Frontend posts to message endpoint and listens to SSE/STOMP for audit updates.
convengine-demo: Core app bootstrap
ConvengineDemoApplication.java
package: com.github.salilvnairfile: convengine-demo/src/main/java/com/github/salilvnair/ConvengineDemoApplication.java
JAVA
@SpringBootApplication
@ComponentScan(basePackages = {"com.github.salilvnair.convengdemo"})
@EntityScan(basePackages = {"com.github.salilvnair.convengdemo.entity"})
@EnableJpaRepositories(basePackages = {"com.github.salilvnair.convengdemo.repo"})
public class ConvengineDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ConvengineDemoApplication.class, args);
}
}
ConvEngineConfig.java
package: com.github.salilvnair.convengdemo.configfile: convengine-demo/src/main/java/com/github/salilvnair/convengdemo/config/ConvEngineConfig.java
JAVA
@Configuration
@EnableConvEngine
@EnableConvEngineAsyncAuditDispatch // optional
@EnableConvEngineStompBrokerRelay // optional
@EnableCcfCore
public class ConvEngineConfig {
@Bean
public RestWebServiceFacade restWebServiceFacade() {
return new RestWebServiceFacade();
}
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
convengine-demo: Runtime config
application.yml
file: convengine-demo/src/main/resources/application.yml
YAML
application-sse.yml
file: convengine-demo/src/main/resources/application-sse.yml
YAML
convengine:
demo:
stream-mode: SSE
transport:
sse:
enabled: true
stomp:
enabled: false
application-stomp.yml
file: convengine-demo/src/main/resources/application-stomp.yml
YAML
convengine:
demo:
stream-mode: STOMP
transport:
sse:
enabled: false
stomp:
enabled: true
application-both.yml
file: convengine-demo/src/main/resources/application-both.yml
YAML
convengine:
demo:
stream-mode: BOTH
transport:
sse:
enabled: true
stomp:
enabled: true
Relay + async audit rollout
Keep broker.mode: SIMPLE and audit.dispatch.async-enabled: false for baseline. Enable relay and async in non-prod first, then tune queue-capacity, rejection-policy, and rate-limit using audit volume.
convengine-demo: Transport + Hook diagnostics
DemoTransportProperties.java
file: convengine-demo/src/main/java/com/github/salilvnair/convengdemo/config/DemoTransportProperties.java
JAVA
@Component
@ConfigurationProperties(prefix = "convengine.demo")
public class DemoTransportProperties {
private StreamMode streamMode = StreamMode.SSE;
private StepHook stepHook = new StepHook();
public enum StreamMode { SSE, STOMP, BOTH }
public static class StepHook {
private boolean enabled = true;
}
}
ConvEngineTransportStartupLogger.java
file: convengine-demo/src/main/java/com/github/salilvnair/convengdemo/config/ConvEngineTransportStartupLogger.java
JAVA
@Component
@RequiredArgsConstructor
public class ConvEngineTransportStartupLogger {
private final DemoTransportProperties demoTransportProperties;
private final ConvEngineTransportConfig transportConfig;
private final Environment environment;
@EventListener(ApplicationReadyEvent.class)
public void logTransportConfiguration() {
boolean sseEnabled = transportConfig.getSse().isEnabled();
boolean stompEnabled = transportConfig.getStomp().isEnabled();
// validates mode and prints endpoints
}
}
DemoEngineStepHook.java
file: convengine-demo/src/main/java/com/github/salilvnair/convengdemo/config/DemoEngineStepHook.java
JAVA
@Component
@RequiredArgsConstructor
public class DemoEngineStepHook implements EngineStepHook {
private static final Set<EngineStep.Name> TRACKED_STEPS = Set.of(
EngineStep.Name.IntentResolutionStep,
EngineStep.Name.SchemaExtractionStep,
EngineStep.Name.RulesStep,
EngineStep.Name.ResponseResolutionStep
);
@Override
public boolean supports(EngineStep.Name stepName, EngineSession session) {
return demoTransportProperties.getStepHook().isEnabled() && TRACKED_STEPS.contains(stepName);
}
@Override
public void beforeStep(EngineStep.Name stepName, EngineSession session) { /* logs */ }
@Override
public void afterStep(EngineStep.Name stepName, EngineSession session, StepResult result) { /* logs */ }
@Override
public void onStepError(EngineStep.Name stepName, EngineSession session, Throwable error) { /* logs */ }
}
zapper-ui: How frontend consumes backend
convengine.api.js (zapper-ui)
file: zapper-ui/src/api/convengine.api.js
JS
const API_BASE = "http://localhost:8080/api/v1/conversation";
export async function sendMessage(conversationId, message, inputParams = {}, reset = false) { /* ... */ }
export async function fetchAudits(conversationId) { /* ... */ }
export function subscribeConversationSse(conversationId, handlers = {}) { /* ... */ }
// STOMP scaffold commented for optional enablement
App.jsx (zapper-ui)
file: zapper-ui/src/App.jsx
JSX
useEffect(() => {
const stream = subscribeConversationSse(conversationId, {
onConnected: () => setAuditVersion(v => v + 1),
onEvent: () => setAuditVersion(v => v + 1),
});
return () => stream.close();
}, [conversationId]);
ChatPanel.jsx (zapper-ui)
file: zapper-ui/src/components/ChatPanel.jsx
JSX
const res = await sendMessage(conversationId, userText);
setMessages(m => [...m, { role: "assistant", text: assistantText }]);
// Typing indicator shown while request is in-flight
Backend + UI runbook
- Start backend (
convengine-demo) with profile sse, stomp, or both. - Start zapper-ui and point API base to backend URL.
- Send message, verify live timeline from stream + detailed payloads from audit API.
Run commands
BASH