Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » scout » [neon] No bean returned
[neon] No bean returned [message #1751359] Mon, 09 January 2017 11:08 Go to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 567
Registered: October 2012
Location: Bern, Switzerland
Senior Member
I have a service class which is defined and used inside the scout server. The service class is annoted with @ApplicationScoped. However, when I try to use it BEANS.get() fails with an AssertionException, stating that no instance for that service class could be found.

Shouldn't the above annotation be enough to be able to resolve the bean?
Re: [neon] No bean returned [message #1751361 is a reply to message #1751359] Mon, 09 January 2017 11:13 Go to previous messageGo to next message
Matthias Zimmermann is currently offline Matthias ZimmermannFriend
Messages: 207
Registered: June 2015
Senior Member
in which maven module is the annotated service class implemented? in the scout application server?
and from which module are you trying to use BEANS.get? in the scout ui server?
Re: [neon] No bean returned [message #1751362 is a reply to message #1751359] Mon, 09 January 2017 11:14 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 123
Registered: March 2010
Senior Member
As most di frameworks we also use jandex to boost app startup.
Jandex caches class meta data.

Probably the new bean you created is not yet in the cache.

In development startup the app by resetting jandex every time (thus making it startup just a little bit slower due to jandex index rebuild)

system properyt: -Djandex.rebuild=true
Re: [neon] No bean returned [message #1751363 is a reply to message #1751362] Mon, 09 January 2017 11:16 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 123
Registered: March 2010
Senior Member
And another possible cause:
Only modules containing a META-INF/scout.xml are included in the bean inventory.

Check if the module (eclipse java project, maven module etc. are the same things) ontains the file
/project-name/src/main/resources/META-INF/scout.xml with

<?xml version="1.0" encoding="UTF-8"?>
<scout>
</scout>
Re: [neon] No bean returned [message #1751368 is a reply to message #1751363] Mon, 09 January 2017 13:06 Go to previous messageGo to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 567
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Matthias & Ivan

Thanks for your answers.

The class is defined and used in the application server (hence no @TunnelToServer annotation). So the scout.xml file is present

There are other services that are used by the client (@ApplicationScoped & @TunnelToServer) which can be accessed from the client (where I assume the proxy is returned by BEANS.get()).

The class where I have the problem is only used once a user logs in on the client. I've also changed the code, so the client doesn't trigger the action until 30 seconds after the GUI is shown after login, so there should be sufficient time for Jandex to have done its rebuilding.

For testing I did the following:

app.client
@ApplicationScoped
public class ClientOnlyService {
    public void doSomething() {
        BEANS.get(RemoteService.class).executeAction()
    }
}

MyClientSession.load() {
  // ... start job with a delay of 30 seconds
}

class MyDelayedJob implements IRunnable {
    @Override
    public void run() throws Exception {
       BEANS.get(ClientOnlyService.class).doSomething();
    }
}


app.server
@ApplicationScoped
@TunnelToServer
public class RemoteService {
   public void executeAction() {
      BEANS.get(ServerOnlyService.class).doTheWork();
   }
}

@ApplicationScoped
public class ServerOnlyService {
   public doTheWork() {
      // ...
   }
}


All of these classes have an empty constructor using sysout() to tell me when they are created. I can see in the console that the ClientOnlyService is instantiated after the 30 second delay is up. Immediately afterwards I can see that the RemoteService is instantiated on the server side. However, when RemoteService.executeAction() tries to get the ServerOnlyService bean, an exception is thrown and the constructor of ServerOnlyService is never called. I've tried adding @CreateImmediately, but even then, the constructor is never called. For some reason this class is not picked up by Jandex.

I'm at a loss what to try next.
Re: [neon] No bean returned [message #1751370 is a reply to message #1751368] Mon, 09 January 2017 13:21 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 123
Registered: March 2010
Senior Member
@TunnelToServer is only valid on interfaces and should be a IService (secruity checks). The interface must be known by the ui-client and the server (typically in shared module).

client:
class ClientOnlyService calls BEANS.get(IRemoteService.class).doTheWork()

shared:
@TunnelToServer
interface IRemoteService extends IService

server:
class RemoteService implements IRemoteService

calls BEANS.get(ServerOnlyService.class).doTheWork
Re: [neon] No bean returned [message #1751372 is a reply to message #1751370] Mon, 09 January 2017 13:40 Go to previous messageGo to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 567
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Ivan, you are of course right and in my real code I am using IRemoteService, I just left it out in the post to demonstrate that the ClientOnlyService and the RemoteService mechanisms seem to work but the ServerOnlyService is not picked up by Jandex.

[Updated on: Mon, 09 January 2017 13:41]

Report message to a moderator

Re: [neon] No bean returned [message #1751375 is a reply to message #1751372] Mon, 09 January 2017 13:45 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 123
Registered: March 2010
Senior Member
sorry for that. Since I did not see such an issue before, is there any chance to see that code somewhere (or a reduced form of it)
I am pretty sure it must be something obvious but I just cannot see it using code snippets.
Maybe a small hello world or another reproducible way? or a remote session?
Re: [neon] No bean returned [message #1751377 is a reply to message #1751375] Mon, 09 January 2017 14:27 Go to previous messageGo to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 567
Registered: October 2012
Location: Bern, Switzerland
Senior Member
No problem.

I'll have to see if I can extract the issue into a hello world project. I'm not sure if a remote session is possible due to our company firewall...

If I can't get it reduced to a small hello world program I'll look at it with Andy on Thursday (he'll be here then).
Re: [neon] No bean returned [message #1751378 is a reply to message #1751377] Mon, 09 January 2017 14:47 Go to previous messageGo to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 567
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Ok, I've tried to implement what I described above in a new Scout project and of course in this configuration it works flawlessly Sad

I'll try to do some more debugging. It seems that I understood how it should work but somehow probably messed up something really trivial. I'll get back to you when I've had my DUH! moment Wink
Re: [neon] No bean returned [message #1751379 is a reply to message #1751378] Mon, 09 January 2017 15:18 Go to previous messageGo to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 567
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Next update:

I changed my RemoteService as follows:

@ApplicationScoped
@TunnelToServer
public class RemoteService { // really implementing IRemoteService which is annotated :-)
   public void executeAction() {


      IBeanManager mgr = BEANS.getBeanManager();
      List<IBean<ServerOnlyService>> beans = mgr.getRegisteredBeans(ServerOnlyService.class);
      if (beans == null || beans.size() == 0) {
        System.err.println("--- No ServerOnlyService beans registered, trying to manually register beans");
        mgr.registerClass(ServerOnlyService.class);
      } else {
        System.out.println("--- Number of registered beans=" + beans.size());
      }

      BEANS.get(ServerOnlyService.class).doTheWork(); // now this line no longer causes an AssertionException
   }
}


Now, on the first timed call, I get the syserr() line, telling me no beans were registered for ServerOnlyService but my manual registering of the class works, because the call to doTheWork() is now successfully called.
On all subsequent calls, I get the sysout() line, telling me that there is 1 bean registered.

So, for some reason, despite ServerOnlyService being annotated with @ApplicationScoped and being in the same app.server project (though in a different package), it is not automatically picked up by Jandex (as opposed to the RemoteService).

Are there any reasons that could cause this (other than the @IgnoreBean annotation, which we are not using)? Anything in my class that would make it "unpickupable" by Jandex?
Re: [neon] No bean returned [message #1751390 is a reply to message #1751379] Mon, 09 January 2017 16:35 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 123
Registered: March 2010
Senior Member
A hint: why are you using the @TunnelToServer annotation on the service implementation. ONLY use @TunnelToServer on the interface.
Re: [neon] No bean returned [message #1751391 is a reply to message #1751390] Mon, 09 January 2017 16:42 Go to previous messageGo to next message
Ivan Motsch is currently offline Ivan MotschFriend
Messages: 123
Registered: March 2010
Senior Member
check the class RegisterTunnelToServerPlatformListener
It should write a log error when a class (other than interface) has the TunnelToServer annotation.

RegisterTunnelToServerBridgePlatformListener is removing the original bean and replacing it with a tunnelling proxy. Since on the serverside there is no tunnel handler (of course:-) there will be no bean available.

So I assume that the reason is that there is a TunnelToServer anno on the implementing class instead than on the interface only.
Re: [neon] No bean returned [message #1751414 is a reply to message #1751391] Tue, 10 January 2017 07:15 Go to previous messageGo to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 567
Registered: October 2012
Location: Bern, Switzerland
Senior Member
I think we are still misunderstanding each other due to my attempt at brevity Smile

I only have the @TunnelToServer annotation on the interface of my remote service (and getting the remote service works flawlessly, it's the ServerOnlyService which fails).

Also, using the code below in a standalone application works. It must be something in our production code that I'm missing. I guess I'll use the workaround shown in comments below for the time being and have a look at things with Andy on Thursday.

I'll repost my code the way it has looked from the start to make things clear.

app.shared (left out for brevity before)
@ApplicationScoped
@TunnelToServer
public interface IRemoteService {
   public void executeAction();
}


app.client
@ApplicationScoped
public class ClientOnlyService {
    public void doSomething() {
        BEANS.get(IRemoteService.class).executeAction() // this works nicely
    }
}

MyClientSession.load() {
  // ... start job with a delay of 30 seconds
}

class MyDelayedJob implements IRunnable {
    @Override
    public void run() throws Exception {
       BEANS.get(ClientOnlyService.class).doSomething(); // this works nicely
    }
}


app.server
public class RemoteService implements IRemoteService {
   public void executeAction() {

      /*
      IBeanManager mgr = BEANS.getBeanManager();
      List<IBean<ServerOnlyService>> beans = mgr.getRegisteredBeans(ServerOnlyService.class);
      if (beans == null || beans.size() == 0) {
        System.err.println("--- No ServerOnlyService beans registered, trying to manually register beans");
        mgr.registerClass(ServerOnlyService.class);
      } else {
        System.out.println("--- Number of registered beans=" + beans.size());
      }
      */


      // the next line fails if the above block is commented out, it works if the block is active
      BEANS.get(ServerOnlyService.class).doTheWork();
   }
}

@ApplicationScoped
public class ServerOnlyService {
   public doTheWork() {
      // ...
   }
}

Re: [neon] No bean returned [message #1751524 is a reply to message #1751414] Wed, 11 January 2017 07:22 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 1250
Registered: October 2011
Senior Member
I can not reproduce your problem. I have taken the hello-world application and added the your class:

@ApplicationScoped
public class ServerOnlyService {
   public void doTheWork() {
      System.out.println("DO THE WORK");
   }
}


And I can call the service from the HelloWorldService (server side).

public class HelloWorldService implements IHelloWorldService {

	@Override
	public HelloWorldFormData load(HelloWorldFormData input) {
		BEANS.get(ServerOnlyService.class).doTheWork(); // MODIFICATION: call the server service.
		
		StringBuilder msg = new StringBuilder();
		msg.append("Hello ").append(ServerSession.get().getUserId()).append('!');
		input.getMessage().setValue(msg.toString());
		return input;
	}
}


and it works.

Are you sure you have rebuild your Jandex Index at startup?
Re: [neon] No bean returned [message #1751564 is a reply to message #1751524] Wed, 11 January 2017 14:14 Go to previous message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 567
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Jérémie

Thanks for your follow-up. Interestingly enough, I can no longer reproduce the problem even in my production version.

HOWEVER:
Your last comment about the Jandex rebuild caused me to re-read Ivan's first post. I had misunderstood him the first time round, thinking that the rebuild took a certain time and my application tried to access it before the rebuild was finished. On second reading, I understood that I needed to enable the rebuild for my development version.

I have two setups for my server and ui projects: a Jetty based one (generated by the Scout SDK) and a tomcat based one. I mostly start the backend-server using the tomcat profile and the UI using Jetty. The jetty launchers already contain the jandex-rebuild property, BUT the tomcat launcher of course DID NOT. So I assume that this was the reason for this error. I guess that Jandex has some internal mechanism to occasionally rebuild its index and for some reason did so today, hence me not being able to reproduce the issue.

I have now also added the jandex-rebuild parameter to our tomcat profiles in the hope of avoiding such isses in the future.

Thanks to everyone for your help!
Previous Topic:Table and Disable Specific Cells if needed
Next Topic:[neon] AbstractOutlineViewButton behaving differently from Mars
Goto Forum:
  


Current Time: Fri Dec 15 21:55:19 GMT 2017

Powered by FUDForum. Page generated in 0.02748 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software