Groovy DSLD and ServiceLoader pattern - eclipse

I have in my Groovy scripts an implicit variable, "services", whose role is to lookup services in a registry.
I can call it with the following syntaxe :
def myService = services.lookup 'com.test.MyService'
The implementation of the lookup method doesn't return an instance of MyService, but a special GroovyObject which delegate missing methods to the service.
I want to tell Eclipse that calls to myService should be delegated to MyService, in order to add to the autocompletion list all methods from MyService. However, I didn't success to implements it with a DSLD definition.
Is it possible to implement such behavior ?

I have used two contributions :
The first one discover every call to services.lookup and populates a map in wormhole
The second one declare every properties in the wormhole map as a global property
A simplified version :
contribute(isMyDSL() & currentType('ServiceProxy') & bind(exprs: assignedVariable(currentType()))) {
def name = exprs[0].leftExpression.name
def classType - exprs[0].arguments.getExpression(0).text /* Introspecting MethodCall */
def services = wormhole.services
if (!services) {
services = [:]
wormhole.services = services
}
services[name] = classType
}
contribute(isMyDSL() & isThisType()) {
wormhole.properties?.each { name, type ->
property name:name, type:type, doc:"OSGI Service: ${type}"
}
}

Related

Scala design suggestion needed

I would like to design a client that would talk to a REST API. I have implemented the bit that actually does call the HTTP methods on the server. I call this Layer, the API layer. Each operation the server exposes is encapsulated as one method in this layer. This method takes as input a ClientContext which contains all the needed information to make the HTTP method call on the server.
I'm now trying to set up the interface to this layer, let's call it ClientLayer. This interface will be the one any users of my client library should use to consume the services. When calling the interface, the user should create the ClientContext, set up the request parameters depending on the operation that he is willing to invoke. With the traditional Java approach, I would have a state on my ClientLayer object which represents the ClientContext:
For example:
public class ClientLayer {
private static final ClientContext;
...
}
I would then have some constructors that would set up my ClientContext. A sample call would look like below:
ClientLayer client = ClientLayer.getDefaultClient();
client.executeMyMethod(client.getClientContext, new MyMethodParameters(...))
Coming to Scala, any suggestions on how to have the same level of simplicity with respect to the ClientContext instantiation while avoiding having it as a state on the ClientLayer?
I would use factory pattern here:
object RestClient {
class ClientContext
class MyMethodParameters
trait Client {
def operation1(params: MyMethodParameters)
}
class MyClient(val context: ClientContext) extends Client {
def operation1(params: MyMethodParameters) = {
// do something here based on the context
}
}
object ClientFactory {
val defaultContext: ClientContext = // set it up here;
def build(context: ClientContext): Client = {
// builder logic here
// object caching can be used to avoid instantiation of duplicate objects
context match {
case _ => new MyClient(context)
}
}
def getDefaultClient = build(defaultContext)
}
def main(args: Array[String]) {
val client = ClientFactory.getDefaultClient
client.operation1(new MyMethodParameters())
}
}

Grails RESTful API Plugin - wrong service siginiture

I am trying to use Restful API plugin (Restful API plugin). (using Grails 2.3.8, Groovy 2.1)
As stated in documentation I created a Grails service that implements RestfulServiceAdapter.
import net.hedtech.restfulapi.RestfulServiceAdapter
import com.game.trivia.Question
#Transactional
class QuestionService implements RestfulServiceAdapter {
#Override
public Object list(def service, Map params) throws Throwable{
List Q = Question.list(params)
return Q;
}
.
.
.
When trying to access the service: http://localhost:8080/test_triv/api/questions
I received following exception:
{"errors":[{"type":"general",
"errorMessage":"No signature of method: test_triv.QuestionService.list() is applicable for argument types:
(org.codehaus.groovy.grails.web.servlet.mvc.GrailsParameterMap) values:
[[pluralizedResourceName:questions, action:[...], ...]]\nPossible solutions: list(java.lang.Object, java.util.Map),
is(java.lang.Object), wait(), find(), wait(long), with(groovy.lang.Closure)"}]}
So I implemented another list method (which is not part of the interface):
public Object list(Map params) throws Throwable {
List Q = Question.list(params)
return Q;
}
Which works ok.
Am I doing something wrong?
Do I implement the correct interface?
Do I have to expose a service for each domain or there is any way to use an existing controller instead of a service?
Creating new service is a big overhead! I already have controllers for all domains.
Just got reply on this issue from Charlie (The pludin developer):
Our documentation should be clearer in this area, so I'll take an action to look at improving it.
You should not implement the RestfulServiceAdapter within a service, but implement and register an adapter that implements this interface if you need to adapt an existing service that does not provide the expected methods.
Since you are writing a new service, you can just expose the required methods (you don't need to implement any interface). Note the contract is essentially the same as the adapter interface, without the 'service' argument that represents the service to which the adapter would delegate.
To avoid needing an adapter, a service should expose these methods:
def list( Map params ) throws Throwable { ... }
def count( Map params ) throws Throwable { ... }
def show( Map params ) throws Throwable { ... }
def create( Map content, Map params ) throws Throwable { ... }
def update( def id, Map content, Map params ) throws Throwable { ... }
void delete( def id, Map content, Map params ) throws Throwable { ... }
The controller is intended to delegate to a service that contains business logic, and it cannot delegate to another controller. Our expectation is the RestfulApiController and other controllers within an application would share services (e.g., a ThingController and the RESTfulApiController could both use the same ThingService so that business logic is not duplicated).

apache commons pool - how to use a factory that takes arguments

I am trying to use apache commons pool to create a pool of 'objects'. Since I already have an object factory which takes a string type argument and create a right type of object I want to use this factory.
But the problem is that none of the signatures of generic pool object allow me to pass a factory which takes arguments.
//This is a wrapper class that holds an Object pool
Class INService {
private ObjectPool<INConnection> pool_ = null;
/**
* Constructs an instance of INService, given a pool size
* and a class which implements INHandler interface.
* #param poolSize - size of the service pool
* #param c - the class which handles the INHandler service interface.
*/
public INService(int poolSize, String objectType) {
pool_ = new GenericObjectPool<INConnection>(factory, Objecttype); // won't compile.
}
...
}
The PoolableObjectfactory interface defines methods like makeObject, destroyObject, validateObject, activateObject and passivateObject. But no makeObject() method which takes parameters.
It seems that the only way I can do this is to write multiple factory classes for each type of object and write an if-else stuff, like:
public INService(int poolSize, String objectType) {
if (objectType.equals("scap")
pool_ = new GenericObjectPool<INConnection>(scapFactory);
else if (objectType.equals("ucip")
pool_ = new GenericObjectPool<INConnection>(ucipFactory);
...
}
Or, is there any elegant way, instead of duplicating/creating several factory classes just for this sake?
You should read up on the KeyedObjectPool<K,V> interface which can also be found in commons-pool.
From its javadoc:
A keyed pool pools instances of multiple types. Each type may be accessed using an arbitrary key.
You could then implement a KeyedPoolableObjectFactory<K,V> to make instances based on the key parameter, it has the makeObject(K key) function you are looking for.
PS: It appears you haven't marked any answers to your questions as "accepted", you might want to work on that.

Play! 2.0 Scala - Accessing global object

I've declared an object which gets instantiated on application start. I want to access it inside a controller, which is part of a plugin. I want to be able to use that plugin, but I can't seem to get past the first part -- finding the MyWebsocketConnection object. None of the examples show how to do this. I don't want to inject into the controller because I'm writing a plugin (I saw static examples of how to do that somewhere).
Global.scala, plugin application \app\Global.scala
object Global extends GlobalSettings {
object MyWebsocketConnection {
val logger = // return something that gets instantiated once, like websocket object for logging to ui
}
class MyWebsocketConnection {
import MyWebsocketConnection.logger
}
override def onStart(app: Application) {
Logger.info("Application has started...");
}
}
My custom logging plugin controller:
MyLogger.Scala, plugin application \app\controllers\MyLogger.scala
object MyLogger {
def info(message: String) = {
// THIS CAN'T BE FOUND ?
// MyWebsocketConnection.logger.send(message)
}
}
So, from the Play! 2.0 app that references the plugin, I would (probably) do something like below, but I can't even get past the part before this:
MyFutureController.scala, another Play! application \app\controllers\MyFutureController.scala
object MyFutureController extends Controller {
def someRandomMethod = Action {
// Custom logging
MyLogger.info("Here's my log message!");
Ok("This documentation stinks!")
}
}
There is also workaround #3: move your Global class to a package and specify its fully qualified name in application.conf file, like so:
global= my.packaged.Global
The problem is that your Global objects resides in default package. And in Java, classes from default package can't be referenced from other packages, they are accessible only within the same package (default).
I see two workarounds of this problem.
Move MyWebsocketConnection to some named package (say config) so it can be accessible in your application.
object MyLogger {
def info(message: String) = {
config.MyWebsocketConnection.logger.send(message)
}
}
Move your whole application into single package (but it is a lot of pain)
foo
|--controllers
|--models
|--views
|--Global.scala
Then Global object will resides in foo package and will be accessible within application.

How to work with dependency injection within SOA?

I'm currently using SOA, I've a bunch of Service, (ArticleService, CommentService, UserService, etc..)
I also have a ConfigurationService which is filled from an XML configuration file.
I'm using Zend Framework.
THis configuration service is needed in some of my service, and I'm using dependency injection, is it a good practice, to add ConfigurationService in constructor of most my Service to be able to fetch global configuration?
Thank you for your feedbacks.
I would say, no, don't pass the config container - neither as a service nor as an array nor a Zend_Config instance - in the constructor of your other services. I would keep the injection (whether by constructor or by setter) for those services focused on the actual objects/collaborators/data they actually need.
So, for example, an ArticleService might depend upon an ArticleRepository interface/object or on an ArticleMapper or on a db adapter. Let the constructor/setter signatures for the ArticleService reflect what it truly needs.
Instead, what I would do is during Bootstrap, create some kind of factory object - perhaps as an application resource - that accepts in its constructor your config data/object/service (or even better, the bootstrap instance itself, from which you could get, not just your config data, but also any application resources, like a db adapter, that were created during the bootstrap process). Then write methods on your factory object that create/deliver the other services you need. Internally, the factory maintains a registry of already created services so that it can lazy-create instances where required.
A snippet of what I have in mind might be as follows:
Bootstrap snippet:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initFactory()
{
$factory = new My_Factory($this);
return $factory;
}
}
Then the factory:
class My_Factory
{
protected $_registry;
protected $_bootstrap;
public function __constructor($bootstrap)
{
$this->_bootstrap = $bootstrap;
}
public function getDbAdapter()
{
if (!isset($this->_registry['dbAdapter']){
$this->_bootstrap->bootstrap('db'); // probably using app resource
$this->_registry['dbAdapter'] = $This->_bootstrap->getResource('db');
}
return $this->_registry['dbAdapter'];
}
public function getArticleService()
{
if (!isset($this->_registry['articleService']){
$dbAdapter = $this->getDbAdapter();
$this->_registry['articleService'] = new My_ArticleService($dbAdapter);
}
return $this->_registry['articleService'];
}
public function getTwitterService()
{
if (!isset($this->_registry['twitterService']){
$options = $this->_bootstrap->getOptions();
$user = $options['twitter']['user'];
$pass = $options['twitter']['pass'];
$this->_registry['twitterService'] = new My_TwitterService($user, $pass);
}
return $this->_registry['twitterService'];
}
}
Then in a controller, you could grab an ArticleService instance:
class SomeController extends Zend_Controller_Action
{
protected $_factory;
public function init()
{
$this->_factory = $this->getInvokeArg('bootstrap')->getResource('factory');
}
public function someAction()
{
$articleService = $this->_factory->getArticleService();
$this->view->articles = $articleService->getRecentArticles(5); // for example
}
}
The upshot here is that each service explicitly identifies the collaborators it needs and the factory is a single place that takes care of creating/injecting all those collaborators.
Finally, I confess that I am just spitballing here. To me, this is essentially a rudimentary dependency injection container; in that sense, using a fully-featured DIC - perhaps the Symfony DIC or the new Zend\Di package in ZF2 - might be better. But after many months of struggling with all the best-practice recommendations to inject your dependencies, this is what I have come up with. If it's goofy or just plain wrong, please (please!) straighten me out. ;-)