Is byte-buddy agent capable of overcoming Attach API restrictions e.g. "new method definition", "static variable changes" ? I can see that redefineClasses method is being called from Agent Builder, but not sure if this is also following the same restrictions as the attach API.
I am trying to understand whether I can do the following:
1) Load the agent jar using an application class loader e.g. ParallelWebappClassLoader. My application is a servlet webapp and during runtime it uses the above classloader to load all application classes.
2) Fully redefine my classes i.e. any method addition/updates and static/local variable changes/updates/addition.
I do have an agent which currently works within the Attach API restrictions, but I am struggling to delegate the class loading from System Class Loader to application.
Many Thanks,
This is a restriction of the Java virtual machine you are running. Byte Buddy is capable of "fully redefining" a class by using its API but most VMs will reject such changes. Have a look at the dynamic code evolution VM for being able to apply such changes.
Related
I am trying to learn, how to create a custom NiFi controller service. To start off, I thought of mimicking the DBCPConnectionPool controller service by simply copying the original source code of DBCPConnectionPool service. To implement the same, I generated a maven archetype from "nifi-service-bundle-archetype" and got the following project structure
However, when i generated the archetype from 'nifi-processor-bundle-archetype , I got the following structure: -
I understand that in case of processor I simply need to write my code in MyProceesor.java present under nifi-ListDbTableDemo-processors folder and then create a nar file out of it. But in case of controller service, I have 4 folders generated. I can see two java files i.e.
StandardMyService.java present under nifi-DbcpServiceDemo folder
MyService.java present under nifi-DbcpServiceDemo-apifolder
Now, why is there two java files generated in case of custom controller service, while there was only one java file generated in case of custom processor. Also, Since I am trying to mimick the DBCPConnectionPool service, in which java file out of two should I copy the original source code of DBCPConnectionPool service.
Please guide me from scratch, the steps that I need to follow to create a custom service equivalent to that of DBCPConnectionPool service.
MyService.java under nifi-DbcpServiceDemo-api is an interface which be implemented by the StandardMyService.java under nifi-DbcpServiceDemo. Once the implementation is done, you have to use nifi-DbcpServiceDemo-api as dependency in the processor bundle which needs to work with this custom controller Service.
The reason why controller services are implemented this way is:
We will be hiding the actual implementation from the processor bundle because it need not depend on the implementation.
Tomorrow you write a new controller service implementation, say StandardMyServiceTwo which again implements MyService because only the implementation varies from StandardMyService and other members remains the same and can be shared. This new controller service can be introduced transparently without making any changes on the processor bundle.
Example:
The best example is the record reader/writer controller services. If you look at the nifi-record-serialization-services-bundle in nifi, they have different implementation for serializing records of JSON, Grok, avro, CSV data formats but they all are actually implementing one API - nifi-record-serialization-service-api And hence for the processors which want to use the Record Reader or Record Writer, instead of having the actual implementations as its dependency, they rather can have the api as its dependency.
So tomorrow you can add add a new implementation in the record-serialization-services-bundle for a new data format without touching anything on the processors bundle.
For you references, please take a look at the following links which would help you in writing the custom controller service from scratch
http://www.nifi.rocks/developing-a-custom-apache-nifi-controller-service/
https://github.com/bbende/nifi-dependency-example
So, I have a viewmodel class in a xamarin project that I inject some dependencies into via ninject binding on app start. One of these is an IDialogService.
When my MainPage in my application changes it raises a property changed event and I rebind the implementation of the dialog service since it is tied to the MainPage.
If my viewmodel has already been created with lets say DialogServiceA and then when MainPage changes we rebind to DialogServiceB, will my viewmodel be using service A or B? I think it is using A and therefore does not display in the UI because it is tied to a MainPage that no longer exists.
So, if this is the case how can I dynamically change my dialog service but then update classes that have already been instantiated without changing everything to get the current dialog service from the container every time its used (therefore not injecting it at all really, and doing more of a servicelocator)
Also, if this approach is completely wrong, set me straight.
You're right. Re-configuration of the container does not affect already instanciated objects.
If you want to change dependencies without re-instanciating the dependent (parent ViewModel) there's a few possibilities for you:
use a factory to instanciate the service every time. Implement an Abstract Factory (Site by Mark Seeman) or use Ninject.Extensions.Factory to do so
instead of injecting a service directly, inject an adapter. The adapter then redirects the request to the currently appropriate service. To do so, either all service can be injected into the adapter, or you can use a factory as with the possibility above.
instead of inject a service directly, inject a proxy. The proxy is quite similar to the adapter, but instead of coding every method / property redirection specifically, you code a generic redirect by an interceptor. Here's a tutorial on castle dynamic proxy
At the end of the day, however, i believe you'll also need a way to manage when to change the service / which it should be. There's probably a design alternative which doesn't rely on exchanging objects in such a manner.. which would make it an easier (and thus better?) design.
Edit: i just saw that you also tagged the question as xamarin-forms. In that case it most likely won't be an option to use either a dynamic proxy nor ninject.extensions.factory (it relies on dynamic proxies, too). Why? dynamic proxy / IL emitting is not supported on all platforms, AFAIR specifically on Apple devices this can't be done.
I'd like to link my custom domain object into the Petrel free memory command. My domain object caches data while visualised and this cache could be cleared when the user wants to free memory.
I have found the IMemorySaver interface and tried declaring this on my custom domain object but the FreeMemory method is not called when the user choose to free memory in Petrel.
Any ideas?
Neal
In Ocean 2013.1 a new API has been introduced that allows custom domain objects and ToggleWindows from a plug-in to be told when the user has invoked the ‘Free memory’ feature (this will also work for programmatic calls to PetrelSystem.ForceFreeMemory()).
The API follows a similar pattern to the existing INameInfoFactory and IImageInfoFactory APIs.
In order to use the API you need to create a factory object for your custom domain object (or ToggleWindow) that implements the new IResourceSaverFactory interface.
This interface requires that you implement a single method called GetResourceSaver(). This
method will return a ResourceSaver object that is associated with your custom domain object (or ToggleWindow).
ResourceSaver is an abstract class and you should implement the FreeResources() method on your derived class.
When the ‘Free memory’ feature is invoked the system will use your ResourceSaverFactory to obtain a ResourceSaver object for each of your custom domain object (or ToggleWindow) instances.
The FreeResources() method will be called on your ResouceSaver
objects.
Regards,
Chippy
Neal, the IMemorySaver is declared as a service interface, which you should not re-implement.
Having said that, participation in Petrel's controlled resource management is a fair requirement.
I have a WCF service application (actually, it uses WCF Web API preview 5) that intercepts each request and extracts several header values passed from the client. The idea is that the 'interceptor' will extract these values and setup a ClientContext object that is then globally available within the application for the duration of the request. The server is stateless, so the context is per-call.
My problem is that the application uses IoC (Unity) for dependency injection so there is no use of singleton's, etc. Any class that needs to use the context receives it via DI.
So, how do I 'dynamically' create a new context object for each request and make sure that it is used by the container for the duration of that request? I also need to be sure that it is completely thread-safe in that each request is truly using the correct instance.
UPDATE
So I realize as I look into the suggestions below that part of my problem is encapsulation. The idea is that the interface used for the context (IClientContext) contains only read-only properties so that the rest of the application code doesn't have the ability to make changes. (And in a team development environment, if the code allows it, someone will inevitably do it.)
As a result, in my message handler that intercepts the request, I can get an instance of the type implementing the interface from the container but I can't make use of it. I still want to only expose a read-only interface to all other code but need a way to set the property values. Any ideas?
I'm considering implementing two interfaces, one that provides read-only access and one that allows me to initialize the instance. Or casting the resolved object to a type that allows me to set the values. Unfortunately, this isn't fool-proof either but unless someone has a better idea, it might be the best I can do.
Read Andrew Oakley's Blog on WCF specific lifetime managers. He creates a UnityOperationContextLifetimeManager:
we came up with the idea to build a Unity lifetime manager tied to
WCF's OperationContext. That way, our container objects would live
only for the lifetime of the request...
Configure your context class with that lifetime manager and then just resolve it. It should give you an "operation singleton".
Sounds like you need a Unity LifetimeManager. See this SO question or this MSDN article.
I'm just starting to play with MEF and have a couple questions.
1) I wrote a WCF service that takes in some xml and passes the xml off to a parser. The parsers are composed using MEF. (metadata in the xml lets me determine which parser to use). I can add a new parser, and support new XML, by just dropping the dll in a directory. That part all works. But, WCF services can be instantiated multiple times, I want my parser catalog to be static, that is, if multiple instances of my service are spun up, and they get the same XML, I only need one instance of the parser running, they are written to be thread safe. I can't seem to configure MEF to do this. Anyone know how?
2) I can drop in a new parser into the directory and a catalog refresh will automatically discover it, that works great. But if I try to drop a modified dll into the directory, and that parser has been activated in the service, I get an error saying the file is in use. Is there a way to override this?
1) It sounds like you should make your MEF container and catalogs static so they only get created once. Make sure you specify that the CompositionContainer should be thread safe by using the constructor with the isThreadSafe parameter and setting it to true.
2) You can enable shadow copying which will prevent the file from being locked when the DLL is loaded. However, you can't unload DLLs from an AppDomain in .NET, and furthermore it is not safe to recompose a CompositionContainer that can be used on multiple threads. In other words, using the isThreadSafe parameter only makes the container thread-safe for "reading"/pulling exports from the container, not modifying it via composition/recomposition.
So if you want to add a new parser it's probably best to restart the service.