ActingWeb v3.1 Migration Guide
This guide helps you migrate from the legacy OnAWBase interface (removed in v3.1) to the modern ActingWebApp interface.
Overview of Changes
Version 3.1 represents a major architectural change:
Removed: Legacy
OnAWBaseinterface completelyRemoved:
actingweb.on_awmodule andOnAWBaseclassRemoved:
ActingWebBridgecompatibility layerChanged: Handler constructors now accept
hooks: HookRegistryinstead ofon_aw: OnAWBaseRequired: Applications must now use the modern
ActingWebAppinterface exclusively
Migration Steps
Step 1: Replace OnAWBase Class
Before (Legacy - NO LONGER SUPPORTED):
from actingweb.on_aw import OnAWBase
class MyApp(OnAWBase):
def get_properties(self, path, data):
# Hide sensitive properties
if path and path[0] == "email":
return None
return data
def post_callbacks(self, name):
if name == "webhook":
# Handle webhook
return True
return False
After (Modern Interface - REQUIRED):
from actingweb.interface import ActingWebApp
app = ActingWebApp("my-app", "dynamodb", "myapp.com")
@app.property_hook("email")
def hide_email_property(actor, operation, value, path):
if operation == "get":
return None # Hide email from external access
return value
@app.callback_hook("webhook")
def handle_webhook(actor, name, data):
# Handle webhook
return {"status": "processed"}
Step 2: Update Handler Instantiation
Before:
from myapp import MyApp
my_onaw = MyApp()
handler = SomeHandler(webobj, config, on_aw=my_onaw)
After:
# Use the same app instance created above
handler = SomeHandler(webobj, config, hooks=app.hooks)
Step 3: Update Flask Integration
Before:
from flask import Flask
from actingweb.interface.integrations.flask_integration import FlaskIntegration
from actingweb.interface.bridge import ActingWebBridge
flask_app = Flask(__name__)
aw_app = ActingWebApp(...)
bridge = ActingWebBridge(aw_app)
integration = FlaskIntegration(aw_app, flask_app)
After:
from flask import Flask
flask_app = Flask(__name__)
aw_app = ActingWebApp(...)
integration = aw_app.integrate_flask(flask_app)
Hook Type Mapping
The new interface uses focused hook functions instead of monolithic class methods:
OnAWBase Method Mapping
Legacy OnAWBase Method |
Modern Hook Equivalent |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Hook Function Signatures
Property Hooks
@app.property_hook("property_name")
def handle_property(actor: ActorInterface, operation: str, value: Any, path: List[str]) -> Any:
# operation is one of: "get", "put", "post", "delete"
if operation == "get":
return value # Transform or return None to reject
elif operation == "put":
return value # Transform or return None to reject
# ... handle other operations
return value
Callback Hooks
@app.callback_hook("callback_name")
def handle_callback(actor: ActorInterface, name: str, data: Dict[str, Any]) -> Union[bool, Dict[str, Any]]:
# Process callback
return {"result": "processed"} # or True/False
Application-Level Callback Hooks
@app.app_callback_hook("bot")
def handle_bot(data: Dict[str, Any]) -> Union[bool, Dict[str, Any]]:
# No actor context - this is application-level
return True
Method Hooks
@app.method_hook("method_name")
def handle_method(actor: ActorInterface, name: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
# Process method call
return {"result": "success"}
Action Hooks
@app.action_hook("action_name")
def handle_action(actor: ActorInterface, name: str, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
# Process action
return {"status": "executed"}
Lifecycle Hooks
@app.lifecycle_hook("actor_created")
def on_actor_created(actor: ActorInterface, **kwargs) -> None:
# Initialize new actor
actor.properties.created_at = str(datetime.now())
@app.lifecycle_hook("actor_deleted")
def on_actor_deleted(actor: ActorInterface, **kwargs) -> None:
# Clean up before deletion
pass
Subscription Hooks
@app.subscription_hook
def handle_subscription(actor: ActorInterface, subscription: Dict[str, Any], peer_id: str, data: Dict[str, Any]) -> bool:
# Process subscription callback
return True
Benefits of Migration
The new interface provides significant advantages:
- Code Reduction
95% less boilerplate code
Focused, single-purpose functions instead of monolithic classes
- Better Developer Experience
Better type safety and IDE support
Easier testing and debugging
Self-documenting hook decorators
- Architecture Benefits
Single source of truth for application logic
No more dual interface maintenance
Improved runtime performance without bridge layer overhead
Clean separation of concerns
- Maintainability
Much simpler debugging without bridge layer abstraction
Direct hook execution in handlers
Eliminated potential for interface synchronization issues
Common Migration Issues
Type Errors
If you encounter type errors, ensure hook function signatures match exactly:
# Correct signature
@app.property_hook("email")
def handle_email(actor: ActorInterface, operation: str, value: Any, path: List[str]) -> Any:
return value
Missing Imports
Update your imports:
# Remove these imports
# from actingweb.on_aw import OnAWBase
# from actingweb.interface.bridge import ActingWebBridge
# Use these instead
from actingweb.interface import ActingWebApp, ActorInterface
Handler Parameters
Ensure all handler instantiations use the new parameter:
# Old: on_aw=my_onaw_instance
# New: hooks=app.hooks
handler = MyHandler(webobj, config, hooks=app.hooks)
Need Help?
If you encounter issues during migration:
Check that all hook function signatures match the documented patterns
Ensure you’re using
hooks=app.hooksin handler constructorsVerify that property hooks return appropriate values (
Noneto reject operations)Review the ActingWeb demo application for complete examples
The migration is straightforward and results in much cleaner, more maintainable code!