how to communicate in multi module dynamice feature Application - android-instant-apps

I have project structure like
app :
InstantApp :
library:
dynamic-feature1 :
dynamic-feature2 :
dynamic-feature3 :
Now there is some dependency between dynamic-feature1 and dynamic-feature2. Now if i add it as dependency in dynamic-feature2 build.gradle then it will cause cyclic dependency.
Above is just one example there are many other cases too. How to handle such dependency conflicts properly or any suggestion ?

Communicate from the main app module to a dynamic feature module
You can do this by reflection in Java. Make sure your class and method names are not obfuscated in the dynamic modules.
Get a Fragment/Activity or other class from module:
Class class = Class.forName("your.dynamic.module.package.name.classname");
Get a method from your class:
Method method = class.getMethod("GenerateQuestion");
Invoke the method:
method.invoke(objectYouWantToInvokeTheMethodOn);
Communicate from dynamic feature module to main module
To get a parent activity of a dynamic feature module's fragment you can do:
#Override
public void onAttach(Context context) {
super.onAttach(context);
activity = (Activity) context;
}
Then you can call a method on that activity.

Related

When I subclass a class using ByteBuddy in certain situations I get IllegalAccessErrors. Why?

(I am a new ByteBuddy user. I'm using ByteBuddy version 1.10.8 and JDK 11 without the module path or any other part of the module system.)
I have a nested class declared like this:
public static class Frob {
protected Frob() {
super();
}
public String sayHello() {
return "Hello!";
}
}
(Its containing class is foo.bar.TestExplorations.)
When I create a dynamic subclass of Frob named foo.bar.Crap like the following, everything works OK as I would expect:
final String className = "foo.bar.Crap";
final DynamicType.Unloaded<?> dynamicTypeUnloaded = new ByteBuddy()
.subclass(Frob.class)
.name(className)
.make();
final Class<?> mySubclass = dynamicTypeUnloaded
.load(this.getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
assertNotNull(mySubclass);
assertEquals(className, mySubclass.getName());
final Object frobSubclass = mySubclass.newInstance();
assertTrue(frobSubclass instanceof Frob);
But if I change Frob's constructor so that it is package private, I get the following error from the final assertion:
java.lang.IllegalAccessError: class foo.bar.Crap tried to access method 'void foo.bar.TestExplorations$Frob.<init>()' (foo.bar.Crap is in unnamed module of loader net.bytebuddy.dynamic.loading.ByteArrayClassLoader #5e3d57c7; foo.bar.TestExplorations$Frob is in unnamed module of loader 'app')
For some reason, Crap's constructor cannot call super(), even though Crap and Frob are in the same package, and Frob() is defined as package-private.
I have a sense the JDK module system is to blame here, even though I am deliberately (very, very deliberately) not using it. I know the module system does not like split packages, which is what it looks like to me is going on here. Is there a constructor strategy or other mechanism to work around this problem?
In Java, a package is only equal to another package if it has the same name and is loaded by the same class loader (the same as it is with classes). If you are using the WRAPPER strategy, you cannot access package-private members of any super class. Byte Buddy does not forbid the generation as it would be legal to do in javac but you would need to use the INJECTION strategy to do what you want to make sure that classes are loaded by the same class loader. Mind that it uses internal API, therefore, from Java 9, you'd rather use a ForLookup class loading strategy.

How to Solve Circular Dependency

Hi I have a problem with the structure of my code, it somehow goes into Circular Dependency. Here is an explanation of how my code looks like:
I have a ProjectA contains BaseProcessor and BaseProcessor has a reference to a class called Structure in ProjectB. Inside BaseProcessor, there is an instance of Structure as a variable.
In projectB there are someother classes such as Pricing, Transaction etc.
Every class in ProjectB has a base class called BaseStructure i.e. Structure, Pricing and Transaction classes all inherited from BaseStructure.
Now in Pricing and Transaction classes, I want to call a method in BaseProcessor class from BaseStructure class which causing Circular Dependency.
What I have tried is:
Using Unity, but I didn't figure out how to make it work because I try to use function like:
unityContainer.ReferenceType(IBaseProcessor, BaseProcessor)
in BaseStructure then it will need a reference of BaseProcessor which also cause Circular Dependency.
And I've also tried creating an interface of IBaseProcessor and create a function(the function I want to call) declaration in this interface. And let both BaseProcessor and BaseStructure inherit this interface. But how can I call the function in Pricing and Transaction class without create an instance of BaseProcessor?
Can anyone please tell me how to resolve this problem other than using reflection?
Any help will be much appreciated. Thanks :)
You could use the lazy resolution:
public class Pricing {
private Lazy<BaseProcessor> proc;
public Pricing(Lazy<BaseProcessor> proc) {
this.proc = proc;
}
void Foo() {
this.proc.Value.DoSomethin();
}
}
Note that you haven't to register the Lazy because Unity will resolve it by BaseProcessor registration.
Your DI container can't help solving the circular reference, since it is the dependency structure of the application that prevents objects from being created. Even without a DI container, you can't construct your object graphs without some special 'tricks'.
Do note that in most cases cyclic dependency graphs are a sign of a design flaw in your application, so you might want to consider taking a very close look at your design and see if this can't be solved by extracting logic into separate classes.
But if this is not an option, there are basically two ways of resolving this cyclic dependency graph. Either you need to fallback to property injection, or need to postpone resolving the component with a factory, Func<T>, or like #onof proposed with a Lazy<T>.
Within these two flavors, there are a lot of possible ways to do this, for instance by falling back to property injection into your application (excuse my C#):
public class BaseStructure {
public BaseStructure(IDependency d1) { ... }
// Break the dependency cycle using a property
public IBaseProcessor Processor { get; set; }
}
This moves the IBaseProcessor dependency from the constructor to a property and allows you to set it after the graph is constructed. Here's an example of an object graph that is built manually:
var structure = new Structure(new SomeDependency());
var processor = new BaseProcessor(structure);
// Set the property after the graph has been constructed.
structure.Processor = processor;
A better option is to hide the property inside your Composition Root. This makes your application design cleaner, since you can keep using constructor injection. Example:
public class BaseStructure {
// vanilla constructor injection here
public BaseStructure(IDependency d1, IBaseProcessor processor) { ... }
}
// Defined inside your Composition Root.
private class CyclicDependencyBreakingProcessor : IBaseProcessor {
public IBaseProcessor WrappedProcessor { get; set; }
void IBaseProcessor.TheMethod() {
// forward the call to the real processor.
this.WrappedProcessor.TheMethod();
}
}
Now instead of injecting the BaseProcessor into your Structure, you inject the CyclicDependencyBreakingProcessor, which will be further initialized after the construction of the graph:
var cyclicBreaker = new CyclicDependencyBreakingProcessor();
var processor = new BaseProcessor(new Structure(new SomeDependency(), cyclicBreaker));
// Set the property after the graph has been constructed.
cyclicBreaker.WrappedProcessor = processor;
This is basically the same as before, but now the application stays oblivious from the fact that there is a cyclic dependency that needed to be broken.
Instead of using property injection, you can also use Lazy<T>, but just as with the property injection, it is best to hide this implementation detail inside your Composition Root, and don't let Lazy<T> values leak into your application, since this just adds noise to your application, which makes your code more complex and harder to test. Besides, the application shouldn't care that the dependency injection is delayed. Just as with Func<T> (and IEnumerable<T>), when injecting a Lazy<T> the dependency is defined with a particular implementation in mind and we're leaking implementation details. So it's better to do the following:
public class BaseStructure {
// vanilla constructor injection here
public BaseStructure(IDependency d1, IBaseProcessor processor) { ... }
}
// Defined inside your Composition Root.
public class CyclicDependencyBreakingProcessor : IBaseProcessor {
public CyclicDependencyBreakingBaseProcessor(Lazy<IBaseProcessor> processor) {...}
void IBaseProcessor.TheMethod() {
this.processor.Value.TheMethod();
}
}
With the following wiring:
IBaseProcessor value = null;
var cyclicBreaker = new CyclicDependencyBreakingProcessor(
new Lazy<IBaseProcessor>(() => value));
var processor = new BaseProcessor(new Structure(new SomeDependency(), cyclicBreaker));
// Set the value after the graph has been constructed.
value = processor;
Up until now I only showed how to build up the object graph manually. When doing this using a DI container, you usually want to let the DI container build up the complete graph for you, since this yields a more maintainable Composition Root. But this can make it a bit more tricky to break the cyclic dependencies. In most cases the trick is to register the component that you want to break with a caching lifestyle (basically anything else than transient). Per Web Request Lifestyle for instance. This allows you to get the same instance in a lazy fashion.
Using the last CyclicDependencyBreakingProcessor example, we can create the following Unity registration:
container.Register<BaseProcessor>(new PerRequestLifetimeManager());
container.RegisterType<IStructure, Structure>();
container.RegisterType<IDependency, SomeDependenc>();
container.Register<IBaseProcessor>(new InjectionFactory(c =>
new CyclicDependencyBreakingProcessor(
new Lazy<IBaseProcessor>(() => c.GetInstance<BaseProcessor>())));

c# how to select test or prod class from config file

I have built a cloud project for a month. My problem is that:
I have 2 classes to connect with Ibm web service. First class is the main class and the second one is test class. I put a key-value to appSetting in Config File.
If value in configFile is "TEST", the project will use test class and if value is the "PROD", the project will use main class. When I change the value in config, I will not change everywhere.
My Manager gave me advice to use "interface" but I didn't understand.
How can I solve this problem basiclly?
Both your test class and prod class could implement the said interface. If you need to use the approach where you do the selection in the config file of which class to use you are probably better off creating a data factory class that returns the correct implementation of the interface. The data factory reads the config file and depending on the value in app settings returns the correct class that implements the interface.
Example of doing this in C# (the concept is the same in other oo languages as well):
From the calling class:
SomethingFactory factory = new SomethingFactory();
ISomething testOrProdObj = factory.GetCorrectImplementation();
var result = testOrProdObj.MyMethod();
And in the factory class:
public class SomethingFactory
{
public ISomething GetCorrectImplementation()
{
//Do a check in appsettings to decide which class (TESTSomething or PRODSomething) to instantiate and return
}
}
Implementation of the interface
public class TESTSomething : ISomething
or
public class PRODSomething : ISomething

MEF Child Container Module Not Initializing

I have a simple container hierarchy with a parent container which is defined in the Shell MEFBootstrapper using a Directory catalog, and child container(s) which get created off the parent with a distinct catalog.
My child containers also use DirectoryCatalog (different path than parent), and I can see that the container has assembly and part information during runtime.
However, the Initialize() method for the modules located in the child containers are never called.
My goal is to use the child containers as session constructs, allowing the user to create new sessions and toggle between them. But if I cannot get the constituent modules to initialize (and place their views into the regions), I am kind of stuck.
I had thought to raise an event from my session manager using event aggregator to allow the modules to listen for the event and self-initialize, but that doesn't seem to work either.
i. Why isn't Initialize getting called on modules loaded into a child container
ii. How can I "trigger" Initialize from the container instance (outside of the module context?) Can you iterate over the assemblies in the container and trigger Initialize that way???
[from MefBootstrapper in shell project]
protected override DependencyObject CreateShell()
{
ExportProvider ep = this.Container as ExportProvider;
this.Container.ComposeExportedValue(ep);
[from the service that manages my sessions (containers)]
[ImportingConstructor]
public SessionService(ExportProvider provider)
{
[constructor for new sessions (containers)]
private void Init(ComposablePartCatalog catalog, ExportProvider provider, string name, int callId, bool useContextProxy)
{
this._Name = name;
this._CallID = callId;
this.startTime = DateTime.Now;
this.appHost = new CompositionContainer(catalog, new ExportProvider[] { provider });
}
=====
Was asked to include my module code whose initialize method is not called (despite being loaded into the container in question...I can even lazy instantiate the module, but calling Initialize() directly causes the injection operation to fail in the method proper.
namespace Module1
{
//, InitializationMode = InitializationMode.OnDemand
[ModuleExport("Module1.ModuleInit", typeof(Module1.ModuleInit))]
public class ModuleInit : IModule
{
private readonly IRegionManager _regionManager;
public IServiceLocator _serviceLocator;
[ImportingConstructor]
public ModuleInit(IRegionManager regionManager, IServiceLocator serviceLocator)
{
_regionManager = regionManager;
_serviceLocator = serviceLocator;
}
#region IModule Members
public void Initialize()
{
// Use View Discovery to automatically display the MasterView when the TopLeft region is displayed.
_regionManager.RegisterViewWithRegion(RegionNames.TopLeftRegion, () => _serviceLocator.GetInstance<MasterView>());
}
#endregion
}
}
I downloaded your code and had a look at it. I immediately found the problem. The bootstrapper is actually getting exports thanks to a DirectoryCatalog like this:
DirectoryCatalog catalog = new DirectoryCatalog(".");
this.AggregateCatalog.Catalogs.Add(catalog);
This means that you will get the exports from the assemblies in this directory. So you simply need to copy all the the assemblies with the exported types in the directory ".", that is to say the executing directory (Debug/bin).
Just copy Module1 and Module2 in the bin directory and everthing will compose gracefully :)
Actually I found that the post-build events supposed to copy the modules in the bin directory were not working. Maybe because your renamed something. So if you want it automatically copy the assemblies after building just replace the actual post-build event by this one:
copy "$(TargetDir)\$(TargetFileName)" "$(TargetDir)\..\..\..\Shell\bin\$(ConfigurationName)\"
I already had this problem many times and resolving it is really simple.
Remove the constructor from the your module. Prism modules are not activated the same way it does for classical exported types, therefore modules cannot use ImportingConstructor to import the services you need. Instead intitialize them with the ServiceLocator within the Initialize method.
This will work:
[ModuleExport("Module1.ModuleInit", typeof(Module1.ModuleInit))]
public class ModuleInit : IModule
{
private readonly IRegionManager _regionManager;
public void Initialize()
{
_regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
_regionManager.RegisterViewWithRegion(RegionNames.TopLeftRegion, () => _serviceLocator.GetInstance<MasterView>());
}
}
I also think that this behavior is kind of disturbing.
I had this same problem where my modules Initialize() method was not being called... I realized I had left off the "override" keyword on my Initialize method that was declared virtual in the Module base class that all of my modules inherit from... added "override" and it worked!

wicket and AtUnit

I've started playing with Wicket and I've chosen Guice as dependency injection framework. Now I'm trying to learn how to write a unit test for a WebPage object.
I googled a bit and I've found this post but it mentioned AtUnit so I decided to give it a try.
My WebPage class looks like this
public class MyWebPage extends WebPage
{
#Inject MyService service;
public MyWebPage()
{
//here I build my components and use injected object.
service.get(id);
....
}
}
I created mock to replace any production MyServiceImpl with it and I guess that Guice in hand with AtUnit should inject it.
Now the problems are:
AtUnit expects that I mark target object with #Unit - that is all right as I can pass already created object to WicketTester
#Unit MyWebPage page = new MyWebPage();
wicketTester.startPage(page);
but usually I would call startPage with class name.
I think AtUnit expects as well that a target object is market with #Inject so AtUnit can create and manage it - but I get an org.apache.wicket.WicketRuntimeException: There is no application attached to current thread main. Can I instruct AtUnit to use application from wicketTester?
Because I don't use #Inject at MyWebPage (I think) all object that should be injected by Guice are null (in my example the service reference is null)
I really can't find anything about AtUnit inside Wicket environment. Am I doing something wrong, am I missing something?
I don't know AtUnit but I use wicket with guice and TestNG. I imagine that AtUnit should work the same way. The important point is the creation of the web application with the use of guice.
Here how I bind all this stuff together for my tests.
I have an abstract base class for all my tests:
public abstract class TesterWicket<T extends Component> {
#BeforeClass
public void buildMockedTester() {
System.out.println("TesterWww.buildMockedTester");
injector = Guice.createInjector(buildModules());
CoachWebApplicationFactory instance =
injector.getInstance(CoachWebApplicationFactory.class);
WebApplication application = instance.buildWebApplication();
tester = new WicketTester(application);
}
protected abstract List<Module> buildModules();
The initialization is done for every test class. The subclass defines the necessary modules for the test in the buildModules method.
In my IWebApplicationFactory I add the GuiceComponentInjector. That way, after all component instantiation, the fields annotated with #Inject are filled by Guice:
public class CoachWebApplicationFactory implements IWebApplicationFactory {
private static Logger LOG = LoggerFactory.getLogger(CoachWebApplicationFactory.class);
private final Injector injector;
#Inject
public CoachWebApplicationFactory(Injector injector) {
this.injector = injector;
}
public WebApplication createApplication(WicketFilter filter) {
WebApplication app = injector.getInstance(WebApplication.class);
Application.set(app);
app.addComponentInstantiationListener(new GuiceComponentInjector(app, injector));
return app;
}
}