ServiceTrackerCustomizer service reference returns null - osgi

I have a persistence bundle containing a Product entity. Since I want to trigger updates on my Solr server on demand, when I'm altering an instance, I introduced an entity listener:
#Entity
public class Product {
// id and fields
#PrePersist
public void onPersist () {
ProductAudit.onPersist( this );
}
// other lifecycle callbacks
}
public class ProductAudit {
private static final Set<ProductListener> listeners = new HashSet<>();
// static addListener/removeListener
public void onPersist (Product p) {
listeners.forEach(l -> {
l.onPersist(p);
}
}
}
To integrate my persistence unit into my OSGi environment, I wrote an adapter bundle leveraging a service tracker:
#Component(
name="com.acme.product.audit",
immediate=true)
public class OsgiProductListener implements ProductListener {
private ServiceTracker<ProductListener,ProductListener> tracker;
#Activate
public void activate (BundleContext context) {
tracker = new ServiceTracker<>(context, ProductListener.class, new ServiceTrackerCustomizer<ProductListener, ProductListener>() {
#Override
public ProductListener addingService(ServiceReference<ProductListener> reference) {
if (validProps(reference)) {
ProductListener l = reference.getBundle().getBundleContext().getService(reference); // null
ProductListener l = context.getService(reference); // null too
System.out.println("Adding " + l);
ProductAudit.addListener(l);
return l;
}
return null;
}
// modifiedService, removedService
private boolean validProps(ServiceReference<?> reference) {
// check for enabling flag
}
});
tracker.open();
}
Now I have two provider bundles - a test bundle and an indexer bundle. When I deploy both, on console is printed:
> Activating com.acme.persistence.audit component
...
> Adding com.acme.persistence.test.ProductListenerImpl#1337
> Adding null
All three bundles use the same API version, else my tracker wouldnt track them.
So why I am getting null, if I try to obtain the ProductListener service?

Related

In AspNet Boilerplate DotNetCore Console App that uses a custom AppService it does not perform the dependency injection

I am trying to make a console app that uses a custom AppService by adapting from the example https://github.com/aspnetboilerplate/aspnetboilerplate-samples/blob/master/AbpEfConsoleApp/AbpEfConsoleApp/Program.cs
It works for me to call the service, but when I try to use a IRepository gives me the following error
Castle.MicroKernel.Handlers.HandlerException: 'Can't create component 'VCloud.Rtdm.CashAudit.TestManager' as it has dependencies to be satisfied.
It's as if I didn't have the IRepository registered.
Program.cs
class Program
{
static void Main(string[] args)
{
TestUserReferencedService();
}
/// <summary>
/// Prueba de USAR un servicio de aspnetzero referenciando al proyecto. Spoiler: No funciona
/// </summary>
static async void TestUserReferencedService()
{
Clock.Provider = ClockProviders.Utc;
Console.WriteLine("Starting");
//Bootstrapping ABP system
using (var bootstrapper = AbpBootstrapper.Create<VCloudConsoleApplicationModule>())
{
bootstrapper.IocManager
.IocContainer
.AddFacility<LoggingFacility>(f => f.UseAbpLog4Net().WithConfig("log4net.config"));
bootstrapper.Initialize();
//Getting a Tester object from DI and running it
using (var tester = bootstrapper.IocManager.ResolveAsDisposable<TestAppService>())
{
var x = (await tester.Object.TestCount());
} //Disposes tester and all it's dependencies
Console.WriteLine("Press enter to exit...");
Console.ReadLine();
}
}
}
VCloudConsoleApplicationModule.cs
[DependsOn(
typeof(VCloudApplicationSharedModule),
typeof(VCloudConsoleCoreModule),
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpDapperModule),
typeof(AbpZeroCommonModule)
)]
public class VCloudConsoleApplicationModule : AbpModule
{
public override void PreInitialize()
{
//Adding authorization providers
Configuration.Authorization.Providers.Add<AppAuthorizationProvider>();
//Adding custom AutoMapper configuration
Configuration.Modules.AbpAutoMapper().Configurators.Add(CustomDtoMapper.CreateMappings);
Configuration.BackgroundJobs.IsJobExecutionEnabled = false;
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(VCloudConsoleApplicationModule).GetAssembly());
DapperExtensions.DapperExtensions.SetMappingAssemblies(new List<Assembly>
{typeof(VCloudConsoleApplicationModule).GetAssembly()});
DapperExtensions.DapperExtensions.SetMappingAssemblies(new List<Assembly>
{
typeof(VCloud.Dapper.Mappers.DapperMapper_RtdmOrder).GetAssembly(),
typeof(VCloud.Dapper.Mappers.DapperMapper_RtdmOrderItem).GetAssembly(),
typeof(VCloud.Dapper.Mappers.DapperMapper_RtdmCompany).GetAssembly(),
typeof(VCloud.Dapper.Mappers.DapperMapper_RtdmRestaurant).GetAssembly()
});
//DapperExtensions.DapperExtensions.Configure();
//Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
}
}
TestManager.cs
public class TestManager : VCloudDomainServiceBase, ITestManager
{
private IRepository<Invoice> _repository;
public TestManager(IRepository<Invoice> repository)
{
_repository = repository;
}
public async Task<int> GetCount()
{
return await _repository.CountAsync();
}
}
Your problem is not related to Dependeny Injection, the problem may be you forget to add the entity Invoice to the DbContext of your application in EntityFramework project.
Once you add it your problem will be solved.
public class VCloudApplicationDbContext : AbpZeroDbContext<Tenant, Role, User, VCloudApplicationDbContext>, IAbpPersistedGrantDbContext
{
public DbSet<Invoice> Invoice { get; set; }
}
I hope it could help you

Cucumber Guice / Injector seems not to be thread-safe (Parallel execution / ExecutorService)

[long description warning]
I'm running some cucumber tests which have to be executed intercalated a defined server - for instance:
a.feature -> JBoss Server 1 | b.feature -> JBoss Serv. 2 | c.feature -> JB1 | etc.
For that, I created a hypothetical ExecutorService like this:
final ExecutorService executorService = Executors.newFixedThreadPool(2); //numberOfServers
for (Runnable task : tasks) {
executorService.execute(task);
}
executorService.shutdown();
try {
executorService.awaitTermination(1000, TimeUnit.SECONDS);
} catch (InterruptedException e) {
//doX();
}
The way that I manage about how will be the server chosen as liable to execute is:
inside of my Runnable class created for the executorService, I pass as a parameter a instanceId to a TestNG (XmlTest class) as below:
#Override
public void run() {
setupTest().run();
}
private TestNG setupTest() {
TestNG testNG = new TestNG();
XmlSuite xmlSuite = new XmlSuite();
XmlTest xmlTest = new XmlTest(xmlSuite);
xmlTest.setName(//irrelevant);
xmlTest.addParameter("instanceId", String.valueOf(instanceId));
xmlTest.setXmlClasses(..........);
testNG.setXmlSuites(..........);
return testNG;
}
Then, I get this just fine in a class that extends TestNgCucumberAdaptor:
#BeforeTest
#Parameters({"instanceId"})
public void setInstanceId(#Optional("") String instanceId) {
if (!StringUtils.isEmpty(instanceId)) {
this.instanceId = Integer.valueOf(instanceId);
}
}
And inside a #BeforeClass I'm populating a Pojo with this instanceId and setting the Pojo in a threadLocal attribute of another class. So far, so good.
public class CurrentPojoContext {
private static final ThreadLocal<PojoContext> TEST_CONTEXT = new ThreadLocal<PojoContext>();
...
public static PojoContext getContext(){
TEST_CONTEXT.get();
}
Now the problem really starts - I'm using Guice (Cucumber guice as well) in a 3rd class, injecting this pojo object that contains the instanceId. The example follows:
public class Environment {
protected final PojoContext pojoContext;
#Inject
public Environment() {
this.pojoContext = CurrentPojoContext.getContext();
}
public void foo() {
print(pojoContext.instanceId); // output: 1
Another.doSomething(pojoContext);
}
class Another{
public String doSomething(PojoContext p){
print(p.instanceId); // output: 2
}
}
}
Here it is not every time like this the outputs (1 and 2) but from time to time, I realized that the execution of different threads is messing with the attribute pojoContext. I know that is a little confusing, but my guess is that the Guice Injector is not thread-safe for this scenario - it might be a long shot, but I'd appreciate if someone else takes a guess.
Regards
Well, just in order to provide a solution for someone else, my solution was the following:
Create a class that maintains a Map with an identifier (unique and thread-safe one) as the key and a Guice Injector as value;
Inside my instantiation of Guice injector, I created my own module
Guice.createInjector(Stage.PRODUCTION, MyOwnModules.SCENARIO, new RandomModule());
and for this module:
public class MyOwnModules {
public static final Module SCENARIO = new ScenarioModule(MyOwnCucumberScopes.SCENARIO);
}
the scope defined here provides the following:
public class MyOwnCucumberScopes {
public static final ScenarioScope SCENARIO = new ParallelScenarioScope();
}
To sum up, the thread-safe will be in the ParallelScenarioScope:
public class ParallelScenarioScope implements ScenarioScope {
private static final Logger LOGGER = Logger.getLogger(ParallelScenarioScope.class);
private final ThreadLocal<Map<Key<?>, Object>> threadLocalMap = new ThreadLocal<Map<Key<?>, Object>>();
#Override
public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
return new Provider<T>() {
public T get() {
Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);
#SuppressWarnings("unchecked")
T current = (T) scopedObjects.get(key);
if (current == null && !scopedObjects.containsKey(key)) {
current = unscoped.get();
scopedObjects.put(key, current);
}
return current;
}
};
}
protected <T> Map<Key<?>, Object> getScopedObjectMap(Key<T> key) {
Map<Key<?>, Object> map = threadLocalMap.get();
if (map == null) {
throw new OutOfScopeException("Cannot access " + key + " outside of a scoping block");
}
return map;
}
#Override
public void enterScope() {
checkState(threadLocalMap.get() == null, "A scoping block is already in progress");
threadLocalMap.set(new ConcurrentHashMap<Key<?>, Object>());
}
#Override
public void exitScope() {
checkState(threadLocalMap.get() != null, "No scoping block in progress");
threadLocalMap.remove();
}
private void checkState(boolean expression, String errorMessage) {
if (!expression) {
LOGGER.info("M=checkState, Will throw exception: " + errorMessage);
throw new IllegalStateException(errorMessage);
}
}
}
Now the gotcha is just to be careful regarding the #ScenarioScoped and the code will work as expected.

JavaFX. Register eventHandler in custom class

I try register eventHandler in my custom class. I don't know what interface or methods I have to implement for having addEventHandler method in my custom class. For this reason my Model class extends Rectangle (Rectangle class has addEventHandler mechanism).
Also I don't know why assigned source object not working (please see comment in Controller class).
Creating custom events I make by this tutorial: https://stackoverflow.com/a/27423430/3102393.
Project Structure
Controller
package sample;
import javafx.event.Event;
public class Controller {
private Model model;
public Controller() {
model = new Model();
model.addEventHandler(MyEvent.ROOT_EVENT, this::handler);
}
private void handler(MyEvent event) {
if(event.getEventType().equals(MyEvent.INSTANCE_CREATED)) {
// Why is event.getSource() instence of Rectangle and not instance of assigned MyObject?
Object obj = event.getSource();
System.out.println(event.getMyObject().getText());
}
}
public void clickedCreate(Event event) {
model.makeEvent();
}
}
Model
package sample;
import javafx.scene.shape.Rectangle;
import java.util.ArrayList;
public class Model extends Rectangle {
private ArrayList<MyObject> objects = new ArrayList<>();
private Integer counter = 0;
public void makeEvent() {
MyObject object = new MyObject((++counter).toString() + "!");
objects.add(object);
fireEvent(new MyEvent(object, null, MyEvent.INSTANCE_CREATED));
}
}
Custom event MyEvent
package sample;
import javafx.event.Event;
import javafx.event.EventTarget;
import javafx.event.EventType;
public class MyEvent extends Event {
public static final EventType<MyEvent> ROOT_EVENT = new EventType<>(Event.ANY, "ROOT_EVENT");
public static final EventType<MyEvent> INSTANCE_CREATED = new EventType<>(ROOT_EVENT, "INSTANCE_CREATED ");
public static final EventType<MyEvent> INSTANCE_DELETED = new EventType<>(ROOT_EVENT, "INSTANCE_DELETED");
private MyObject object;
public MyEvent(MyObject source, EventTarget target, EventType<MyEvent> eventType) {
super(source, target, eventType);
object = source;
}
public MyObject getMyObject() {
return object;
}
}
And finally MyObject
package sample;
public class MyObject {
private String text;
MyObject(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
Note (and question): I also tried using a ObservableList of instances of MyObjects, but I think that there is no notify for updating instance attribute.
Basics of Events
Events are fired using Event.fireEvent which works in 2 steps:
Build the EventDispatchChain using EventTarget.buildEventDispatchChain.
Pass the Event to the first EventDispatcher in the resulting EventDispatchChain.
This code snippet demonstrates the behaviour:
EventTarget target = new EventTarget() {
#Override
public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) {
return tail.append(new EventDispatcher() {
#Override
public Event dispatchEvent(Event event, EventDispatchChain tail) {
System.out.println("Dispatch 1");
tail.dispatchEvent(event);
return event;
}
}).append(new EventDispatcher() {
#Override
public Event dispatchEvent(Event event, EventDispatchChain tail) {
System.out.println("Dispatch 2");
tail.dispatchEvent(event);
return event;
}
});
}
};
Event.fireEvent(target, new Event(EventType.ROOT));
It prints
Dispatch 1
Dispatch 2
As you can see, the way the EventTarget constructs the EventDispatchChain is totally up to the EventTarget.
This explains why you have to implement addEventHandler ect. yourself.
How it's done for Nodes
This is described in detail in the article JavaFX: Handling Events - 1 Processing Events on the Oracle website.
The important details are:
Different source objects are used during the event handling.
EventHandlers / EventFilters are used during the event dispatching (2.).
This explains why the source value is unexpected.
How to implement addEventHandler
It's not that hard to do this, if you leave out the event capturing and bubbling. You just need to store the EventHandlers by type in a Map<EventType, Collection>> and call the EventHandlers for each type in the EventType hierarchy:
public class EventHandlerTarget implements EventTarget {
private final Map<EventType, Collection<EventHandler>> handlers = new HashMap<>();
public final <T extends Event> void addEventHandler(EventType<T> eventType, EventHandler<? super T> eventHandler) {
handlers.computeIfAbsent(eventType, (k) -> new ArrayList<>())
.add(eventHandler);
}
public final <T extends Event> void removeEventHandler(EventType<T> eventType, EventHandler<? super T> eventHandler) {
handlers.computeIfPresent(eventType, (k, v) -> {
v.remove(eventHandler);
return v.isEmpty() ? null : v;
});
}
#Override
public final EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) {
return tail.prepend(this::dispatchEvent);
}
private void handleEvent(Event event, Collection<EventHandler> handlers) {
if (handlers != null) {
handlers.forEach(handler -> handler.handle(event));
}
}
private Event dispatchEvent(Event event, EventDispatchChain tail) {
// go through type hierarchy and trigger all handlers
EventType type = event.getEventType();
while (type != Event.ANY) {
handleEvent(event, handlers.get(type));
type = type.getSuperType();
}
handleEvent(event, handlers.get(Event.ANY));
return event;
}
public void fireEvent(Event event) {
Event.fireEvent(this, event);
}
}

Adding Custom Dialog to Javafx with Spring DI

I have a gui built with javafx the controllers are loaded from fxml and created as Beans with spring so I can access my model. But that is predefined in fxml and loaded at start. Now I would like to load components, defined in fxml at runtime, but I could not yet find a working example, and no matter how I try it doesn't work.
So my question:
How can I create a custom Dialog (or any custom component) in runtime , that is loaded from .fxml and is aware of (Spring application) context?
Edit
So it loads but some fields are not initialized.
This is my custom DialogPane,
#Controller
#Scope("prototype")
public class NewProgramDialogPane extends DialogPane implements Initializable {
public static final ButtonType buttonTypeOk = new ButtonType("Create", ButtonBar.ButtonData.OK_DONE);
public static final ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
public TextField nameField;
public TextField data1Field;
public TextField data2Field;
public RegexValidator requiredField1;
public RequiredField requiredField2;
public RequiredField requiredField3;
public ErrorLabel duplicateProjectErrorLabel;
private SimpleBooleanProperty match = new SimpleBooleanProperty(false);
#Autowired
MainService mainService;
public NewProgramDialogPane() {
URL url = getClass().getClassLoader().getResource("com/akos/fxml/NewProgramDialog.fxml");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(url);
loader.setRoot(this);
try {
loader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void initialize(URL location, ResourceBundle resources) {
this.lookupButton(buttonTypeOk).addEventHandler(ActionEvent.ACTION, event -> {
if (!validate()) {
event.consume();
}
});
duplicateProjectErrorLabel.visibleProperty().bind(match);
}
public boolean validate() {
requiredField1.eval();
requiredField2.eval();
requiredField3.eval();
match.set(mainService.getPrograms().stream().anyMatch(
program -> program != null && program.getName().equals(nameField.getText())));
return !match.get() &&
!requiredField1.getHasErrors() &&
!requiredField2.getHasErrors() &&
!requiredField3.getHasErrors();
}
}
And when I try to read the nameField, it is null.
public class NewProgramDialog extends Dialog<Program> {
public NewProgramDialog() {
this.setDialogPane(new NewProgramDialogPane());
this.setTitle("New program");
this.initModality(Modality.APPLICATION_MODAL);
this.initStyle(StageStyle.DECORATED);
this.setResultConverter(param -> {
if (param == NewProgramDialogPane.buttonTypeOk) {
int x = 0;
return new Program(((NewProgramDialogPane) getDialogPane()).nameField.getText());
}
return null;
});
}
}
Define your custom dialog using the custom component FXML pattern; then just expose the custom component as a (prototype-scoped) spring bean.

JavaFX2 - very poor performance when adding custom made (fxml)panels to gridpane dynamically

Problem
I want to add custom made panels, built via javafx scene builder, to a gridpane at runtime. My custom made panel exsits of buttons, labels and so on.
My Attempt
I tried to extend from pane...
public class Celli extends Pane{
public Celli() throws IOException{
Parent root = FXMLLoader.load(getClass().getResource("Cell.fxml"));
this.getChildren().add(root);
}
}
... and then use this panel in the adding method of the conroller
#FXML
private void textChange(KeyEvent event) {
GridPane g = new GridPane();
for (int i=0 : i<100; i++){
g.getChildren().add(new Celli());
}
}
}
It works, but it performs very very poor.
What I am looking for
Is there a way to design panels via javafx scene builder (and as a result having this panels in fxml) and then add it to a gridpane at runtime without make use of this fxmlloader for each instance. I think it performs poor because of the fxml loader. When I add a standard button e.g. whitout fxml it is very much faster.
Short answer: No, it is not (as of JavaFX 2.x and 8.0). It may be in a future version (JFX >8)
Long answer:
The FXMLLoader is currently not designed to perform as a template provider that instantiates the same item over and over again. Rather it is meant to be a one-time-loader for large GUIs (or to serialize them).
The performance is poor because depending on the FXML file, on each call to load(), the FXMLLoader has to look up the classes and its properties via reflection. That means:
For each import statement, try to load each class until the class could successfully be loaded.
For each class, create a BeanAdapter that looks up all properties this class has and tries to apply the given parameters to the property.
The application of the parameters to the properties is done via reflection again.
There is also currently no improvement for subsequent calls to load() to the same FXML file done in the code. This means: no caching of found classes, no caching of BeanAdapters and so on.
There is a workaround for the performance of step 1, though, by setting a custom classloader to the FXMLLoader instance:
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
public class MyClassLoader extends ClassLoader{
private final Map<String, Class> classes = new HashMap<String, Class>();
private final ClassLoader parent;
public MyClassLoader(ClassLoader parent) {
this.parent = parent;
}
#Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> c = findClass(name);
if ( c == null ) {
throw new ClassNotFoundException( name );
}
return c;
}
#Override
protected Class<?> findClass( String className ) throws ClassNotFoundException {
// System.out.print("try to load " + className);
if (classes.containsKey(className)) {
Class<?> result = classes.get(className);
return result;
} else {
try {
Class<?> result = parent.loadClass(className);
// System.out.println(" -> success!");
classes.put(className, result);
return result;
} catch (ClassNotFoundException ignore) {
// System.out.println();
classes.put(className, null);
return null;
}
}
}
// ========= delegating methods =============
#Override
public URL getResource( String name ) {
return parent.getResource(name);
}
#Override
public Enumeration<URL> getResources( String name ) throws IOException {
return parent.getResources(name);
}
#Override
public String toString() {
return parent.toString();
}
#Override
public void setDefaultAssertionStatus(boolean enabled) {
parent.setDefaultAssertionStatus(enabled);
}
#Override
public void setPackageAssertionStatus(String packageName, boolean enabled) {
parent.setPackageAssertionStatus(packageName, enabled);
}
#Override
public void setClassAssertionStatus(String className, boolean enabled) {
parent.setClassAssertionStatus(className, enabled);
}
#Override
public void clearAssertionStatus() {
parent.clearAssertionStatus();
}
}
Usage:
public static ClassLoader cachingClassLoader = new MyClassLoader(FXMLLoader.getDefaultClassLoader());
FXMLLoader loader = new FXMLLoader(resource);
loader.setClassLoader(cachingClassLoader);
This significantly speeds up the performance. However, there is no workaround for step 2, so this might still be a problem.
However, there are already feature requests in the official JavaFX jira for this. It would be nice of you to support this requests.
Links:
FXMLLoader should be able to cache imports and properties between to load() calls:
https://bugs.openjdk.java.net/browse/JDK-8090848
add setAdapterFactory() to the FXMLLoader:
https://bugs.openjdk.java.net/browse/JDK-8102624
I have had a similar issue. I also had to load a custom fxml-based component several times, dynamically, and it was taking too long. The FXMLLoader.load method call was expensive, in my case.
My approach was to parallelize the component instantiation and it solved the problem.
Considering the example posted on the question, the controller method with multithread approach would be:
private void textChange(KeyEvent event) {
GridPane g = new GridPane();
// creates a thread pool with 10 threads
ExecutorService threadPool = Executors.newFixedThreadPool(10);
final List<Celli> listOfComponents = Collections.synchronizedList(new ArrayList<Celli>(100));
for (int i = 0; i < 100; i++) {
// parallelizes component loading
threadPool.execute(new Runnable() {
#Override
public void run() {
listOfComponents.add(new Celli());
}
});
}
// waits until all threads completion
try {
threadPool.shutdown();
threadPool.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// seems to be a improbable exception, but we have to deal with it
e.printStackTrace();
}
g.getChildren().addAll(listOfComponents);
}
Just adding code for "caching of already loaded classes" in #Sebastian sir given code. It is working for me. Please suggest changes in it for better performance.
#Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("In Class loader");
Class result;
System.out.println(" >>>>>> Load class : "+name);
result = (Class)classes.get(name);
if(result != null){
System.out.println(" >>>>>> returning cached class.");
return result;
}else{
Class<?> c = findClass(name);
if ( c == null ) {
throw new ClassNotFoundException( name );
}
System.out.println(" >>>>>> loading new class for first time only");
return c;
}
}

Resources