src/main/java/js/container/ManagedClass.java
private void scanAnnotations() {
		// set remote type and request URI path from @Remote, @Controller or @Service
		boolean remoteType = false;
		Controller controllerAnnotation = getAnnotation(implementationClass, Controller.class);
		if (controllerAnnotation != null) {
			remoteType = true;
			requestPath = controllerAnnotation.value();
		}
		Service serviceAnnotation = getAnnotation(implementationClass, Service.class);
		if (serviceAnnotation != null) {
			remoteType = true;
			requestPath = serviceAnnotation.value();
		}

		Remote remoteAnnotation = getAnnotation(implementationClass, Remote.class);
		if (remoteAnnotation != null) {
			remoteType = true;
		}
		RequestPath requestPathAnnotation = getAnnotation(implementationClass, RequestPath.class);
		if (requestPathAnnotation != null) {
			requestPath = requestPathAnnotation.value();
		}

		if (requestPath != null && requestPath.isEmpty()) {
			requestPath = null;
		}
		if (remoteType) {
			remotelyAccessible = true;
		}

		// set transactional and immutable type
		boolean transactionalType = hasAnnotation(implementationClass, Transactional.class);
		boolean immutableType = hasAnnotation(implementationClass, Immutable.class);
		if (!transactionalType && immutableType) {
			throw new BugError("@Immutable annotation without @Transactional on class |%s|.", implementationClass.getName());
		}
		if (transactionalType && !instanceType.isPROXY()) {
			throw new BugError("@Transactional requires |%s| type but found |%s| on |%s|.", InstanceType.PROXY, instanceType, implementationClass);
		}

		Class<? extends Interceptor> classInterceptor = getInterceptorClass(implementationClass);
		boolean publicType = hasAnnotation(implementationClass, Public.class);

		// managed classes does not support public inheritance
		for (Method method : implementationClass.getDeclaredMethods()) {
			final int modifiers = method.getModifiers();
			if (Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
				// scans only public and non-static methods
				continue;
			}
			Method interfaceMethod = getInterfaceMethod(method);
			ManagedMethod managedMethod = null;

			boolean remoteMethod = hasAnnotation(method, Remote.class);
			if (!remoteMethod) {
				remoteMethod = remoteType;
			}
			if (hasAnnotation(method, Local.class)) {
				if (!remoteMethod) {
					throw new BugError("@Local annotation on not remote method |%s|.", method);
				}
				remoteMethod = false;
			}
			if (remoteMethod) {
				// if at least one owned managed method is remote this managed class become remote too
				remotelyAccessible = true;
			}

			// load method interceptor annotation and if missing uses class annotation; is legal for both to be null
			Class<? extends Interceptor> methodInterceptor = getInterceptorClass(method);
			if (methodInterceptor == null) {
				methodInterceptor = classInterceptor;
			}
			// if method is intercepted, either by method or class annotation, create intercepted managed method
			if (methodInterceptor != null) {
				if (!instanceType.isPROXY() && !remotelyAccessible) {
					throw new BugError("@Intercepted method |%s| supported only on PROXY type or remote accessible classes.", method);
				}
				managedMethod = new ManagedMethod(this, methodInterceptor, interfaceMethod);
			}

			// handle remote accessible methods

			boolean publicMethod = hasAnnotation(method, Public.class);
			if (publicMethod && !remotelyAccessible) {
				throw new BugError("@Public annotation on not remote method |%s|.", method);
			}
			if (!publicMethod) {
				publicMethod = publicType;
			}
			if (hasAnnotation(method, Private.class)) {
				if (!remotelyAccessible) {
					throw new BugError("@Private annotation on not remote method |%s|.", method);
				}
				publicMethod = false;
			}
			RequestPath methodPath = getAnnotation(method, RequestPath.class);
			if (!remotelyAccessible && methodPath != null) {
				throw new BugError("@MethodPath annotation on not remote method |%s|.", method);
			}
			if (remoteMethod) {
				if (managedMethod == null) {
					managedMethod = new ManagedMethod(this, interfaceMethod);
				}
				managedMethod.setRequestPath(methodPath != null ? methodPath.value() : null);
				managedMethod.setRemotelyAccessible(remoteMethod);
				managedMethod.setAccess(publicMethod ? Access.PUBLIC : Access.PRIVATE);
			}

			// handle declarative transaction
			// 1. allow transactional only on PROXY
			// 2. do not allow immutable on method if not transactional
			// 3. do not allow mutable on method if not transactional
			// 4. if PROXY create managed method if not already created from above remote method logic

			if (!transactionalType) {
				transactionalType = hasAnnotation(method, Transactional.class);
			}
			if (transactionalType) {
				transactional = true;
				if (!instanceType.isPROXY()) {
					throw new BugError("@Transactional requires |%s| type but found |%s|.", InstanceType.PROXY, instanceType);
				}
			}

			boolean immutable = hasAnnotation(method, Immutable.class);
			if (immutable && !transactional) {
				log.debug("@Immutable annotation without @Transactional on method |%s|.", method);
			}
			if (!immutable) {
				immutable = immutableType;
			}
			if (hasAnnotation(method, Mutable.class)) {
				if (!transactional) {
					log.debug("@Mutable annotation without @Transactional on method |%s|.", method);
				}
				immutable = false;
			}

			if (instanceType.isPROXY() && managedMethod == null) {
				managedMethod = new ManagedMethod(this, interfaceMethod);
			}
			if (transactional) {
				managedMethod.setTransactional(true);
				managedMethod.setImmutable(immutable);
			}

			// handle asynchronous mode
			// 1. instance type should be PROXY or managed class should be flagged for remote access
			// 2. transactional method cannot be executed asynchronously
			// 3. asynchronous method should be void

			boolean asynchronousMethod = hasAnnotation(method, Asynchronous.class);
			if (asynchronousMethod) {
				if (!instanceType.isPROXY() && !remotelyAccessible) {
					throw new BugError("Not supported instance type |%s| for asynchronous method |%s|.", instanceType, method);
				}
				if (transactional) {
					throw new BugError("Transactional method |%s| cannot be executed asynchronous.", method);
				}
				if (!Types.isVoid(method.getReturnType())) {
					throw new BugError("Asynchronous method |%s| must be void.", method);
				}

				// at this point either instance type is PROXY or remote flag is true; checked by above bug error
				// both conditions has been already processed with managed method creation
				// so managed method must be already created
				managedMethod.setAsynchronous(asynchronousMethod);
			}

			Cron cronMethod = getAnnotation(method, Cron.class);
			if (cronMethod != null) {
				// if (!instanceType.isPROXY()) {
				// throw new BugError("Not supported instance type |%s| for cron method |%s|.", instanceType, method);
				// }
				if (remotelyAccessible) {
					throw new BugError("Remote accessible method |%s| cannot be executed by cron.", method);
				}
				if (transactional) {
					throw new BugError("Transactional method |%s| cannot be executed by cron.", method);
				}
				if (!Types.isVoid(method.getReturnType())) {
					throw new BugError("Cron method |%s| must be void.", method);
				}

				if (managedMethod == null) {
					managedMethod = new ManagedMethod(this, interfaceMethod);
				}
				managedMethod.setCronExpression(cronMethod.value());
				cronMethodsPool.add(managedMethod);
				autoInstanceCreation = true;
			}

			// store managed method, if created, to managed methods pool
			if (managedMethod != null) {
				methodsPool.put(interfaceMethod, managedMethod);
				if (managedMethod.isRemotelyAccessible() && netMethodsPool.put(method.getName(), managedMethod) != null) {
					throw new BugError("Overloading is not supported for net method |%s|.", managedMethod);
				}
			}
		}

		for (Field field : implementationClass.getDeclaredFields()) {
			ContextParam contextParam = field.getAnnotation(ContextParam.class);
			if (contextParam != null) {
				field.setAccessible(true);
				contextParamFields.put(contextParam.value(), field);
			}
		}
	}
private void scanAnnotations() {
		// set remote type and request URI path from @Remote, @Controller or @Service
		boolean remoteType = false;
		Controller controllerAnnotation = getAnnotation(implementationClass, Controller.class);
		if (controllerAnnotation != null) {
			remoteType = true;
			requestPath = controllerAnnotation.value();
		}
		Service serviceAnnotation = getAnnotation(implementationClass, Service.class);
		if (serviceAnnotation != null) {
			remoteType = true;
			requestPath = serviceAnnotation.value();
		}

		Remote remoteAnnotation = getAnnotation(implementationClass, Remote.class);
		if (remoteAnnotation != null) {
			remoteType = true;
		}
		RequestPath requestPathAnnotation = getAnnotation(implementationClass, RequestPath.class);
		if (requestPathAnnotation != null) {
			requestPath = requestPathAnnotation.value();
		}

		if (requestPath != null && requestPath.isEmpty()) {
			requestPath = null;
		}
		if (remoteType) {
			remotelyAccessible = true;
		}

		// set transactional and immutable type
		boolean transactionalType = hasAnnotation(implementationClass, Transactional.class);
		boolean immutableType = hasAnnotation(implementationClass, Immutable.class);
		if (!transactionalType && immutableType) {
			throw new BugError("@Immutable annotation without @Transactional on class |%s|.", implementationClass.getName());
		}
		if (transactionalType && !instanceType.isPROXY()) {
			throw new BugError("@Transactional requires |%s| type but found |%s| on |%s|.", InstanceType.PROXY, instanceType, implementationClass);
		}

		Class<? extends Interceptor> classInterceptor = getInterceptorClass(implementationClass);
		boolean publicType = hasAnnotation(implementationClass, Public.class);

		// managed classes does not support public inheritance
		for (Method method : implementationClass.getDeclaredMethods()) {
			final int modifiers = method.getModifiers();
			if (Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
				// scans only public and non-static methods
				continue;
			}
			Method interfaceMethod = getInterfaceMethod(method);
			ManagedMethod managedMethod = null;

			boolean remoteMethod = hasAnnotation(method, Remote.class);
			if (!remoteMethod) {
				remoteMethod = remoteType;
			}
			if (hasAnnotation(method, Local.class)) {
				if (!remoteMethod) {
					throw new BugError("@Local annotation on not remote method |%s|.", method);
				}
				remoteMethod = false;
			}
			if (remoteMethod) {
				// if at least one owned managed method is remote this managed class become remote too
				remotelyAccessible = true;
			}

			// load method interceptor annotation and if missing uses class annotation; is legal for both to be null
			Class<? extends Interceptor> methodInterceptor = getInterceptorClass(method);
			if (methodInterceptor == null) {
				methodInterceptor = classInterceptor;
			}
			// if method is intercepted, either by method or class annotation, create intercepted managed method
			if (methodInterceptor != null) {
				if (!instanceType.isPROXY() && !remotelyAccessible) {
					throw new BugError("@Intercepted method |%s| supported only on PROXY type or remote accessible classes.", method);
				}
				managedMethod = new ManagedMethod(this, methodInterceptor, interfaceMethod);
			}

			// handle remote accessible methods

			boolean publicMethod = hasAnnotation(method, Public.class);
			if (publicMethod && !remotelyAccessible) {
				throw new BugError("@Public annotation on not remote method |%s|.", method);
			}
			if (!publicMethod) {
				publicMethod = publicType;
			}
			if (hasAnnotation(method, Private.class)) {
				if (!remotelyAccessible) {
					throw new BugError("@Private annotation on not remote method |%s|.", method);
				}
				publicMethod = false;
			}
			RequestPath methodPath = getAnnotation(method, RequestPath.class);
			if (!remotelyAccessible && methodPath != null) {
				throw new BugError("@MethodPath annotation on not remote method |%s|.", method);
			}
			if (remoteMethod) {
				if (managedMethod == null) {
					managedMethod = new ManagedMethod(this, interfaceMethod);
				}
				managedMethod.setRequestPath(methodPath != null ? methodPath.value() : null);
				managedMethod.setRemotelyAccessible(remoteMethod);
				managedMethod.setAccess(publicMethod ? Access.PUBLIC : Access.PRIVATE);
			}

			// handle declarative transaction
			// 1. allow transactional only on PROXY
			// 2. do not allow immutable on method if not transactional
			// 3. do not allow mutable on method if not transactional
			// 4. if PROXY create managed method if not already created from above remote method logic

			if (!transactionalType) {
				transactionalType = hasAnnotation(method, Transactional.class);
			}
			if (transactionalType) {
				transactional = true;
				if (!instanceType.isPROXY()) {
					throw new BugError("@Transactional requires |%s| type but found |%s|.", InstanceType.PROXY, instanceType);
				}
			}

			boolean immutable = hasAnnotation(method, Immutable.class);
			if (immutable && !transactional) {
				log.debug("@Immutable annotation without @Transactional on method |%s|.", method);
			}
			if (!immutable) {
				immutable = immutableType;
			}
			if (hasAnnotation(method, Mutable.class)) {
				if (!transactional) {
					log.debug("@Mutable annotation without @Transactional on method |%s|.", method);
				}
				immutable = false;
			}

			if (instanceType.isPROXY() && managedMethod == null) {
				managedMethod = new ManagedMethod(this, interfaceMethod);
			}
			if (transactional) {
				managedMethod.setTransactional(true);
				managedMethod.setImmutable(immutable);
			}

			// handle asynchronous mode
			// 1. instance type should be PROXY or managed class should be flagged for remote access
			// 2. transactional method cannot be executed asynchronously
			// 3. asynchronous method should be void

			boolean asynchronousMethod = hasAnnotation(method, Asynchronous.class);
			if (asynchronousMethod) {
				if (!instanceType.isPROXY() && !remotelyAccessible) {
					throw new BugError("Not supported instance type |%s| for asynchronous method |%s|.", instanceType, method);
				}
				if (transactional) {
					throw new BugError("Transactional method |%s| cannot be executed asynchronous.", method);
				}
				if (!Types.isVoid(method.getReturnType())) {
					throw new BugError("Asynchronous method |%s| must be void.", method);
				}

				// at this point either instance type is PROXY or remote flag is true; checked by above bug error
				// both conditions has been already processed with managed method creation
				// so managed method must be already created
				managedMethod.setAsynchronous(asynchronousMethod);
			}

			Cron cronMethod = getAnnotation(method, Cron.class);
			if (cronMethod != null) {
				// if (!instanceType.isPROXY()) {
				// throw new BugError("Not supported instance type |%s| for cron method |%s|.", instanceType, method);
				// }
				if (remotelyAccessible) {
					throw new BugError("Remote accessible method |%s| cannot be executed by cron.", method);
				}
				if (transactional) {
					throw new BugError("Transactional method |%s| cannot be executed by cron.", method);
				}
				if (!Types.isVoid(method.getReturnType())) {
					throw new BugError("Cron method |%s| must be void.", method);
				}

				if (managedMethod == null) {
					managedMethod = new ManagedMethod(this, interfaceMethod);
				}
				managedMethod.setCronExpression(cronMethod.value());
				cronMethodsPool.add(managedMethod);
				autoInstanceCreation = true;
			}

			// store managed method, if created, to managed methods pool
			if (managedMethod != null) {
				methodsPool.put(interfaceMethod, managedMethod);
				if (managedMethod.isRemotelyAccessible() && netMethodsPool.put(method.getName(), managedMethod) != null) {
					throw new BugError("Overloading is not supported for net method |%s|.", managedMethod);
				}
			}
		}

		for (Field field : implementationClass.getDeclaredFields()) {
			ContextParam contextParam = field.getAnnotation(ContextParam.class);
			if (contextParam != null) {
				field.setAccessible(true);
				contextParamFields.put(contextParam.value(), field);
			}
		}
	}
private void scanAnnotations ( ) { // set remote type and request URI path from @Remote, @Controller or @Service
 boolean remoteType = false ; Controller controllerAnnotation = getAnnotation ( implementationClass , Controller . class ) ; if ( controllerAnnotation != null ) { remoteType = true ; requestPath = controllerAnnotation . value ( ) ; } Service serviceAnnotation = getAnnotation ( implementationClass , Service . class ) ; if ( serviceAnnotation != null ) { remoteType = true ; requestPath = serviceAnnotation . value ( ) ; } Remote remoteAnnotation = getAnnotation ( implementationClass , Remote . class ) ; if ( remoteAnnotation != null ) { remoteType = true ; } RequestPath requestPathAnnotation = getAnnotation ( implementationClass , RequestPath . class ) ; if ( requestPathAnnotation != null ) { requestPath = requestPathAnnotation . value ( ) ; } if ( requestPath != null && requestPath . isEmpty ( ) ) { requestPath = null ; } if ( remoteType ) { remotelyAccessible = true ; } // set transactional and immutable type
 boolean transactionalType = hasAnnotation ( implementationClass , Transactional . class ) ; boolean immutableType = hasAnnotation ( implementationClass , Immutable . class ) ; if ( ! transactionalType && immutableType ) { throw new BugError ( "@Immutable annotation without @Transactional on class |%s|." , implementationClass . getName ( ) ) ; } if ( transactionalType && ! instanceType . isPROXY ( ) ) { throw new BugError ( "@Transactional requires |%s| type but found |%s| on |%s|." , InstanceType . PROXY , instanceType , implementationClass ) ; } Class < ? extends Interceptor > classInterceptor = getInterceptorClass ( implementationClass ) ; boolean publicType = hasAnnotation ( implementationClass , Public . class ) ; // managed classes does not support public inheritance
 for ( Method method : implementationClass . getDeclaredMethods ( ) ) { final int modifiers = method . getModifiers ( ) ; if ( Modifier . isStatic ( modifiers ) || ! Modifier . isPublic ( modifiers ) ) { // scans only public and non-static methods
 continue ; } Method interfaceMethod = getInterfaceMethod ( method ) ; ManagedMethod managedMethod = null ; boolean remoteMethod = hasAnnotation ( method , Remote . class ) ; if ( ! remoteMethod ) { remoteMethod = remoteType ; } if ( hasAnnotation ( method , Local . class ) ) { if ( ! remoteMethod ) { throw new BugError ( "@Local annotation on not remote method |%s|." , method ) ; } remoteMethod = false ; } if ( remoteMethod ) { // if at least one owned managed method is remote this managed class become remote too
 remotelyAccessible = true ; } // load method interceptor annotation and if missing uses class annotation; is legal for both to be null
 Class < ? extends Interceptor > methodInterceptor = getInterceptorClass ( method ) ; if ( methodInterceptor == null ) { methodInterceptor = classInterceptor ; } // if method is intercepted, either by method or class annotation, create intercepted managed method
 if ( methodInterceptor != null ) { if ( ! instanceType . isPROXY ( ) && ! remotelyAccessible ) { throw new BugError ( "@Intercepted method |%s| supported only on PROXY type or remote accessible classes." , method ) ; } managedMethod = new ManagedMethod ( this , methodInterceptor , interfaceMethod ) ; } // handle remote accessible methods
 boolean publicMethod = hasAnnotation ( method , Public . class ) ; if ( publicMethod && ! remotelyAccessible ) { throw new BugError ( "@Public annotation on not remote method |%s|." , method ) ; } if ( ! publicMethod ) { publicMethod = publicType ; } if ( hasAnnotation ( method , Private . class ) ) { if ( ! remotelyAccessible ) { throw new BugError ( "@Private annotation on not remote method |%s|." , method ) ; } publicMethod = false ; } RequestPath methodPath = getAnnotation ( method , RequestPath . class ) ; if ( ! remotelyAccessible && methodPath != null ) { throw new BugError ( "@MethodPath annotation on not remote method |%s|." , method ) ; } if ( remoteMethod ) { if ( managedMethod == null ) { managedMethod = new ManagedMethod ( this , interfaceMethod ) ; } managedMethod . setRequestPath ( methodPath != null ? methodPath . value ( ) : null ) ; managedMethod . setRemotelyAccessible ( remoteMethod ) ; managedMethod . setAccess ( publicMethod ? Access . PUBLIC : Access . PRIVATE ) ; } // handle declarative transaction
 // 1. allow transactional only on PROXY
 // 2. do not allow immutable on method if not transactional
 // 3. do not allow mutable on method if not transactional
 // 4. if PROXY create managed method if not already created from above remote method logic
 if ( ! transactionalType ) { transactionalType = hasAnnotation ( method , Transactional . class ) ; } if ( transactionalType ) { transactional = true ; if ( ! instanceType . isPROXY ( ) ) { throw new BugError ( "@Transactional requires |%s| type but found |%s|." , InstanceType . PROXY , instanceType ) ; } } boolean immutable = hasAnnotation ( method , Immutable . class ) ; if ( immutable && ! transactional ) { log . debug ( "@Immutable annotation without @Transactional on method |%s|." , method ) ; } if ( ! immutable ) { immutable = immutableType ; } if ( hasAnnotation ( method , Mutable . class ) ) { if ( ! transactional ) { log . debug ( "@Mutable annotation without @Transactional on method |%s|." , method ) ; } immutable = false ; } if ( instanceType . isPROXY ( ) && managedMethod == null ) { managedMethod = new ManagedMethod ( this , interfaceMethod ) ; } if ( transactional ) { managedMethod . setTransactional ( true ) ; managedMethod . setImmutable ( immutable ) ; } // handle asynchronous mode
 // 1. instance type should be PROXY or managed class should be flagged for remote access
 // 2. transactional method cannot be executed asynchronously
 // 3. asynchronous method should be void
 boolean asynchronousMethod = hasAnnotation ( method , Asynchronous . class ) ; if ( asynchronousMethod ) { if ( ! instanceType . isPROXY ( ) && ! remotelyAccessible ) { throw new BugError ( "Not supported instance type |%s| for asynchronous method |%s|." , instanceType , method ) ; } if ( transactional ) { throw new BugError ( "Transactional method |%s| cannot be executed asynchronous." , method ) ; } if ( ! Types . isVoid ( method . getReturnType ( ) ) ) { throw new BugError ( "Asynchronous method |%s| must be void." , method ) ; } // at this point either instance type is PROXY or remote flag is true; checked by above bug error
 // both conditions has been already processed with managed method creation
 // so managed method must be already created
 managedMethod . setAsynchronous ( asynchronousMethod ) ; } Cron cronMethod = getAnnotation ( method , Cron . class ) ; if ( cronMethod != null ) { // if (!instanceType.isPROXY()) {
 // throw new BugError("Not supported instance type |%s| for cron method |%s|.", instanceType, method);
 // }
 if ( remotelyAccessible ) { throw new BugError ( "Remote accessible method |%s| cannot be executed by cron." , method ) ; } if ( transactional ) { throw new BugError ( "Transactional method |%s| cannot be executed by cron." , method ) ; } if ( ! Types . isVoid ( method . getReturnType ( ) ) ) { throw new BugError ( "Cron method |%s| must be void." , method ) ; } if ( managedMethod == null ) { managedMethod = new ManagedMethod ( this , interfaceMethod ) ; } managedMethod . setCronExpression ( cronMethod . value ( ) ) ; cronMethodsPool . add ( managedMethod ) ; autoInstanceCreation = true ; } // store managed method, if created, to managed methods pool
 if ( managedMethod != null ) { methodsPool . put ( interfaceMethod , managedMethod ) ; if ( managedMethod . isRemotelyAccessible ( ) && netMethodsPool . put ( method . getName ( ) , managedMethod ) != null ) { throw new BugError ( "Overloading is not supported for net method |%s|." , managedMethod ) ; } } } for ( Field field : implementationClass . getDeclaredFields ( ) ) { ContextParam contextParam = field . getAnnotation ( ContextParam . class ) ; if ( contextParam != null ) { field . setAccessible ( true ) ; contextParamFields . put ( contextParam . value ( ) , field ) ; } } }
Scan annotations for managed classes that requires implementation. Annotations are processed only for managed classes
that have {@link #implementationClass} that is primary source scanned for annotation. If an annotation is not present
into implementation class try to find it on interface(s). See <a href="#annotations">Annotations</a> section from class
description.

@throws BugError for insane conditions.
Scan annotations for managed classes that requires implementation . Annotations are processed only for managed classes that have { @link #implementationClass } that is primary source scanned for annotation . If an annotation is not present into implementation class try to find it on interface ( s ) . See <a href = #annotations > Annotations< / a > section from class description .