jEmbedded-0.1.3-Release Announcement.

1 view
Skip to first unread message

Adolfo Estevez

unread,
Dec 19, 2009, 3:59:41 AM12/19/09
to jEmbedded Discussion Group
Hi all,

I'm very pleased to announce that I've just released the
jEmbedded-0.1.3 version.

It's much more that a collections of fixes from the previous RC
versions as I have included some features that was intended for the
0.2 version (or higher), but it gives a good preview of the future
direction of the project. In fact I though to label this one as 0.2,
but I didn't for consistency.


There are 5 very important features included in this release:

- Annotation inheritance: Now you can extend any of the core
annotations (@AnnotatedService, @AbstractAnnotatedService...) to
create you own annotations. This means that you can set up your
services directly using annotations like if you were writing and xml
bean in Spring:

Until now you were doing this (still you can of course):

@AnnotatedService(id="service", resources={WebClient.class})
public class Service extends AbstractCMTService {

@Compose(ref="webClient")
private WebClient webClient;

@Inject (value=${service.url})
private String url;
}
}

Now you could do this:

public @interface CustomAnnotatedService {

Class <?> inherits() default @AnnotatedService; // the annotation you
want to extend.

//now you override the attributes you'd like to use (this case from
the @AnnotatedService(id, lazy clazz, etc..),
// the ones that are not overriden will be taken from the parent.

String id() default "service";

String clazz() default "org.jsemantic.jembedded.Service";

Class[] resources() default {WebClient.class};

//new attributes
String url();

}

Now the service looks like this:

@CustomAnnotatedService(url="http://code.google.com/p/jembedded")
public class Service extends AbstractCMTService {

@Compose(ref="webClient")
private WebClient webClient;

@Inject (value=${service.url})
private String url;
}

Now you can reuse this new annotation whenever you like.

The inheritance mechanism can be used with the core annotations
(AnnotatedService, AbstractAnnotatedService, AnnotatedBean,
AnnotatedComponent..).

If you have a look at the source code or to the examples you will see
that I have refactored the code to use this feature when it fits.


- @AbstractAnnotatedService

This is a very and a powerful feature that also will give you an idea
of the future direction of the framework. Now you can create a Service
using an abstract class (similar to the @AbstractService) without
needing to extend or implement anything (not even the Service
interface). You can mix regular and abstract classes and injecting or
composing fields.

This is the old example of WebServer refactored to use the new
features (also custom and inheritance annotaions).

@AnnotatedWebServer
public abstract class WebServer {

@Start
public void start() {
getJettyService().start();
}

@Stop
public void stop() {
getJettyService().stop();
}

public void setPort(String port) {
getJettyService().setPort(port);
}

//Composition, WebServer will handle the jettyService lifeCycle
@Compose(ref="httpService")
public abstract JettyService getJettyService();

@Compose(ref = "propertiesService")
@PropertiesService(propertiesFile="META-INF/web-server/web-
server.properties")
public abstract
org.jsemantic.jirepository.core.services.properties.PropertiesService
getPropertiesService();
// end of service composition

//Added functionality, you can create dynamic invoking methods from
any service
//that you may have in the container
@ImplementedBy(ref="httpService", refMethodName="getServerContext")
public abstract ServletContext getServletContext();

}

If you read the code you would notice:

- The abstract methods are implemented in real time, so you can use
then in the regular implemented methods.

- There are 2 new annotations @Start and Stop that replaces the old
startService and stopService.

- The service can be cast to Service (even though it does not need to
implement it).

- If you like the PropertiesService can be declared at class level,
this is just a choice, you have as much freedom as usual.

- @Compose new annotation: works like @Inject, but ties the lifecycle
of the composed service to the parent Service, not the container. In
other words, the composed service will be started and stopped by the
parent service. For example, if you declare the propertiesService at
class level the propertiesService will be handled by the container,
nor by the WebServer:

@AnnotatedWebServer
@PropertiesService(propertiesFile="META-INF/web-server/web-
server.properties")
public abstract class WebServer {

@Start
public void start() {
getJettyService().start();
}

@Stop
public void stop() {
getJettyService().stop();
}

public void setPort(String port) {
getJettyService().setPort(port);
}

//Composition, WebServer will handle the jettyService lifeCycle
@Compose(ref="httpService")
public abstract JettyService getJettyService();

}

In the case of the jettyService it makes sense its lifecyle it's tied
to the WebSever but you can also do this:

@AnnotatedWebServer
@PropertiesService(propertiesFile="META-INF/web-server/web-
server.properties")
public abstract class WebServer {

@Inject (you can use Compose here too), here the container will
handle the jettyService
private JettyService jettyService;

@Start
public void start() {
jettyService.start();
}

@Stop
public void stop() {
jettyService.stop();
}

public void setPort(String port) {
jettyService.setPort(port);
}

//Added functionality, you can create dynamic invoking methods
from any service
//that you may have in the container
@ImplementedBy(ref="httpService", refMethodName="getServerContext")
public abstract ServletContext getServletContext();

}

As you can see you have a lot of freedom to compose or create new
Services with the new features, you can annotate at class, method or
field leve, using abstract or regular methods.

You can also provide a interface for the service if you like or need
it.

The @AnnotatedWebServer ann looks like this:

public @interface AnnotatedWebServer {

/**
*
* @return
*/
String id() default "webServer";

/**
*
* @return
*/
Class<?> inherits() default AbstractAnnotatedService.class;

/**
*
* @return
*/
Class<?>[] resources() default { JettyServiceImpl.class };
}


- Integration testing framework integrated within the container and
services (jIntegration therefore is depecrated):

I've always felt that the testing process should be more integrated
into the development process so what I did was to include the testing
framework within the core framework and the services so now it's
availble at any time (I left the jUnit4 dependency optional though).

So basically now the core framework has an Assert class with some
useful classes and the same happens with the services.

For instance the core has Assert.getService(), Assert.existService()
and so on.

In order to setup a unit test class (or integration test class) you
need to use @Container and the @RunWith annotation. Keep in mind that
the Asserts are static classes so the created container must be
attached to the current thread, so you need to use the
prototype_by_thread annotation.

@RunWith(IntegrationTestClassRunner.class)
@Container(instanceType=ContainerInstanceType.PROTOTYPE_BY_THREAD)

@WebClient
@Include(resources=WebServer.class)
public class IntegrationWebServerTest {

//dispose the container between test methods invocations, if you want
to reuse the same within invocations, delete this method
@After
public void dispose() {
ContainerHolder.releaseCurrentThreadContainer();
}

@Test
public void test() {
WebServer server = (WebServer)Assert.getService("webServer");
assertNotNull(server);
}
}

As you see you don't need to create a container yourself,one will be
created for you by the testing framework.

- Ruby now it's a separate service and services can be fully
implemented with it. Have a look at the new CalculatorService example
that mix a complete ruby service with a java one.

- New Spring AOP Service.

- Core and services Refactored.

I have refactored some parts of the core but I will work more on this.
The services and annotations have been refactored as well and adapted
to the new features.

- Examples and case study.

I have completely refactored them and adapted to the new features,
trying always to simplify as much as possible.

The case study has been completely refactored and simplified (I have
removed GWT in this version), usign the new features and services. I'm
writing a complete paper about this, but I think you will find easier
to understand this time.


- RoadMap

As you can see a lot of effort has been put into this release, not
only to improve the past version but to look to into the future.
The @AsbtractAnnotateService and the annotation inheritance are 2
powerful features and examples of this. The idea is to implement all
the services and elements without any asbtract class (like
AbstractCMTService) and make the services more intelligent.


- Versions 0.1.3 to 0.2 - Maintenance and fixes. Improve Services and
examples . Complete documentation.

- Versions 0.2 ->1.0 - New features (removing the need of abstract
services etc) and new services. More scripting languages.

As I'm designing the new versions, please any features you think it
would be nice to have please let me know.

Special thanks to all of you that downloaded jEmbedded and helped me
to improve it. Your comments are always appreciated.

I will dedicate the next few weeks to upto date the documentation.
Please be patience, I promise I will do it :)


Reply all
Reply to author
Forward
0 new messages