The Portal for Java is a reference implementation written in Java of the server counterpart of the Portal project which provides useful semantics and concepts for modern web application development in the server side as well as server implementation.
The Portal and Portal for Java project is developed and maintained by Donghwan Kim. If you are interested, please subscribe to the discussion group.
The following list of modules are available.
core: provides API and SPI.bridge: makes the application run in the following environment.atmosphere: Servlet container.play: Play framework.vertx: Vert.x.
objectfactory: delegates bean creation to the following framework.evaluator: evaluate an expression using the following expression language.spel: Spring Expression Language.
The easiest way to get started with Portal is to try out and look at examples. Thanks to Ralph, various online demos and source codes are available now at http://ha-bio.rasc.ch/portal-demos Try out!
Also, officialy a very simple chat application is provided with each bridge module to help getting started.
A simple echo handler which echoes back any message.
portal.open("/echo").send("message", "hello").message(function(data) {
console.log(data);
});@Bean
public class EchoHandler {
@On
public void message(Socket socket, @Data String message) {
socket.send("message", message);
}
}A simple chat handler which broadcasts a received message to the room.
portal.open("/chat").on({
open: function() {
this.send("message", "Hi, there");
},
message: function(message) {
console.log(message);
}
});@Bean
public class ChatHandler {
@Wire
private Room hall;
@On
public void message(@Data String message) {
hall.send(message);
}
}Any event which occurs in anywhere in the server side can be sent to the client.
portal.open("/notifications").on(notifiers);@Component
public class NotificationEventListener implements ApplicationListener<NotificationEvent> {
@Inject
private App app;
@Override
public void onApplicationEvent(NotificationEvent e) {
Notification n = e.notification();
app.hall().send(n.type(), n.data());
}
}Changes in domain layer can be applied to presentation layer in real time as well.
portal.find("/entity").on("account#" + id, function(model) {
console.log(model);
});@Entity
public class Account extend Model {
@PostUpdate
public void updated() {
App.find("/entity").room("account#" + id).send("updated", this);
}
}Event data can be object and be converted to the specific type based on JSON format.
portal.find().send("account.save", {username: "flowersinthesand", email: "flowersinthesand@gmail.com"});@Bean
public class AccountHandler {
@On("account.save")
public void save(@Data Account account) {
account.save();
}
}Using reply callback, the client can retrieve data from the server asynchronously like AJAX.
portal.find("/band")
.send("find", 45, function(band) {
console.log(band);
})
.send("query", query, function(bands) {
console.log(bands);
});@Bean
public class BandHandler {
@On
@Reply
public Band find(@Data Long id) {
return Band.byId(id));
}
@On
public void query(@Data String query, @Reply final Reply.Fn reply) {
new Thread(new Runnable() {
@Override
public void run() {
try {
reply.done(query...list);
} catch (EntityException e) {
reply.fail(e);
}
}
})
.start();
}
}Service bean can be executed directly via the portal.
portal.find("/account")
.send("find", 23, function(account) {
console.log('found');
console.log(account);
}, function(error) {
console.log(error.type + ":" + error.message);
})
.send("remove", 45, function() {
console.log('deleted');
}, function(error) {
console.log(error.type + ":" + error.message);
});@Bean
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao dao;
@Override
@On
@Reply
public Account find(@Data long id) throws EntityNotFoundException {
return dao.find(id);
}
@Override
@On
@Reply(failFor = EntityNotFoundException.class)
public void remove(@Data long id) {
dao.remove(id);
}
}