Architecture
- Server used to manage service, for outside provide a interface’s service
for inside maintain service’s collection.- manage services’ lifecycle
- search service for request
- stop service so on
- Service consist by
connector
andcontainer
- Connector be responsible for give request to container
- Container be responsible for deal with request
Server
Forcus on two method addService(Service service)
and findService(String name)
org.apache.catalina.core.StandardServer1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29/**
* Add a new Service to the set of defined Services.
*
* @param service The Service to be added
*/
public void addService(Service service) {
service.setServer(this);
synchronized (servicesLock) {
Service results[] = new Service[services.length + 1];
System.arraycopy(services, 0, results, 0, services.length);
results[services.length] = service;
services = results;
if (getState().isAvailable()) {
try {
service.start();
} catch (LifecycleException e) {
// Ignore
}
}
// Report this property change to interested listeners
support.firePropertyChange("service", null, service);
}
}
- set current service’s server
- extends service array, place new service in the last index
- check service’s lefe state
- report event to interested listeners
Interface Lifecycle
1 | start() |
Any state can transition to FAILED.
Calling start() while a component is in states STARTING_PREP, STARTING or
STARTED has no effect.Calling start() while a component is in state NEW will cause init() to be
called immediately after the start() method is entered.Calling stop() while a component is in states STOPPING_PREP, STOPPING or
STOPPED has no effect.Calling stop() while a component is in state NEW transitions the component
to STOPPED. This is typically encountered when a component fails to start and
does not start all its sub-components. When the component is stopped, it will
try to stop all sub-components - even those it didn’t start.Attempting any other transition will throw LifecycleException.
Anaylsis
1 | I Lifecycle |
All component in tomcat implemnts Lifecycle
interface,
father level component manage sub-level component.
So when top component changes, state will transmit to all conponments.
Focus on anaylsis start
progress.
org.apache.catalina.util.LifecycleBase1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public final synchronized void start() throws LifecycleException {
......
try {
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
......
} catch (Throwable t) {
// This is an 'uncontrolled' failure so put the component into the
// FAILED state and throw an exception.
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
}
}
org.apache.catalina.core.StandardServer1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/**
* Start nested components ({@link Service}s) and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
protected void startInternal() throws LifecycleException {
fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING);
globalNamingResources.start();
// Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
All sub-components will be notify through fireLifecycleEvent
All registed service will be start.
org.apache.catalina.util.LifecycleSupport1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16/**
* Notify all lifecycle event listeners that a particular event has
* occurred for this Container. The default implementation performs
* this notification synchronously using the calling thread.
*
* @param type Event type
* @param data Event data
*/
public void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
LifecycleListener interested[] = listeners;
for (int i = 0; i < interested.length; i++)
interested[i].lifecycleEvent(event);
}
Be called[defined] in LifecycleBase
, method name is the same.
Service
A service packaged multi connector and a container
We forcus on addConnector(Connector connector)
setContainer(Container container)
org.apache.catalina.core.StandardService1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34/**
* Set the <code>Container</code> that handles requests for all
* <code>Connectors</code> associated with this Service.
*
* @param container The new Container
*/
public void setContainer(Container container) {
Container oldContainer = this.container;
if ((oldContainer != null) && (oldContainer instanceof Engine))
((Engine) oldContainer).setService(null);
this.container = container;
if ((this.container != null) && (this.container instanceof Engine))
((Engine) this.container).setService(this);
if (getState().isAvailable() && (this.container != null)) {
try {
this.container.start();
} catch (LifecycleException e) {
// Ignore
}
}
if (getState().isAvailable() && (oldContainer != null)) {
try {
oldContainer.stop();
} catch (LifecycleException e) {
// Ignore
}
}
// Report this property change to interested listeners
support.firePropertyChange("container", oldContainer, this.container);
}
- set new input container
- reversal setting container’s service
- if state ok, start container
- if old container exists, stop it
- report event
1 | /** |
- Setting connector’s service.
- Similar with server manage services, use array storage connector.
- Extends connector array, place new connector in the last index, implements dynamic array.
- start connector, report event.
Design Model
All registed observers
listener will be call by reported event
Observer may do something, or just ignore.