Configuring the validator provided to #Valid for message interpolation - jax-rs

I'm using the hibernate validator:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.2.Final</version>
</dependency>
In my unit test, it works just fine using it this way:
private static Validator validator;
validator = ValidatorProvider.getInstance().getValidator();
with the validator being configured for message interpolation:
public class ValidatorProvider {
static ValidatorProvider INSTANCE;
Validator validator;
private ValidatorProvider() {
CustomMessageInterpolator messageInterpolator = new CustomMessageInterpolator();
ValidatorFactory validatorFactory
= Validation.byProvider(HibernateValidator.class).configure()
.messageInterpolator(messageInterpolator).buildValidatorFactory();
validator = validatorFactory.getValidator();
}
public static ValidatorProvider getInstance() {
if (INSTANCE == null) {
INSTANCE = new ValidatorProvider();
}
return INSTANCE;
}
public Validator getValidator() {
return validator;
}
}
The above singleton is not being used by the integration tests.
Now, in my REST controller, I only have the #Valid annotation:
#Valid Answer answer
For now, the following message:
javax.validation.constraints.Pattern.message=The "{0}" value must match "{regexp}".
is not interpolated when used in the integration test.
How can I tell the above #Valid annotation that it should use my configured validator ?

Which REST framework are you using? Depending on the specific implementation it may be possible to inject a ValidatorFactory in one way or another.
The simplest though would be to not bootstrap the validator yourself, but rather let the REST framework do it, applying the configuration from META-INF/validation.xml (the "default validator factory"). You can set message interpolators and many other things in that XML file and constraint mapping files which it may include.

Related

#Cacheable annotation cannot work as expected when deserialize beans with LocalDateTime type property

I found that the annotation #Cacheable cannot work when the method returns a Java Bean type, this is the complete description:
I annotated #Cacheable on a method to use spring cache:
#Cacheable(cacheNames="userCache", key="#userId")
public User getUser(long userId){
return userRepository.getUserById(userId);
}
And the User class like this:
public class User{
Long userId;
String username;
#JsonSerialize(using = LocalDateTimeSerializer.class)
#JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime birthDateTime;
}
As you can see, I annotated the relating Jackson annotations to make Jackson deserialization for LocalDateTime types work, and this is the related dependency in pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.5</version>
</dependency>
After that, I call the #Cacheable method getUser like this:
User user = userCache.getUser(1L);
and there throws an exception:
org.redisson.client.RedisException: Unexpected exception while processing command
at org.redisson.command.CommandAsyncService.convertException(CommandAsyncService.java:326)
at org.redisson.command.CommandAsyncService.get(CommandAsyncService.java:123)
at org.redisson.RedissonObject.get(RedissonObject.java:82)
...blabla
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type java.time.LocalDateTime not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 101] (through reference chain: com.stackoverflow.domain.User["birthDateTime"]) at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1764)
at com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer.deserialize(UnsupportedTypeDeserializer.java:36)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
3.Before I use the #Cacheable, there is no problem if I get the User from database straightly. But when I begin to use #Cacheable, it always throws the exception above, no matter if I configured those Jackson deserialization for LocalDateTime. Is #Cacheable cannot work well with Java Bean with LocalDateTime property, or just my configuration of Jackson is wrong?
I had the same problem. Spring Cache doesn't use the implicit ObjectMapper used by other Spring components.
Include the module, you already did that.
Create a configuration which will override the default Spring Cache Configuration:
#Configuration
#EnableCaching
public class CacheConfiguration {
#Bean
public RedisSerializationContext.SerializationPair<Object> serializationPair() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule())
.activateDefaultTyping(
objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.EVERYTHING,
JsonTypeInfo.As.PROPERTY
);
return RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
}
#Bean
public RedisCacheConfiguration redisCacheConfiguration(
#Value("${cache.default-ttl-in-seconds}") Integer ttl,
RedisSerializationContext.SerializationPair<Object> serializationPair
) {
return RedisCacheConfiguration.defaultCacheConfig()
.disableCachingNullValues()
.entryTtl(Duration.ofSeconds(ttl))
.serializeValuesWith(serializationPair);
}
}

Injecting IOptions<> into ApiKeyAuthorizeAttribute

I am using options pattern that stores different configurations, including API keys for different environments. So far I have been using it fine and injecting my values into classes as needed.
However, I faced a little challenge while trying to setup authorization in the controller and run validation against my ApiKey that is unique per environment, because I was not able to inject IOptions into ApiKeyAuthorizeAttribute class to perform validation.
Here is how my controller looks like now:
[ApiKeyAuthorize]
public class NotificationSettingsController : Controller
{
//some endpoints here
}
ApiKeyAuthorize Class:
public class ApiKeyAuthorizeAttribute : Attribute, IAuthorizationFilter
{
//////This...
private readonly IOptions<MyConfig> _config;
public ApiKeyAuthorizeAttribute(IOptions<MyConfig> config)
{
_config = config;
}
/////////...is what I am trying to accomplish
public void OnAuthorization(AuthorizationFilterContext context)
{
var request = context.HttpContext.Request;
var foundApiKeys = request.Headers.TryGetValue("ReplaceWithOptionsApiKeyName", out var requestApiKeys);
if (!foundApiKeys || requestApiKeys[0] != "ReplaceWithOptionsApiKeyValue")
{
context.Result = new UnauthorizedResult();
}
}
}
My problem is that injecting here isn't possible, but I need to get a value from IOptions<> to run ApiKey validation.
Attributes are constructed in-place, so it's not possible to inject dependencies into them. However, ASP.NET Core provides a workaround. Instead of applying the attribute directly, you can use the ServiceFilter attribute instead and pass it the type of the filter you want to apply:
[ServiceFilter(typeof(ApiAuthorizeAttribute))]
This will dynamically apply the filter to the controller/action while instantiating it with any dependencies it requires at the same time. However, it does limit you in the other direction. For example, if you need to do something like:
[ApiAuthorizeAttribute(Roles = "Admin")]
It would not be possible to achieve this with the ServiceFilter attribute, because you cannot pass property values, like Roles here, along with the type.

How to mock a MyBatis mapper method using JMockit

We have a service component (#service) which internally uses MyBatis to do CRUD operations. All the components are managed by Spring.
Lets assume our MyBatis mapper file
class MyBatisMapper{
public void getData(Map<String,Object> arg);
}
In our mybatis xml file,we have element defined for a callable statement. arg is a map which holds IN and OUT parameters.
Our service component is like
#Service("myService")
class MyService{
#Autowired
private MyBatisMapper myMapper;
public void processData(){
Map<String,Object> input = new HashMap<String,Object>();
............
............
myMapper.getDat(input);
Object response = input.get("RESPONSE");
//process response and so on
}
My objective is to write Junits for the service component and don't have to interact with DB. So, I tried to use JMockIt to mock some of the DAO operations
My attempt is ike
#Mocked
#Injectable
private MyBatisMapper myMapper;
#Test
public void testService() {
new NonStrictExpectations(){
{
Map<String,Object> input = new HashMap<String,Object>();
input.put("xxx,"yyy");
myMapper.getData(input);
}
};
}
But when I ran my tests, I noticed that call went through actualy DB , instead of mocked one.
How to make sure only the mocked components gets called, instead of the actual object
#Injectable mock instances only get injected into #Tested objects. And to specify a return value from a mocked method, you need to assign it to the result field. So, the test should look like the following:
#Tested MyService myService;
#Injectable MyBatisMapper myMapper;
#Test
public void testService() {
final Map<String,Object> data = new HashMap<String, Object>();
data.put("RESPONSE", "yyy");
new Expectations() {{
myMapper.getData((Map<String, Object>) any); result = data;
}};
myService.processData();
// Assert some expected outcome.
}
Thank you Rogerio. I tried to follow the approach you mentioned, but still I see the call going to the actual object. There is a point which I did not mention earlier. My project is spring based and the components are all autowired.
My test has
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:spring/test-applicationContext.xml"})
and test-applicationContext.xml has component scan. So I think, Spring is injecting the actual object ignoring the mock instruction.
Am I wrong ?

Looking for a Ninject scope that behaves like InRequestScope

On my service layer I have injected an UnitOfWork and 2 repositories in the constructor. The Unit of Work and repository have an instance of a DbContext I want to share between the two of them. How can I do that with Ninject ? Which scope should be considered ?
I am not in a web application so I can't use InRequestScope.
I try to do something similar... and I am using DI however, I need my UoW to be Disposed and created like this.
using (IUnitOfWork uow = new UnitOfWorkFactory.Create())
{
_testARepository.Insert(a);
_testBRepository.Insert(b);
uow.SaveChanges();
}
EDIT: I just want to be sure i understand… after look at https://github.com/ninject/ninject.extensions.namedscope/wiki/InNamedScope i though about my current console application architecture which actually use Ninject.
Lets say :
Class A is a Service layer class
Class B is an unit of work which take into parameter an interface (IContextFactory)
Class C is a repository which take into parameter an interface (IContextFactory)
The idea here is to be able to do context operations on 2 or more repository and using the unit of work to apply the changes.
Class D is a context factory (Entity Framework) which provide an instance (keep in a container) of the context which is shared between Class B et C (.. and would be for other repositories aswell).
The context factory keep the instance in his container so i don’t want to reuse this instance all the name since the context need to be disposed at the end of the service operaiton.. it is the main purpose of the InNamedScope actually ?
The solution would be but i am not sure at all i am doing it right, the services instance gonna be transcient which mean they actually never disposed ? :
Bind<IScsContextFactory>()
.To<ScsContextFactory>()
.InNamedScope("ServiceScope")
.WithConstructorArgument(
"connectionString",
ConfigurationUtility.GetConnectionString());
Bind<IUnitOfWork>().To<ScsUnitOfWork>();
Bind<IAccountRepository>().To<AccountRepository>();
Bind<IBlockedIpRepository>().To<BlockedIpRepository>();
Bind<IAccountService>().To<AccountService>().DefinesNamedScope("ServiceScope");
Bind<IBlockedIpService>().To<BlockedIpService>().DefinesNamedScope("ServiceScope");
UPDATE: This approach works against NuGet current, but relies in an anomaly in the InCallscope implementation which has been fixed in the current Unstable NuGet packages. I'll be tweaking this answer in a few days to reflect the best approach after some mulling over. NB the high level way of structuring stuff will stay pretty much identical, just the exact details of the Bind<DbContext>() scoping will work. (Hint: CreateNamedScope in unstable would work or one could set up the Command Handler as DefinesNamedScope. Reason I dont just do that is that I want to have something that composes/plays well with InRequestScope)
I highly recommend reading the Ninject.Extensions.NamedScope integration tests (seriously, find them and read and re-read them)
The DbContext is a Unit Of Work so no further wrapping is necessary.
As you want to be able to have multiple 'requests' in flight and want to have a single Unit of Work shared between them, you need to:
Bind<DbContext>()
.ToMethod( ctx =>
new DbContext(
connectionStringName: ConfigurationUtility.GetConnectionString() ))
.InCallScope();
The InCallScope() means that:
for a given object graph composed for a single kernel.Get() Call (hence In Call Scope), everyone that requires an DbContext will get the same instance.
the IDisposable.Dispose() will be called when a Kernel.Release() happens for the root object (or a Kernel.Components.Get<ICache>().Clear() happens for the root if it is not .InCallScope())
There should be no reason to use InNamedScope() and DefinesNamedScope(); You don't have long-lived objects you're trying to exclude from the default pooling / parenting / grouping.
If you do the above, you should be able to:
var command = kernel.Get<ICommand>();
try {
command.Execute();
} finally {
kernel.Components.Get<ICache>().Clear( command ); // Dispose of DbContext happens here
}
The Command implementation looks like:
class Command : ICommand {
readonly IAccountRepository _ar;
readonly IBlockedIpRepository _br;
readonly DbContext _ctx;
public Command(IAccountRepository ar, IBlockedIpRepository br, DbContext ctx){
_ar = ar;
_br = br;
_ctx = ctx;
}
void ICommand.Execute(){
_ar.Insert(a);
_br.Insert(b);
_ctx.saveChanges();
}
}
Note that in general, I avoid having an implicit Unit of Work in this way, and instead surface it's creation and Disposal. This makes a Command look like this:
class Command : ICommand {
readonly IAccountService _as;
readonly IBlockedIpService _bs;
readonly Func<DbContext> _createContext;
public Command(IAccountService #as, IBlockedIpServices bs, Func<DbContext> createContext){
_as = #as;
_bs = bs;
_createContext = createContext;
}
void ICommand.Execute(){
using(var ctx = _createContext()) {
_ar.InsertA(ctx);
_br.InsertB(ctx);
ctx.saveChanges();
}
}
This involves no usage of .InCallScope() on the Bind<DbContext>() (but does require the presence of Ninject.Extensions.Factory's FactoryModule to synthesize the Func<DbContext> from a straightforward Bind<DbContext>().
As discussed in the other answer, InCallScope is not a good approach to solving this problem.
For now I'm dumping some code that works against the latest NuGet Unstable / Include PreRelease / Instal-Package -Pre editions of Ninject.Web.Common without a clear explanation. I will translate this to an article in the Ninject.Extensions.NamedScope wiki at some stagehave started to write a walkthrough of this technique in the Ninject.Extensions.NamedScope wiki's CreateNamedScope/GetScope article.
Possibly some bits will become Pull Request(s) at some stage too (Hat tip to #Remo Gloor who supplied me the outline code). The associated tests and learning tests are in this gist for now), pending packaging in a proper released format TBD.
The exec summary is you Load the Module below into your Kernel and use .InRequestScope() on everything you want created / Disposed per handler invocation and then feed requests through via IHandlerComposer.ComposeCallDispose.
If you use the following Module:
public class Module : NinjectModule
{
public override void Load()
{
Bind<IHandlerComposer>().To<NinjectRequestScopedHandlerComposer>();
// Wire it up so InRequestScope will work for Handler scopes
Bind<INinjectRequestHandlerScopeFactory>().To<NinjectRequestHandlerScopeFactory>();
NinjectRequestHandlerScopeFactory.NinjectHttpApplicationPlugin.RegisterIn( Kernel );
}
}
Which wires in a Factory[1] and NinjectHttpApplicationPlugin that exposes:
public interface INinjectRequestHandlerScopeFactory
{
NamedScope CreateRequestHandlerScope();
}
Then you can use this Composer to Run a Request InRequestScope():
public interface IHandlerComposer
{
void ComposeCallDispose( Type type, Action<object> callback );
}
Implemented as:
class NinjectRequestScopedHandlerComposer : IHandlerComposer
{
readonly INinjectRequestHandlerScopeFactory _requestHandlerScopeFactory;
public NinjectRequestScopedHandlerComposer( INinjectRequestHandlerScopeFactory requestHandlerScopeFactory )
{
_requestHandlerScopeFactory = requestHandlerScopeFactory;
}
void IHandlerComposer.ComposeCallDispose( Type handlerType, Action<object> callback )
{
using ( var resolutionRoot = _requestHandlerScopeFactory.CreateRequestHandlerScope() )
foreach ( object handler in resolutionRoot.GetAll( handlerType ) )
callback( handler );
}
}
The Ninject Infrastructure stuff:
class NinjectRequestHandlerScopeFactory : INinjectRequestHandlerScopeFactory
{
internal const string ScopeName = "Handler";
readonly IKernel _kernel;
public NinjectRequestHandlerScopeFactory( IKernel kernel )
{
_kernel = kernel;
}
NamedScope INinjectRequestHandlerScopeFactory.CreateRequestHandlerScope()
{
return _kernel.CreateNamedScope( ScopeName );
}
/// <summary>
/// When plugged in as a Ninject Kernel Component via <c>RegisterIn(IKernel)</c>, makes the Named Scope generated during IHandlerFactory.RunAndDispose available for use via the Ninject.Web.Common's <c>.InRequestScope()</c> Binding extension.
/// </summary>
public class NinjectHttpApplicationPlugin : NinjectComponent, INinjectHttpApplicationPlugin
{
readonly IKernel kernel;
public static void RegisterIn( IKernel kernel )
{
kernel.Components.Add<INinjectHttpApplicationPlugin, NinjectHttpApplicationPlugin>();
}
public NinjectHttpApplicationPlugin( IKernel kernel )
{
this.kernel = kernel;
}
object INinjectHttpApplicationPlugin.GetRequestScope( IContext context )
{
// TODO PR for TrgGetScope
try
{
return NamedScopeExtensionMethods.GetScope( context, ScopeName );
}
catch ( UnknownScopeException )
{
return null;
}
}
void INinjectHttpApplicationPlugin.Start()
{
}
void INinjectHttpApplicationPlugin.Stop()
{
}
}
}

How to change configs in Spring.Net

An advantage of an IoC container is that you can swap in a mock service at the bottom of your object graph. However this seems much harder to do in Spring.Net than in other IoC Containers. Here's some code that does it in Unity and has Spring.Net code;
namespace IocSpringDemo
{
using Microsoft.Practices.Unity;
using NUnit.Framework;
using Spring.Context;
using Spring.Context.Support;
public interface ISomeService
{
string DoSomething();
}
public class ServiceImplementationA : ISomeService
{
public string DoSomething()
{
return "Hello A";
}
}
public class ServiceImplementationB : ISomeService
{
public string DoSomething()
{
return "Hello B";
}
}
public class RootObject
{
public ISomeService SomeService { get; private set; }
public RootObject(ISomeService service)
{
SomeService = service;
}
}
[TestFixture]
public class UnityAndSpringDemo
{
[Test]
public void UnityResolveA()
{
UnityContainer container = new UnityContainer();
container.RegisterType<ISomeService, ServiceImplementationA>();
RootObject rootObject = container.Resolve<RootObject>();
Assert.AreEqual("Hello A", rootObject.SomeService.DoSomething());
}
[Test]
public void UnityResolveB()
{
UnityContainer container = new UnityContainer();
container.RegisterType<ISomeService, ServiceImplementationB>();
RootObject rootObject = container.Resolve<RootObject>();
Assert.AreEqual("Hello B", rootObject.SomeService.DoSomething());
}
[Test]
public void SpringResolveA()
{
IApplicationContext container = ContextRegistry.GetContext();
RootObject rootObject = (RootObject)container.GetObject("RootObject");
Assert.AreEqual("Hello A", rootObject.SomeService.DoSomething());
}
[Test]
public void SpringResolveB()
{
// does not work - what to do to make this pass?
IApplicationContext container = ContextRegistry.GetContext();
RootObject rootObject = (RootObject)container.GetObject("RootObject");
Assert.AreEqual("Hello B", rootObject.SomeService.DoSomething());
}
}
}
For the benefit of Spring, the following needed to be in the App.config file. Clearly this only serves the first spring test, and not the second. Can you put multiple spring configurations in the config file? If so, what is the syntax and how do you access them? Or is there another way to do this?
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<object name="RootObject" type="IocSpringDemo.RootObject, IocDemo" autowire="constructor" />
<object name="service" type="IocSpringDemo.ServiceImplementationA, IocDemo" autowire="constructor" />
</objects>
</spring>
Update
Here is a partial answer based at code at the links that Marko Lahma gave to Mark Pollack's blog. I have the above tests passing, with the following code:
public static class SpringHelper
{
public static T Resolve<T>(this IApplicationContext context, string name)
{
return (T)context.GetObject(name);
}
public static void RegisterType<T>(this GenericApplicationContext context, string name)
{
context.RegisterType(name, typeof(T));
}
public static void RegisterType(this GenericApplicationContext context, string name, Type type)
{
IObjectDefinitionFactory objectDefinitionFactory = new DefaultObjectDefinitionFactory();
ObjectDefinitionBuilder builder = ObjectDefinitionBuilder.RootObjectDefinition(objectDefinitionFactory, type);
builder.SetAutowireMode(AutoWiringMode.AutoDetect);
context.RegisterObjectDefinition(name, builder.ObjectDefinition);
}
}
...
[Test]
public void SpringResolveA()
{
GenericApplicationContext container = new GenericApplicationContext();
container.RegisterType<RootObject>("RootObject");
container.RegisterType<ServiceImplementationA>("service");
RootObject rootObject = container.Resolve<RootObject>("RootObject");
Assert.AreEqual("Hello A", rootObject.SomeService.DoSomething());
}
[Test]
public void SpringResolveB()
{
GenericApplicationContext container = new GenericApplicationContext();
container.RegisterType<RootObject>("RootObject");
container.RegisterType<ServiceImplementationB>("service");
RootObject rootObject = container.Resolve<RootObject>("RootObject");
Assert.AreEqual("Hello B", rootObject.SomeService.DoSomething());
}
This raises a few questions to me:
I want to integrate this technique into existing code that uses the usual container. Why do I have to use a different container type, GenericApplicationContext in this case? What if I want to read data into this object from the existing spring config in app.config or web.config? Would it work as the usual context? Could I then write data over these registrations with code?
How can I specify that ISomeService is to be created as a singleton? I don't mean supply a singleton instance to the container, but the container to create the instance, resolving its constructor, and use it when that type is needed.
how can I do the equivalent of container.RegisterType<ISomeService, ServiceImplementationA>(); ? I want to register type mappings to use in all cases where that type is needed by a constructor.
What exactly does container.RegisterType<ServiceImplementationA>("service"); do? It seems to register ServiceImplementationA as the implementation of ISomeService but ISomeServiceis never mentioned, so there could be ambiguity. e.g. what if ServiceImplementationA implemented more than one interface.
What is the string name given to the registration for? It won't work with en empty string, but it doesn't seem to matter what it is.
Am I trying to use spring in a way that it just does not work? I'm trying to use it like other IoC containers, but it's not quite working.
Adding as new answer trying to address the open points...
I want to integrate this technique
into existing code that uses the usual
container. Why do I have to use a
different container type,
GenericApplicationContext in this
case? What if I want to read data into
this object from the existing spring
config in app.config or web.config?
Would it work as the usual context?
Could I then write data over these
registrations with code?
Spring has concrete application context implementations for different kind of initialization tactics. The most common ones to use are GenericApplicationContext (manual), XmlApplicationContext (XML files) and WebApplicationContext (very much like XmlApplicationContext but tailored for web use). They all implement common interface: IApplicationContext which is the preferred way to access these containers.
Unfortonately altering registrations with code usually means that you need to use the specific sub-class directly. With GenericApplicationContext and StaticApplicationContext this is quite natural but XmlApplicationContext is usually considered to be XML only and this ways "fixed" to XML definition.
How can I specify that ISomeService is
to be created as a singleton? I don't
mean supply a singleton instance to
the container, but the container to
create the instance, resolving its
constructor, and use it when that type
is needed.
Your SpringHelper does just that, by default all objects in Spring are singletons. You could alter this behavior by calling ObjectDefinitionBuilder's SetSingleton method with false.
how can I do the equivalent of
container.RegisterType(); ? I want to
register type mappings to use in all
cases where that type is needed by a
constructor.
Spring uses object names (ids) to distinct between different implementations. So if you want to get specific type to serve a specific instance in case that there are many alternatives you should refer to this specific instance by name. If you are using autowiring and your object has dependency to interface ISomeService and there's only one object registered that implements it, the autowiring can set it without ambiguity.
What exactly does
container.RegisterType("service");
do? It seems to register
ServiceImplementationA as the
implementation of ISomeService but
ISomeServiceis never mentioned, so
there could be ambiguity. e.g. what if
ServiceImplementationA implemented
more than one interface.
Continuing from previous answer, this registers singleton of type ServiceImplementationA with name "service". This object comes autowiring candidate with all it's implemented interfaces (and with it's concrete type of course).
What is the string name given to the
registration for? It won't work with
en empty string, but it doesn't seem
to matter what it is.
It matters a great deal as explained earlier. The name is unique id within that context (parent context could have object with same name) and can be used to access specific object registrations. In short where other frameworks may associate a type as key to object registration, Spring uses name.
That's a bit apples and oranges comparison as the unit test uses code configuration for Unity and XML (app.config) configuration for Spring.NET.
If you go the XML route, then you can either comment out old implementation A and define the B implementation as the one to use - that what's configuration is all about right? Other option is to have dedicated XML files for each scenario (configuration setup) and include them via context's resource definitions (you have inline resource now). Other options include file system and assembly, see the web configuration section in Spring.NET's manual for a nice example.
If you go the code configuration route I would suggest to check Spring.NET Recoil and upcoming CodeConfig.