knut 2004/11/09 03:24:30
Modified: framework/src/test/hivemind/test/services
TestBuilderFactory.java ConstructorFactory.xml
framework/src/documentation/content/xdocs/hivemind
BuilderFactory.xml
. status.xml
framework/src/java/org/apache/hivemind/util
ConstructorUtils.java
framework/src/java/org/apache/hivemind/service/impl
ServiceMessages.java BuilderFactory.java
BuilderFactoryLogic.java ServiceStrings.properties
Added: framework/src/test/hivemind/test/services
ConstructorAutowireTarget.java
Log:
added support for autowiring through constructor based dependency injection
Revision Changes Path
1.19 +111 -6
jakarta-hivemind/framework/src/test/hivemind/test/services/TestBuilderFactory.java
Index: TestBuilderFactory.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/test/hivemind/test/services/TestBuilderFactory.java,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- TestBuilderFactory.java 2 Nov 2004 17:46:10 -0000 1.18
+++ TestBuilderFactory.java 9 Nov 2004 11:24:29 -0000 1.19
@@ -16,10 +16,7 @@
import hivemind.test.services.impl.StringHolderImpl;
-import java.util.Collections;
-
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.ClassResolver;
import org.apache.hivemind.ErrorHandler;
@@ -28,13 +25,11 @@
import org.apache.hivemind.Registry;
import org.apache.hivemind.ServiceImplementationFactoryParameters;
import org.apache.hivemind.impl.DefaultClassResolver;
-import org.apache.hivemind.impl.DefaultErrorHandler;
import org.apache.hivemind.internal.Module;
import org.apache.hivemind.service.impl.BuilderClassResolverFacet;
import org.apache.hivemind.service.impl.BuilderErrorHandlerFacet;
import org.apache.hivemind.service.impl.BuilderErrorLogFacet;
import org.apache.hivemind.service.impl.BuilderFacet;
-import org.apache.hivemind.service.impl.BuilderFactory;
import org.apache.hivemind.service.impl.BuilderFactoryLogic;
import org.apache.hivemind.service.impl.BuilderLogFacet;
import org.apache.hivemind.service.impl.BuilderMessagesFacet;
@@ -42,8 +37,8 @@
import org.apache.hivemind.service.impl.BuilderServiceIdFacet;
import org.apache.hivemind.test.AggregateArgumentsMatcher;
import org.apache.hivemind.test.ArgumentMatcher;
-import org.apache.hivemind.test.TypeMatcher;
import org.apache.hivemind.test.HiveMindTestCase;
+import org.apache.hivemind.test.TypeMatcher;
import org.easymock.MockControl;
/**
@@ -474,6 +469,116 @@
ServiceAutowireTarget service = (ServiceAutowireTarget) execute(fp,
parameter);
assertNull(service.getStringHolder());
+
+ verifyControls();
+ }
+
+ public void testAutowireConstructor() throws Exception
+ {
+ MockControl fpc =
newControl(ServiceImplementationFactoryParameters.class);
+ ServiceImplementationFactoryParameters fp =
(ServiceImplementationFactoryParameters) fpc
+ .getMock();
+
+ MockControl mc = newControl(Module.class);
+ Module module = (Module) mc.getMock();
+
+ MockControl lc = newControl(Log.class);
+ Log log = (Log) lc.getMock();
+
+ fp.getLog();
+ fpc.setReturnValue(log);
+
+ fp.getServiceId();
+ fpc.setReturnValue("foo");
+
+ fp.getInvokingModule();
+ fpc.setReturnValue(module, MockControl.ONE_OR_MORE);
+
+ ClassResolver classResolver = new DefaultClassResolver();
+
+ module.getClassResolver();
+ mc.setReturnValue(classResolver);
+
+ StringHolder h = new StringHolderImpl();
+
+ module.getService(Comparable.class);
+ mc.setThrowable(new ApplicationRuntimeException("Failure."));
+
+ module.getService(StringHolder.class);
+ mc.setReturnValue(h);
+
+ module.getClassResolver();
+ mc.setReturnValue(classResolver);
+
+ replayControls();
+
+ BuilderParameter parameter = new BuilderParameter();
+
+ parameter.setClassName(ConstructorAutowireTarget.class.getName());
+ parameter.setAutowireServices(true);
+
+ ConstructorAutowireTarget service = (ConstructorAutowireTarget)
execute(fp, parameter);
+
+ assertSame(h, service.getStringHolder());
+ assertSame(classResolver, service.getClassResolver());
+
+ verifyControls();
+ }
+
+ public void testAutowireConstructorFailure() throws Exception
+ {
+ MockControl fpc =
newControl(ServiceImplementationFactoryParameters.class);
+ ServiceImplementationFactoryParameters fp =
(ServiceImplementationFactoryParameters) fpc
+ .getMock();
+
+ MockControl mc = newControl(Module.class);
+ Module module = (Module) mc.getMock();
+
+ MockControl elc = newControl(ErrorLog.class);
+ ErrorLog el = (ErrorLog) elc.getMock();
+
+ MockControl lc = newControl(Log.class);
+ Log log = (Log) lc.getMock();
+
+ fp.getLog();
+ fpc.setReturnValue(log);
+
+ fp.getServiceId();
+ fpc.setReturnValue("foo");
+
+ fp.getInvokingModule();
+ fpc.setReturnValue(module, MockControl.ONE_OR_MORE);
+
+ ClassResolver classResolver = new DefaultClassResolver();
+
+ module.getClassResolver();
+ mc.setReturnValue(classResolver);
+
+ module.getService(Comparable.class);
+ mc.setThrowable(new ApplicationRuntimeException("Failure."));
+
+ module.getService(StringHolder.class);
+ mc.setThrowable(new ApplicationRuntimeException("Failure."), 2);
+
+ fp.getErrorLog();
+ fpc.setReturnValue(el);
+
+ el.error(
+ "Error building service foo: Unable to find constructor
applicable for autowiring. "
+ + "Use explicit constructor parameters.",
+ null,
+ new ApplicationRuntimeException(""));
+ elc.setMatcher(new AggregateArgumentsMatcher(new ArgumentMatcher[]
+ { null, null, new TypeMatcher() }));
+
+ replayControls();
+
+ BuilderParameter parameter = new BuilderParameter();
+
+ parameter.setClassName(ConstructorAutowireTarget.class.getName());
+ parameter.setAutowireServices(true);
+
+ ConstructorAutowireTarget service = (ConstructorAutowireTarget)
execute(fp, parameter);
verifyControls();
}
1.4 +1 -1
jakarta-hivemind/framework/src/test/hivemind/test/services/ConstructorFactory.xml
Index: ConstructorFactory.xml
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/test/hivemind/test/services/ConstructorFactory.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ConstructorFactory.xml 1 Oct 2004 21:34:05 -0000 1.3
+++ ConstructorFactory.xml 9 Nov 2004 11:24:29 -0000 1.4
@@ -3,7 +3,7 @@
<service-point id="DefaultConstructor"
interface="hivemind.test.services.ConstructorAccess">
<invoke-factory>
- <construct
class="hivemind.test.services.impl.ConstructorAccessImpl">
+ <construct
class="hivemind.test.services.impl.ConstructorAccessImpl"
autowire-services="false">
<set property="expectedConstructorMessage" value="()"/>
</construct>
</invoke-factory>
1.1
jakarta-hivemind/framework/src/test/hivemind/test/services/ConstructorAutowireTarget.java
Index: ConstructorAutowireTarget.java
===================================================================
// Copyright 2004 The Apache Software Foundation
//
// 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 hivemind.test.services;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import org.apache.hivemind.ClassResolver;
import org.apache.hivemind.impl.DefaultClassResolver;
/**
* Used to test autowiring of constructor parameters by the BuilderFactory.
*
* @author Knut Wannheden
*/
public class ConstructorAutowireTarget
{
private StringHolder _stringHolder;
private ClassResolver _classResolver;
public ConstructorAutowireTarget(StringHolder holder)
{
this(holder, new DefaultClassResolver());
}
public ConstructorAutowireTarget(StringHolder holder, ClassResolver
classResolver)
{
_stringHolder = holder;
_classResolver = classResolver;
}
public ConstructorAutowireTarget(int dummy)
{
}
public ConstructorAutowireTarget(Serializable dummy1, Serializable
dummy2, Serializable dummy3)
{
}
public ConstructorAutowireTarget(Comparable dummy1, List dummy2, Set
dummy3)
{
}
public StringHolder getStringHolder()
{
return _stringHolder;
}
public ClassResolver getClassResolver()
{
return _classResolver;
}
}
1.14 +56 -24
jakarta-hivemind/framework/src/documentation/content/xdocs/hivemind/BuilderFactory.xml
Index: BuilderFactory.xml
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/documentation/content/xdocs/hivemind/BuilderFactory.xml,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- BuilderFactory.xml 2 Nov 2004 17:46:08 -0000 1.13
+++ BuilderFactory.xml 9 Nov 2004 11:24:29 -0000 1.14
@@ -68,7 +68,7 @@
property dependency injection. Many of the options are rarely used; the
most general purpose
and most frequently used are <link href="#set">set</link>, <link
href="#set-object">set-object</link>
and <link href="#event-listener">event-listener</link> (along with
- <link href="#Autowiring">autowiring of certain properties</link>).
+ <link href="#Autowiring">autowiring</link>).
</note>
<section>
@@ -83,7 +83,8 @@
<td>autowire-services</td>
<td>no</td>
<td>If true (the default), then the BuilderFactory will attempt to
- automatically wire any services that are not otherwise set (see
notes below).
+ automatically wire services and some common properties to
constructor parameters
+ and to properties of the constructed implementation with a
setter methods (see notes below).
</td>
</tr>
<tr>
@@ -120,7 +121,7 @@
<td>The name of a property which will
be assigned a <code>
org.apache.commons.logging.Log</code> instance for the service. The
Log is created from the
complete service id (not the name of the
- class). If ommitted, no Log
will be assigned.</td>
+ class). If ommitted (and
autowiring is disabled), no Log will be assigned.</td>
</tr>
<tr>
<td>messages-property</td>
@@ -144,17 +145,18 @@
<title>Autowiring</title>
<p>
- BuilderFactory will automatically set certain common properties of
the service implementation.
- By using standard names (and standard types), the need to specify
- attributes <code>log-property</code>,
<code>error-handler-property</code>, etc. is avoided.
- Simply by having a writable property with the correct name and type
is sufficient:
-
+ With <code>autowire-services</code> set to true the BuilderFactory
can automatically both perform
+ constructor based and setter based dependency injection. It will
not only attempt to inject
+ services but also certain common properties. By using standard
names (and standard types),
+ the need to specify attributes <code>log-property</code>,
<code>error-handler-property</code>,
+ etc. is avoided. Simply declaring a constructor parameter with the
correct type <em>or</em> a
+ writable property with the correct name <em>and</em> type is
sufficient:
</p>
<table>
<tr>
<th>Property name</th>
- <th>Property Type</th>
+ <th>Property / parameter type</th>
</tr>
<tr>
<td>classResolver</td>
@@ -177,6 +179,7 @@
<tr>
<td>messages</td>
<td>&api.Messages;</td>
+ <td/>
</tr>
<tr>
<td>serviceId</td>
@@ -184,29 +187,58 @@
</tr>
</table>
+ <note>
+ The service id (last entry in above table) will <em>only</em> be
automatically injected through a writable property
+ (i.e. <code>setServiceId(String)</code>). This because a
constructor parameter of type String
+ is far too common.
+ </note>
+
<p>
- After wiring the above properties, and processing all the service
property configuring elements, BuilderFactory may
- autowire service properties. For each writable property, whose
property type is an interface, and which has not otherwise been set,
- HiveMind will search for a service which implements the exact
interface. If one and only one service implements the interface,
- then BuilderFactory will inject that service into the property.
+ As noted the BuilderFactory will also inject services into the
constructed service implementation.
+ Through every constructor parameter and writable property whose type
is an interface (with the exception
+ of the common parameters / properties listed above) and hasn't been
set otherwise the BuilderFactory will
+ attempt to inject a service. This attempt may fail if there is
<em>no</em> visible service or <em>more than
+ one</em> visible service implementing the given interface.
(Visibility is checked with respect to the module
+ declaring the constructed service's implementation.)
</p>
<p>
- If no services implement the interface, or more than one does, then
an error will be logged. BuilderFactory
- accounts for <em>visibility</em> of the other services relative to
the module that contains the service's core implementation.
+ The action taken if the service injection fails (due to one of the
reasons given above) depends on the type
+ of dependency injection. For constructor based dependency injection
the BuilderFactory will try using a
+ different constructor (see selection details below). If no
"working" constructor is found an error
+ is logged. For setter based dependency injection the BuilderFactory
will log an error imedeately upon failed injection.
</p>
<p>
+ Constructor based dependency injection is enabled with the
<code>autowire-services</code> attribute but can be
+ overridden by declaring any constructor parameter elements (see next
section). The constructor being used for
+ the constructor based dependency injection has to meet all of the
following criteria:
+ </p>
+
+ <ul>
+ <li>the constructor is declared as <code>public</code></li>
+ <li>all parameter types are interfaces (including the common types
listed above)</li>
+ <li>no two parameters are of the same type</li>
+ </ul>
+
+ <p>
+ All constructors of the service implementation class meeting these
criteria (the default constructor is
+ considered as one of these) are ordered by length (given by the
number of parameters) and the first of these for which
+ every parameter type either has a matching common property or there
is exactly one corresponding visible service
+ available will be invoked. If no such constructor can be found an
error is logged.
+ </p>
+
+ <p>
Autowiring may be complicated by the fact that one module may
define a service point that will tangentially affect the
- construction of a service in
- another module (simply by implementing the same service interface).
In this situation, service autowiring can be turned off, by setting the
- <code>autowire-services</code> attribute to false.
+ construction of a service in another module (simply by implementing
the same service interface). In this situation,
+ service autowiring can be turned off, by setting the
<code>autowire-services</code> attribute to false.
</p>
<p>
- Once all properties have been set (possibly by autowiring), an
initializer method will be invoked. If the <code>initialize-method</code>
attribute is <em>not</em> specified,
- and the service implementation includes a public method
<code>initializeService()</code> (no parameters,
- returns void), then <code>initializeService()</code> will be invoked
as the initializer.
+ Once all properties have been set (possibly by autowiring), an
initializer method will be invoked. If the
+ <code>initialize-method</code> attribute is <em>not</em> specified,
and the service implementation includes a
+ public method <code>initializeService()</code> (no parameters,
returns void), then <code>initializeService()</code>
+ will be invoked as the initializer.
</p>
</section>
@@ -398,9 +430,9 @@
</tr>
<tr>
<td>value</td>
- <td>The <em>selector</em> used to find an object value. The
selector consists of a prefix (such as "service" or "configuration"), a colon,
- and a <em>locator</em> whose interpretation is defined by
the prefix. For example,
- <code>service:MyService</code>. See
&hivemind.ObjectProviders;.</td>
+ <td>The <em>selector</em> used to find an object value. The
selector consists of a prefix (such as
+ "service" or "configuration"), a colon, and a
<em>locator</em> whose interpretation is defined by
+ the prefix. For example, <code>service:MyService</code>.
See &hivemind.ObjectProviders;.</td>
</tr>
</table>
</section>
1.78 +5 -1 jakarta-hivemind/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/jakarta-hivemind/status.xml,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -r1.77 -r1.78
--- status.xml 8 Nov 2004 14:14:25 -0000 1.77
+++ status.xml 9 Nov 2004 11:24:29 -0000 1.78
@@ -89,7 +89,11 @@
Add the hivemind.lib.AdapterRegistryFactory service implementation
factory.
</action>
<action type="update" dev="HLS"> Removed the module parameter from
ClassFactory.newClass() and from
- DefaultImplementationBuilder.buildDefaultImplementation(). </action>
+ DefaultImplementationBuilder.buildDefaultImplementation().
+ </action>
+ <action type="update" dev="KW">
+ BuilderFactory now supports autowiring through constructor based
dependency injection.
+ </action>
</release>
<release version="1.0" date="Sep 22 2004">
1.6 +1 -1
jakarta-hivemind/framework/src/java/org/apache/hivemind/util/ConstructorUtils.java
Index: ConstructorUtils.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/util/ConstructorUtils.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ConstructorUtils.java 1 Oct 2004 21:34:05 -0000 1.5
+++ ConstructorUtils.java 9 Nov 2004 11:24:29 -0000 1.6
@@ -129,7 +129,7 @@
return false;
}
- private static Object invoke(Constructor c, Object[] parameters)
+ public static Object invoke(Constructor c, Object[] parameters)
{
try
{
1.14 +5 -0
jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/ServiceMessages.java
Index: ServiceMessages.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/ServiceMessages.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- ServiceMessages.java 27 Sep 2004 14:36:50 -0000 1.13
+++ ServiceMessages.java 9 Nov 2004 11:24:29 -0000 1.14
@@ -190,4 +190,9 @@
{
return _formatter.format("autowire-property-failure", propertyName,
serviceId, cause);
}
+
+ public static String unableToFindAutowireConstructor()
+ {
+ return _formatter.getMessage("unable-to-find-autowire-constructor");
+ }
}
1.18 +1 -5
jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/BuilderFactory.java
Index: BuilderFactory.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/BuilderFactory.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- BuilderFactory.java 2 Nov 2004 17:46:09 -0000 1.17
+++ BuilderFactory.java 9 Nov 2004 11:24:29 -0000 1.18
@@ -14,12 +14,8 @@
package org.apache.hivemind.service.impl;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
import org.apache.hivemind.ServiceImplementationFactory;
import org.apache.hivemind.ServiceImplementationFactoryParameters;
-import org.apache.hivemind.internal.Module;
/**
* Implementation of [EMAIL PROTECTED]
org.apache.hivemind.ServiceImplementationFactory}that can instantiate
@@ -39,7 +35,7 @@
public Object createCoreServiceImplementation(
ServiceImplementationFactoryParameters factoryParameters)
{
- BuilderParameter parameter = (BuilderParameter)
factoryParameters.getParameters().get(0);
+ BuilderParameter parameter = (BuilderParameter)
factoryParameters.getFirstParameter();
BuilderFactoryLogic logic = new
BuilderFactoryLogic(factoryParameters, parameter);
1.7 +103 -8
jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/BuilderFactoryLogic.java
Index: BuilderFactoryLogic.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/BuilderFactoryLogic.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- BuilderFactoryLogic.java 2 Nov 2004 17:46:09 -0000 1.6
+++ BuilderFactoryLogic.java 9 Nov 2004 11:24:30 -0000 1.7
@@ -14,20 +14,27 @@
package org.apache.hivemind.service.impl;
+import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
+import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.ClassResolver;
-import org.apache.hivemind.Defense;
import org.apache.hivemind.ErrorHandler;
+import org.apache.hivemind.ErrorLog;
import org.apache.hivemind.HiveMind;
import org.apache.hivemind.Location;
+import org.apache.hivemind.Messages;
import org.apache.hivemind.ServiceImplementationFactoryParameters;
import org.apache.hivemind.internal.Module;
import org.apache.hivemind.service.EventLinker;
@@ -99,19 +106,24 @@
ClassResolver resolver = _contributingModule.getClassResolver();
Class serviceClass = resolver.findClass(_parameter.getClassName());
- Object[] constructorParameters = buildConstructorParameters();
+ List parameters = _parameter.getParameters();
+
+ if (_parameter.getAutowireServices() && parameters.isEmpty())
+ {
+ return instantiateConstructorAutowiredInstance(serviceClass);
+ }
+ else
+ {
+ Object[] constructorParameters =
buildConstructorParameters(parameters);
- return ConstructorUtils.invokeConstructor(serviceClass,
constructorParameters);
+ return ConstructorUtils.invokeConstructor(serviceClass,
constructorParameters);
+ }
}
- private Object[] buildConstructorParameters()
+ private Object[] buildConstructorParameters(List parameters)
{
- List parameters = _parameter.getParameters();
int count = parameters.size();
- if (count == 0)
- return null;
-
Object[] result = new Object[count];
for (int i = 0; i < count; i++)
@@ -131,6 +143,89 @@
}
return result;
+ }
+
+ private Object instantiateConstructorAutowiredInstance(Class
serviceClass)
+ {
+ List serviceConstructorCandidates =
getOrderedServiceConstructors(serviceClass);
+
+ outer: for (Iterator candidates =
serviceConstructorCandidates.iterator(); candidates
+ .hasNext();)
+ {
+ Constructor candidate = (Constructor) candidates.next();
+
+ Class[] parameterTypes = candidate.getParameterTypes();
+
+ Object[] parameters = new Object[parameterTypes.length];
+
+ for (int i = 0; i < parameters.length; i++)
+ if (parameterTypes[i] == ClassResolver.class)
+ parameters[i] =
_factoryParameters.getInvokingModule().getClassResolver();
+ else if (parameterTypes[i] == ErrorHandler.class)
+ parameters[i] =
_factoryParameters.getInvokingModule().getErrorHandler();
+ else if (parameterTypes[i] == ErrorLog.class)
+ parameters[i] = _factoryParameters.getErrorLog();
+ else if (parameterTypes[i] == Log.class)
+ parameters[i] = _factoryParameters.getLog();
+ else if (parameterTypes[i] == Messages.class)
+ parameters[i] =
_factoryParameters.getInvokingModule().getMessages();
+ else
+ try
+ {
+ parameters[i] =
_factoryParameters.getInvokingModule().getService(
+ parameterTypes[i]);
+ }
+ catch (ApplicationRuntimeException e)
+ {
+ continue outer;
+ }
+
+ return ConstructorUtils.invoke(candidate, parameters);
+ }
+
+ throw new
ApplicationRuntimeException(ServiceMessages.unableToFindAutowireConstructor(),
+ _parameter.getLocation(), null);
+ }
+
+ private List getOrderedServiceConstructors(Class serviceClass)
+ {
+ List orderedInterfaceConstructors = new ArrayList();
+
+ Constructor[] constructors = serviceClass.getDeclaredConstructors();
+
+ outer: for (int i = 0; i < constructors.length; i++)
+ {
+ if (!Modifier.isPublic(constructors[i].getModifiers()))
+ continue;
+
+ Class[] parameterTypes = constructors[i].getParameterTypes();
+
+ if (parameterTypes.length > 0)
+ {
+ Set seenTypes = new HashSet();
+
+ for (int j = 0; j < parameterTypes.length; j++)
+ {
+ if (!parameterTypes[j].isInterface() ||
seenTypes.contains(parameterTypes[j]))
+ continue outer;
+
+ seenTypes.add(parameterTypes[j]);
+ }
+ }
+
+ orderedInterfaceConstructors.add(constructors[i]);
+ }
+
+ Collections.sort(orderedInterfaceConstructors, new Comparator()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return ((Constructor) o2).getParameterTypes().length
+ - ((Constructor) o1).getParameterTypes().length;
+ }
+ });
+
+ return orderedInterfaceConstructors;
}
private void invokeInitializer(Object service)
1.10 +1 -0
jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/ServiceStrings.properties
Index: ServiceStrings.properties
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/ServiceStrings.properties,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ServiceStrings.properties 27 Sep 2004 14:36:50 -0000 1.9
+++ ServiceStrings.properties 9 Nov 2004 11:24:30 -0000 1.10
@@ -36,3 +36,4 @@
invalid-service-property-locator=''{0}'' is not a valid locator for use with
the service-property object provider. It should be the id of a service, a
comma, and the name of a property provided by that service.
failure-building-service=Error building service {0}: {1}
autowire-property-failure=Unable to autowire property {0} of service {1}: {2}
+unable-to-find-autowire-constructor=Unable to find constructor applicable
for autowiring. Use explicit constructor parameters.
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]