Can't inject EPartService - eclipse

In my bundle activator I try to inject fields 'IEventBroker' and 'EPartService'. But injected only first. Code follows:
#Inject
IEventBroker m_broker;
#Inject
EPartService m_part_service;
public void start(BundleContext context) throws Exception {
IEclipseContext service_context = EclipseContextFactory.getServiceContext(context);
ContextInjectionFactory.inject(this, service_context);
boolean contains = service_context.containsKey(EPartService.class);
// contains is always "true", but m_part_service is always "null"
// all follows invocations returns "null" too
//
// service_context.get(EPartService.class);
// service_context.getActiveLeaf().getActive(EPartService.class);
// service_context.getActiveLeaf().getLocal(EPartService.class);
// context.getServiceReference(EPartService.class);
// m_broker always non-null
m_broker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new EventHandler()
{
#Override
public void handleEvent(Event event)
{
// ... bla bla bla
}
});
}
In internal lists of IEclipseContext I found EPartService.
Can you help me? What I did wrong?

Bundle activators are not injected so you can't use #Inject.
The context returned by EclipseContextFactory.getServiceContext has very limited contents and can't be used to access things like EPartService.
In any case the bundle activator generally isn't even run until something else in your plugin is used, so it would be too late the see the startup complete message anyway.
So all this means you can't do what you want in the bundle activator start method.
To get notified about the app startup complete event you can use the application LifeCycle class or define an AddOn - both these classes are injected.
In those classes use a method like:
#Optional
#Inject
public void appStartupComplete(#UIEventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE)
org.osgi.service.event.Event event)

Related

Dagger 1 to 2 migration - Members injection methods may only return the injected type or void

Im trying to migrate our current system from dagger 1 to 2 and I been stuck for half a day on this. I don't think I'm understanding this well.
Here is my module:
public class BaseModule {
private final Context context;
private final SharedPreferences rawSharedPreferences;
public BaseModule(
Context context,
#Named("RawPreferences") SharedPreferences rawSharedPreferences
) {
this.context = context;
this.rawSharedPreferences = rawSharedPreferences;
}
#Provides
#Singleton
public Context provideContext() {
return context;
}
#Provides
#Singleton
public DevicePlatform provideDevicePlatform(AndroidDevicePlatform devicePlatform) {
return devicePlatform;
}
#Provides
#Named("RawPreferences")
#Singleton
public SharedPreferences provideRawSharedPreferences() {
return rawSharedPreferences;
}
#Provides
#Named("RawPreferencesStore")
#Singleton
public SharedPreferencesStore provideRawSharedPreferencesStore(
#Named("RawPreferences") SharedPreferences sharedPreferences) {
return new AndroidSharedPreferencesStore(sharedPreferences);
}
And my component:
#Singleton
#Component(
modules = {BaseModule.class}
)
public interface BaseComponent {
void inject (DefaultClientController defaultClientController);
void inject (StatisticsProvider statisticsProvider);
Context provideContext();
AndroidDevicePlatform provideDevicePlatform(AndroidDevicePlatform devicePlatform);
SharedPreferences provideRawSharedPreferences();
SharedPreferencesStore provideRawSharedPreferencesStore(
#Named("RawPreferences") SharedPreferences sharedPreferences);
}
I keep getting this error in provideRawSharedPreferencesStore when I run it:
Error:(168, 28) error: Members injection methods may only return the injected type or void.
I dont understand why. Can someone please help me out. Thanks!
A component can contain 3 types of methods:
inject something into some object, which is the error you see. Those methods usually return void, but you can just return the same object, if you try to have something like a builder.
MyInjectedObject inject(MyInjectedObject object); // or
void inject(MyInjectedObject object);
Subcomponents, for which you would include the needed modules as parameters (if they require initialization)
MySubcomponent plus(MyModuleA module);
and basically just "getters" or correctly called provision methods to expose objects, to manually get them from the component, and to your subcomponents
MyExposedThing getMything();
Which one of those is this?
// the line you get your error:
SharedPreferencesStore provideRawSharedPreferencesStore(
#Named("RawPreferences") SharedPreferences sharedPreferences);
You are already providing the SharedPreferencesStore from your module. There you also declare its dependency on RawPreferences: SharedPreferences. You do not have to do this again in your component.
It seems you just try to make the SharedPreferencesStore accessible, as described in 3.. If you just depend on it within the same scope / component, you could just remove the whole component. If you need the getter, you should just remove the parameter. Your Module knows how to create it.
SharedPreferencesStore provideRawSharedPreferencesStore(); // should work.

Replace default pop-up window when exception throws on top level in RCP 4 application

How can I replace default pop-up window when exception throws on top level in RCP 4 application?
You can set a class implementing IEventLoopAdvisor in the application Eclipse Context. This is given all unhandled errors.
Something like:
class EventLoopAdvisor implements IEventLoopAdvisor
{
#Override
public void eventLoopIdle(final Display display)
{
display.sleep();
}
#Override
public void eventLoopException(final Throwable exception)
{
// TODO Your code
}
}
Note: It is extremely important to call display.sleep in the eventLoopIdle method.
A good place to set this up is the #PostContextCreate of your LifeCycle class (if you have one):
#PostContextCreate
public void postContextCreate(final IEclipseContext context)
{
context.set(IEventLoopAdvisor.class, new EventLoopAdvisor());
}
Note: IEventLoopAdvisor is an internal class so normally I would not advise using it, but this use does seem to be allowed.

Using HeaderResponseContainer: No FilteringHeaderResponse is present in the request cycle

I'm trying to add a custom HeaderResponseContainer in my wicket application. The tutorial looks quite simple (see Positioning of contributions), but when I add these lines and run the application I alwas get an IllegalStateException:
java.lang.IllegalStateException: No FilteringHeaderResponse is present in the request cycle. This may mean that you have not decorated the header response with a FilteringHeaderResponse. Simply calling the FilteringHeaderResponse constructor sets itself on the request cycle
at org.apache.wicket.markup.head.filter.FilteringHeaderResponse.get(FilteringHeaderResponse.java:165)
at org.apache.wicket.markup.head.filter.HeaderResponseContainer.onComponentTagBody(HeaderResponseContainer.java:64)
at org.apache.wicket.markup.html.panel.DefaultMarkupSourcingStrategy.onComponentTagBody(DefaultMarkupSourcingStrategy.java:71)
...
Yes, I already saw the note about FilteringHeaderResponse. But I am not sure where I should call the constructor. I already tried to add it in renderHead before calling response.render but I still get the same exception:
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
FilteringHeaderResponse resp = new FilteringHeaderResponse(response);
resp.render(new FilteredHeaderItem(..., "myKey"));
}
You can create a decorator that wraps responses in a FilteringHeaderResponse:
public final class FilteringHeaderResponseDecorator implements IHeaderResponseDecorator {
#Override
public IHeaderResponse decorate(IHeaderResponse response) {
return new FilteringHeaderResponse(response);
}
}
And that set it during application initialization:
Override
public void init() {
super.init();
setHeaderResponseDecorator(new FilteringHeaderResponseDecorator());
}
I just ran into this same problem and found that the Wicket In Action tutorial leaves out the part about setting up a custom IHeaderResponseDecorator in your main Wicket Application init. The Wicket guide has a more thorough example:
Apache Wicket User Guide - Put JavaScript inside page body
You need something like this in your wicket Application:
#Override
public void init()
{
setHeaderResponseDecorator(new JavaScriptToBucketResponseDecorator("myKey"));
}
/**
* Decorates an original IHeaderResponse and renders all javascript items
* (JavaScriptHeaderItem), to a specific container in the page.
*/
static class JavaScriptToBucketResponseDecorator implements IHeaderResponseDecorator
{
private String bucketName;
public JavaScriptToBucketResponseDecorator(String bucketName) {
this.bucketName = bucketName;
}
#Override
public IHeaderResponse decorate(IHeaderResponse response) {
return new JavaScriptFilteredIntoFooterHeaderResponse(response, bucketName);
}
}

GWT SyncProxy Testing

I create a new Web Application Project with the standard GWT example. Then i want to test the greetingserviceimpl with the following test class. I don't know where is the problem. I also upload the project: http://ul.to/1pz1989y
public class RPCTest extends GWTTestCase {
#Override
public String getModuleName() {
// TODO Auto-generated method stub
return "de.GreetingTest";
}
public void testGreetingAsync() {
GreetingServiceAsync rpcService = (GreetingServiceAsync) SyncProxy.newProxyInstance(GreetingServiceAsync.class,"http://127.0.0.1:8888/GreetingTest.html?gwt.codesvr=127.0.0.1:9997");
rpcService.greetServer("GWT User", new AsyncCallback<String>() {
public void onFailure(Throwable ex) {
ex.printStackTrace();
fail(ex.getMessage());
}
public void onSuccess(String result) {
assertNotNull(result);
finishTest();//
}
});
delayTestFinish(1000);
}
}
Validating newly compiled units
Ignored 1 unit with compilation errors in first pass.
Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors.
[ERROR] Line 17: No source code is available for type com.gdevelop.gwt.syncrpc.SyncProxy; did you forget to inherit a required module?
[ERROR] Unable to find type 'de.client.RPCTest'
[ERROR] Hint: Previous compiler errors may have made this type unavailable
[ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly
Your rpc service is async - it doesn't finish by the time that the testGreetingAsync method returns. GWTTestCase (but you are extending TestCase, you should probably change this) has support for this though - call delayTestFinish at the end of the method to indicate that the test is async. Then, call finishTest once you are successful.
public class RPCtest extends GWTTestCase {
public void testGreetingAsync() {
GreetingServiceAsync rpcService = (GreetingServiceAsync) SyncProxy.newProxyInstance(GreetingServiceAsync.class,"http://127.0.0.1:8888/Tests.html?gwt.codesvr=127.0.0.1:9997");
rpcService.greetServer("GWT User", new AsyncCallback() {
public void onFailure(Throwable ex) {
//indicate that a failure has occured
ex.printStackTrace();
fail(ex.getMessage());//something like this
}
public void onSuccess(Object result) {
//verify the value...
assertNotNull(result);
//Then, once sure the value is good, finish the test
finishTest();//This tells GWTTestCase that the async part is done
}
});
delayTestFinish(1000);//1000 means 'delay for 1 second, after that time out'
}
}
Edit for updated question:
The test class 'de.RPCTest' was not found in module 'de.GreetingTest'; no compilation unit for that type was seen
Just like your regular GWT code must be in a client package, so must your GWTTestCase code - this also gets run as JavaScript so it can properly be tested as if it were in a browser. Based on the error, I'm guessing your EntryPoint, etc are in de.client - this test should be there too.

jBoss deployment of message-driven bean spec violation

I have an java EE application which has one message-driven bean and it runs fine on JBoss 4, however when I configure the project for JBoss 6 and deploy on it, I get this error;
WARN [org.jboss.ejb.deployers.EjbDeployer.verifier] EJB spec violation:
...
The message driven bean must declare one onMessage() method.
...
org.jboss.deployers.spi.DeploymentException: Verification of Enterprise Beans failed, see above for error messages.
But my bean HAS the onMessage method! It would not have worked on jboss 4 either then.
Why do I get this error!?
Edit:
The class in question looks like this
package ...
imports ...
public class MyMDB implements MessageDrivenBean, MessageListener {
AnotherSessionBean a;
OneMoreSessionBean b;
public MyMDB() {}
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
//Lookup sessionBeans by jndi, create them
lookupABean();
// check message-type, then invokie
a.handle(message);
// else
b.handle(message);
} catch (SomeException e) {
//handling it
}
}
}
public void lookupABean() {
try {
// code to lookup session beans and create.
} catch (CreateException e) { // handling it and catching NamingException too }
}
}
Edit 2:
And this is the jboss.xml relevant parts
<message-driven>
<ejb-name>MyMDB</ejb-name>
<destination-jndi-name>topic/A_Topic</destination-jndi-name>
<local-jndi-name>A_Topic</local-jndi-name>
<mdb-user>user</mdb-user>
<mdb-passwd>pass</mdb-passwd>
<mdb-client-id>MyMessageBean</mdb-client-id>
<mdb-subscription-id>subid</mdb-subscription-id>
<resource-ref>
<res-ref-name>jms/TopicFactory</res-ref-name>
<jndi-name>jms/TopicFactory</jndi-name>
</resource-ref>
</message-driven>
Edit 3:
I just removed all my jars from the project, and only re-added relevant ones (from new versions also) to put out NoClassDefFound errors.
Still the problem remains.
Edit:
Any directions, what area should I look at? My project, or jboss-configration, or the deployment settings??
org.jboss.ejb.deployers.EjbDeployer.verifier
looks for
public void onMessage(javax.jms.Message)
via some code like this (this is from JBoss5):
/**
* Check if the given message is the onMessage() method
*/
public boolean isOnMessageMethod(Method m)
{
if ("onMessage".equals(m.getName()))
{
Class[] paramTypes = m.getParameterTypes();
if (paramTypes.length == 1)
{
if (Message.class.equals(paramTypes[0]))
return true;
}
}
return false;
}
It is important that the parameter type is javax.jms.Message and nothing else, for example some subclass or superclass or some implementing class.
Your signature is public void onMessage(Message message) which looks ok on first sight.
A Class is equal only in its ClassLoader. If for some reasons javax.jms.Message is available in different classloaders in the same JVM, strange things can happen, depending on the ClassLoader of the EjbDeployer.verifier. Maybe the EjbDeployer.verifer has a access to javax.jms.Message in another ClassLoader as MyMDB. As result, both javax.jms.Message are not equal to each other, although they are the same byte-code and literally exists. The EjbVerifier will warn about missing onMessage, because javax.jms.Message on ClassLoader A is not equal to javax.jms.Message on ClassLoader B.
This can happen when libraries with javax.jms.Message is copied on wrong places on the JBoss AS. So I guess - from a distance - that there is some jars containing javax.jms.Message in wrong places on the JBoss or the EAR. For example some wrong jbossallclient.jar in the EAR.
Make sure your EAR does not contain its own copies of the javax.ejb classes (or any javax classes at all, for that matter). JBoss 4 and 6 have rather different classloading semantics, and what works on one may not work on the other. For example, if your EAR's lib contained its own copies of Message or MessageListener, then it may no longer work.
I tried it out on "JBossAS [6.0.0.20100911-M5 "Neo"]" and Eclipse Helios
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.Message;
import javax.jms.MessageListener;
#MessageDriven(
activationConfig = { #ActivationConfigProperty(
propertyName = "destinationType", propertyValue = "javax.jms.Topic"
) },
mappedName = "topic/A_Topic",
messageListenerInterface = MessageListener.class)
public class MyMDB implements MessageListener, MessageDrivenBean {
private static final long serialVersionUID = -4923389997501209506L;
public MyMDB() {
// TODO Auto-generated constructor stub
}
#Override
public void ejbRemove() {
// TODO Auto-generated method stub
}
#Override
public void setMessageDrivenContext(MessageDrivenContext arg0) {
// TODO Auto-generated method stub
}
#Override
public void onMessage(Message message) {
// TODO Auto-generated method stub
}
}
And this setting works. Do you have the same imports for your bean (perhaps there was an automatic import gone wrong???)