| /* |
| * 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; |
| } |
| } |