blob: 0dd2627cac108c74d0d80ea25e0d4548921b6716 [file] [log] [blame]
/*
* Copyright 2009 Niclas Hedhman.
* Copyright 2012 Paul Merlin.
*
* 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.qi4j.runtime.service;
import java.util.ArrayList;
import org.junit.Test;
import org.qi4j.api.activation.ActivatorAdapter;
import org.qi4j.api.activation.PassivationException;
import org.qi4j.api.mixin.Mixins;
import org.qi4j.api.service.ServiceComposite;
import org.qi4j.api.service.ServiceReference;
import org.qi4j.bootstrap.AssemblyException;
import org.qi4j.bootstrap.ModuleAssembly;
import org.qi4j.bootstrap.SingletonAssembler;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class PassivationTest
{
@Test
public void givenSuccessPassivationWhenPassivatingExpectNoExceptions()
throws Throwable
{
SingletonAssembler assembly = new SingletonAssembler()
{
public void assemble( ModuleAssembly module )
throws AssemblyException
{
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
}
};
Iterable<ServiceReference<DataAccess>> iterable = assembly.module().findServices( DataAccess.class );
for( ServiceReference<DataAccess> service : iterable )
{
assertTrue( "Service should not be Active before accessed", !service.isActive() );
assertTrue( service.get().data().activated );
assertTrue( "Service should be Active after access.", service.isActive() );
}
assembly.application().passivate();
}
@Test
public void givenMixedSuccessFailurePassivationWhenPassivatingExpectAllPassivateMethodsToBeCalled()
throws Exception
{
SingletonAssembler assembly = new SingletonAssembler()
{
public void assemble( ModuleAssembly module )
throws AssemblyException
{
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
}
};
ArrayList<Data> datas = new ArrayList<Data>();
Iterable<ServiceReference<DataAccess>> iterable = assembly.module().findServices( DataAccess.class );
for( ServiceReference<DataAccess> service : iterable )
{
assertTrue( "Service should not be Active before accessed", !service.isActive() );
Data data = service.get().data();
if( DataAccessService.class.isInstance( service.get() ) )
{
// Collect the expected successes.
datas.add( data );
}
assertTrue( "Data should indicate that the service is activated", data.activated );
assertTrue( "Service should be Active after access.", service.isActive() );
}
try
{
assembly.application().passivate();
fail( "PassivationException should have been thrown." );
}
catch( PassivationException e )
{
// Expected
}
// Still ensure that all services have been shutdown.
for( ServiceReference<DataAccess> service : iterable )
{
assertFalse( "All services should have been shutdown", service.isActive() );
}
}
@Test(expected = PassivationException.class)
public void givenMultipleFailingPassivationWhenPassivatingExpectPassivationExceptionToBubbleUp()
throws Exception
{
SingletonAssembler assembly = new SingletonAssembler()
{
public void assemble( ModuleAssembly module )
throws AssemblyException
{
module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
}
};
Iterable<ServiceReference<DataAccess>> iterable = assembly.module().findServices( DataAccess.class );
for( ServiceReference<DataAccess> service : iterable )
{
assertTrue( "Service should not be Active before accessed", !service.isActive() );
assertTrue( service.get().data().activated );
assertTrue( "Service should be Active after access.", service.isActive() );
}
assembly.application().passivate();
}
@Mixins(DataAccessMixin.class)
public interface DataAccessService
extends DataAccess, ServiceComposite
{
}
public interface DataAccess
{
Data data();
}
public static class DataAccessMixin
implements DataAccess
{
Data data = new Data();
public Data data()
{
return data;
}
}
public static class PassivationSuccessActivator
extends ActivatorAdapter<ServiceReference<DataAccess>>
{
@Override
public void afterActivation( ServiceReference<DataAccess> activated )
throws Exception
{
activated.get().data().activated = true;
}
@Override
public void beforePassivation( ServiceReference<DataAccess> passivating )
throws Exception
{
passivating.get().data().activated = false;
}
}
public static class PassivationFailureActivator
extends ActivatorAdapter<ServiceReference<DataAccess>>
{
@Override
public void afterActivation( ServiceReference<DataAccess> activated )
throws Exception
{
activated.get().data().activated = true;
}
@Override
public void beforePassivation( ServiceReference<DataAccess> passivating )
throws Exception
{
throw new IllegalStateException();
}
}
public static class Data
{
boolean activated = false;
}
}