/*
* Copyright 2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rioproject.impl.associations;
import org.rioproject.associations.AssociationType;
import org.rioproject.impl.associations.strategy.FailOver;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
/**
* <p>
* Annotation to indicate an association to another service.
* </p>
* <p>
* Example: You can declare an association to another service as follows:
* </p>
*
* <pre class="code">
* {@link ServiceAssociation @ServiceAssociation}(name="Foo", serviceType="Foo.class")
* setFoo(Foo foo) {
* // ...
* }
* </pre>
* <p>
* Note: {@link ServiceAssociation @ServiceAssociation} can be applied at either the
* method or field level.
* </p>
*
* @see org.rioproject.associations.Association
* @see org.rioproject.associations.AssociationManagement
* @see org.rioproject.associations.AssociationDescriptor
*
* @author Dennis Reedy
*/
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ServiceAssociation {
/**
* The name of the service to match.
*
* @return The name of the service to match. If the default <tt>""</tt> is
* used, then the service will be matched using only the {@link #serviceType}.
*/
String name() default "";
/**
* The exported service interface type to match.
*
* @return The service's exported service interface type to match.
*/
Class serviceType() ;
/**
* The type of association to declare.
* The {@link ServiceAssociation @ServiceAssociation} may have one of the
* following types:
*
* <ul>
* <li>{@link org.rioproject.associations.AssociationType#USES}
* <li>{@link org.rioproject.associations.AssociationType#COLOCATED}
* <li>{@link org.rioproject.associations.AssociationType#REQUIRES}
* <li>{@link org.rioproject.associations.AssociationType#ISOLATED}
* <li>{@link org.rioproject.associations.AssociationType#OPPOSED}
* </ul>
* @return The type of the association.
*/
AssociationType type() default AssociationType.USES;
/**
* A strategy that determines how services in the collection of
* discovered services are invoked. The current service selection
* strategies are:
* <ul>
* <li>{@link org.rioproject.impl.associations.strategy.FailOver}
* <li>{@link org.rioproject.impl.associations.strategy.RoundRobin}
* <li>{@link org.rioproject.impl.associations.strategy.Utilization}
* </ul>
*
* <p>Note: all service selection strategies will also
* prefer local services over remote services.
*
* <p>The Fail-Over strategy will invoke the first service in it's collection
* for each method invocation until that service is no longer reachable.
* If the associated service is unavailable, the fail-over strategy invokes
* the next service in it's list.
*
* <p>The Round Robin strategy alternates selection of services from the
* association, alternating the selection of associated services using a
* round-robin approach.
*
* <p>The Utilization strategy is a round-robin selector that selects
* services running on compute resources whose system resources are not
* depleted. System resource depletion is determined by
* {@link org.rioproject.system.MeasuredResource} provided as part of
* the {@link org.rioproject.system.ComputeResourceUtilization}
* object returned as part of the deployment map. If any of a Cybernode's
* resources are depleted, the service hosted in that Cybernode will not
* be invoked. This is of particular use in cases where out of memory
* conditions may occur. Using the utilization strategy a service running
* in a memory constrained Cybernode will not be invoked until the JVM
* performs garbage collection and memory is reclaimed.
*
* @return The class to use for service selection.
*/
Class strategy() default FailOver.class;
/**
* Declare how the association proxy is injected. When the association proxy
* is injected <i>eagerly</i>, it is injected immediately upon service
* creation.
*
* <p>If the association proxy is injected <i>lazily</i>, it is injected
* when associated services are discovered.
*
* <p>Care must be taken when using the <i>eager</i> approach, the proxy
* may not have discovered services <i>backing</i> the generated
* proxy.
*
* <p>If you configure that the association proxy is injected eagerly,
* you really need to consider declaring a service discovery timeout.
*
* @return Whether to inject eagerly or lazily.
*/
boolean eager() default false;
/**
* How long to wait for a service before throwing a
* {@link java.rmi.RemoteException}. In a typical distributed environment,
* if there are no discovered (available) services and a remote method
* invocation is attempted on a service, a <tt>RemoteException</tt> is thrown.
*
* <p>By declaring the <tt>timeout</tt> value below the dynamic proxy will
* wait the declared amount of time and wait for a service to become
* available to make the invocation.
*
* @return The amount of time to wait for service discovery if no services
* are available.
*/
long timeout() default 0;
/**
* The {@link #timeout} unit of time for service discovery timeout.
*
* @return The unit of time that the {@link #timeout} is configured for.
*/
TimeUnit timeoutUnits() default TimeUnit.SECONDS;
/**
* The version of the service to associate to.
*
* @return The version of the service to associate to.
*/
String version() default "";
}