[JBoss Seam] - REST applications with Seam and the Restlet framework (no JS
by d1g
I have created a proof-of-concept application based on Seam and the Restlet framework. Fortunately Seam has been designed with this kind of integration in mind and the job was not difficult. I thought other users might like to see how easy this is.
By using Seam & Restlets I can reuse my existing Seam components within a dedicated REST environment and still have access to EJB 3.0 via Seam and the JBoss Embeddable EJB 3.0 container.
I'm considering using the Restlet framework to build full featured web applications backed by Seam - but of course, those apps need to be RESTful. JSF offers a different approach which is not appropriate to the projects I'm currently working on. I will still use Seam with JSF where relevant (as well as Seam's REST functionality).
This post is a follow up to my earlier post on embedding Seam (http://www.jboss.com/index.html?module=bb&op=viewtopic&t=92597). Thanks are due to Gavin for pointing me in the right direction.
If you need to know more about Restlets look at http://www.restlet.org.
My application allows you to see the name of users by accessing /users/[id] and is similar to example Restlet code. The application uses the Seam MockServletContext to simulate the presence of a Servlet container. Here is how I start Seam and the Restlet framework:
| public class SeamContainer extends Container {
|
| public SeamContainer() throws Exception {
|
| // we need to wrap all this in a call via Seam
| Lifecycle.beginCall();
|
| // retrieve Context from our Container
| Context context = getContext();
|
| // add an HTTP server connector to the Restlet container
| getServers().add(Protocol.HTTP, 8182);
|
| // attach a filter to manage calls via Seam
| SeamCallFilter seamCallFilter = new SeamCallFilter();
| setRoot(seamCallFilter);
|
| // attach a log Filter to the container
| LogFilter logFilter = new LogFilter(context, "org.restlet.seam");
| seamCallFilter.setNext(logFilter);
|
| // create a host router matching calls to the server
| HostRouter host = new HostRouter(context, 8182);
| seamCallFilter.setNext(host);
|
| // create the user router
| Router userRouter = new Router(context);
| host.getScorers().add("/users/[0-9]+", userRouter);
| userRouter.getScorers().add("$", getSeamRestlet("userRestlet"));
|
| // done with Seam for now
| Lifecycle.endCall();
| }
|
| public static void main(String[] args) {
| ServletContext servletContext = new MockServletContext();
| try {
| // start JBoss Seam
| new Initialization(servletContext).init();
| Lifecycle.setServletContext(servletContext);
| // start the container
| new SeamContainer().start();
| // TODO: stop JBoss Seam - when we make this a service
| // TODO: Lifecycle.endApplication(servletContext);
| } catch (Exception e) {
| System.err.println("Can't launch the Web server.\nAn unexpected exception occured:");
| e.printStackTrace(System.err);
| }
| }
|
| public Restlet getSeamRestlet(String name) {
| return (Restlet) Component.getInstance(name, true);
| }
| }
|
Note that my Restlet is also a Seam component, though I'm not using this to do anything right now. Restlet objects are shared by many calls so we need to be careful when injecting Seam components. Here is the Restlet source:
| @Name("userRestlet")
| @Startup
| @Scope(ScopeType.APPLICATION)
| public class UserRestlet extends Restlet {
|
| private final static Logger log = Logger.getLogger(UserRestlet.class);
|
| public void handleGet(Call call) {
|
| String output;
|
| // get user by id
| String id = call.getBaseRef().getLastSegment();
| log.debug("handleGet() user id: " + id);
|
| // load user with id and create output
| UserService userService = getUserService();
| User user = userService.loadUser(new Long(id));
| if (user != null) {
| log.debug("handleGet() user found");
| output = "User with name: " + user.getName();
| } else {
| log.debug("handleGet() user NOT found");
| output = "User not found";
| }
|
| // all done
| call.setOutput(new StringRepresentation(output, MediaType.TEXT_PLAIN));
| }
|
| public UserService getUserService() {
| return (UserService) Component.getInstance("userService", true);
| }
| }
The magic bit is a Restlet Filter which I have called SeamCallFilter. This wraps all calls that come into my Restlet application and handles the start and end of a call to Seam. Here is the source:
| public class SeamCallFilter extends Filter {
|
| private final static Logger log = Logger.getLogger(SeamCallFilter.class);
|
| protected void beforeHandle(Call call) {
| log.debug("beforeHandle()");
| Lifecycle.beginCall();
| Lifecycle.setPhaseId(PhaseId.INVOKE_APPLICATION);
| }
|
| protected void afterHandle(Call call) {
| log.debug("afterHandle()");
| Lifecycle.setPhaseId(null);
| Lifecycle.endCall();
| }
| }
|
You can guess the content of my User entity but it's worth seeing what UserService does:
| @Stateless
| @Name("userService")
| public class UserServiceBean implements UserService, Serializable {
|
| private final static Logger log = Logger.getLogger(UserServiceBean.class);
|
| @PersistenceContext(unitName = "custdb")
| private EntityManager em;
|
| public UserServiceBean() {
| super();
| log.debug("UserServiceBean()");
| }
|
| public long saveUser(User user) {
| log.debug("saveUser()");
| em.persist(user);
| return user.getId();
| }
|
| public User loadUser(long id) {
| log.debug("loadUser()");
| return em.find(User.class, id);
| }
| }
There are some obvious limitations when using Seam in this manner. Primarily, you can't use the Session and Conversation context (no Servlet API) and you can't use other Servlet / JSF features (validation, model updates, etc).
It would be helpful if Seam were enhanced to make using non Servlet/JSF applications easier (I needed to include the Servlet API and MyFaces on the classpath to get my application to work). Ideally Servlet/JSF would be pluggable in Seam, as well as the Seam components and contexts that become irrelevant.
If you want the source please let me know.
Dig.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3978556#3978556
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3978556
19 years, 8 months
[JBoss/Spring Integration] - javax.naming.NameNotFoundException: jndi not bound
by tvan
Hi,
I got an exception when deploying my application to Jboss:
anonymous wrote :
| org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: jndi not bound
|
I defined <jndi-name>jndi/myAppliDS</jndi-name>in myappli-ds.xml.
I called it in the bean:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
| <property name="jndiName">
| <value>jndi/myAppliDS</value>
| </property>
| </bean>
| <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" singleton="true" >
| <property name="dataSource">
| <ref bean="dataSource"></ref>
| </property>
| <property name="mappingResources">
| <list>
| <value>Address.hbm.xml</value>
|
| </list>
| </property>
| <property name="hibernateProperties">
| <props>
| <prop key="hibernate.dialect">xxx.yyy.zzz.hibernate.RdbDialect</prop>
| <prop key="hibernate.cglib.use_reflection_optimizer">false</prop>
| <prop key="hibernate.show_sql">true</prop>
| <prop key="hibernate.default_batch_fetch_size">16</prop>
| <prop key="hibernate.max_fetch_depth">1</prop>
| <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
| <prop key="jta.UserTransaction">java:comp/UserTransaction</prop>
| <prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop>
| <!-- prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.OC4JTransactionManagerLookup</prop-->
| <prop key="hibernate.connection.release_mode">auto</prop>
| </props>
| </property>
| </bean>
|
|
What is wrong with that? With the server oc4j, it has no problem. But here I have a headache: Jndi is not bound. I even added
| <prop key="hibernate.connection.datasource">java:/comp/env/jndi/myAppliDS</prop>
| in the hibernateProperties, but the problem still remains! If anyone has a tip.
Thank you very much.
Tvan
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3978553#3978553
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3978553
19 years, 8 months
[JBoss jBPM] - Re: Task Not Being Created?
by jed204
No, the AssignmentHandler isn't being called when I use the process from the database. I added some logging to the assignment handler and it looks like it's only called once the task is trying to be created. Here's the log from the two methods being run:
| 10:24:06,281 INFO [UserAdminScreen] Starting Test Process via Coded Definition
| 10:24:06,281 DEBUG [GraphElement] event 'process-start' on 'ProcessDefinition(the baby process)' for 'Token(/)'
| 10:24:06,296 DEBUG [GraphElement] event 'before-signal' on 'StartState(start)' for 'Token(/)'
| 10:24:06,296 DEBUG [GraphElement] event 'node-leave' on 'StartState(start)' for 'Token(/)'
| 10:24:06,296 DEBUG [GraphElement] event 'transition' on 'Transition(baby cries)' for 'Token(/)'
| 10:24:06,296 DEBUG [GraphElement] event 'node-enter' on 'TaskNode(t)' for 'Token(/)'
| 10:24:06,296 DEBUG [GraphElement] event 'task-create' on 'Task(change nappy)' for 'Token(/)'
| 10:24:06,296 INFO [NappyAssignmentHandler] <-------------- Setting Actor ID in NappyAssignmentHandler
| 10:24:06,296 DEBUG [GraphElement] event 'task-assign' on 'Task(change nappy)' for 'Token(/)'
| 10:24:06,296 INFO [NappyAssignmentHandler] --------------> DONE SETTING ACTOR
| 10:24:06,296 DEBUG [GraphElement] event 'after-signal' on 'StartState(start)' for 'Token(/)'
| 10:24:06,296 INFO [UserAdminScreen] Token Node: TaskNode(t)
|
Here is the same process def loaded from the DB, but not task is created:
| 10:24:08,046 DEBUG [JbpmContextInfo] creating jbpm context with service factories '[message, scheduler, logging, persist
| ence, authentication]'
| 10:24:08,046 DEBUG [JbpmContext] creating JbpmContext
| 10:24:08,046 INFO [UserAdminScreen] Starting Process via Definition [Test]
| 10:24:08,046 DEBUG [DbPersistenceServiceFactory] creating persistence service
| 10:24:08,046 DEBUG [DbPersistenceService] creating hibernate session
| 10:24:08,046 DEBUG [DbPersistenceService] beginning hibernate transaction
| 10:24:08,062 DEBUG [GraphElement] event 'process-start' on 'ProcessDefinition(Test)' for 'Token(/)'
| 10:24:08,062 DEBUG [GraphElement] event 'before-signal' on 'StartState(start)' for 'Token(/)'
| 10:24:08,062 DEBUG [GraphElement] event 'node-leave' on 'StartState(start)' for 'Token(/)'
| 10:24:08,062 DEBUG [GraphElement] event 'transition' on 'Transition(baby cries)' for 'Token(/)'
| 10:24:08,078 DEBUG [GraphElement] event 'node-enter' on 'TaskNode(t)' for 'Token(/)'
| 10:24:08,078 DEBUG [GraphElement] event 'node-leave' on 'TaskNode(t)' for 'Token(/)'
| 10:24:08,078 DEBUG [GraphElement] event 'transition' on 'Transition(1281264)' for 'Token(/)'
| 10:24:08,078 DEBUG [GraphElement] event 'node-enter' on 'EndState(end)' for 'Token(/)'
| 10:24:08,078 DEBUG [GraphElement] event 'process-end' on 'ProcessDefinition(Test)' for 'Token(/)'
| 10:24:08,078 DEBUG [GraphElement] event 'after-signal' on 'StartState(start)' for 'Token(/)'
| 10:24:08,078 INFO [UserAdminScreen] Token Node: EndState(end)
|
Is there any other reason that the task wouldn't be created? Does anyone else have this problem?
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3978552#3978552
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3978552
19 years, 8 months