JAX-RS: Server-side user interface - java

I have a JAX-RS REST service which needs to provide some visual server side output when a REST endpoint is invoked. Later on, I might also want to provide a user interface which an administrator will use for interacting with the web service. I could obviously build REST endpoints for this interaction, and have the administrator invoke these (from a different machine or the same machine) using a provided client application with a UI, but I would like to avoid exposing this functionality to the network. In order to make deployment easy, I would also like everything (i.e. the web service and its administrator UI) to be part of the same application.
I have found that my JAX-RS application will throw a HeadlessException if I try to construct a JFrame or any other top level UI element as described here. I have also found that I can avoid this by setting the system property -Djava.awt.headless=false.
I think I may be able to achieve what I need by setting the headless system property as above and defining a singleton startup EJB that will handle all server side UI tasks:
#Singleton
#Startup
public class UiBean {
private JFrame frame;
#PostConstruct
public void init() {
SwingUtilities.invokeLater(() -> {
frame = new JFrame();
// ...setup UI...
});
}
// JAX-RS resources will inject the UiBean and invoke methods as this one when UI updates are needed.
public void updateSomeUiComponent() {
SwingUtilities.invokeLater(() -> { ... });
}
}
I realise that this design is not ideal. Are there other ways of achieving my requirements? The software being built is a prototype and time is of the essence, so I would like to avoid having to learn complete new technologies (already invested a lot in learning JAX-RS and JPA). Quick-and-dirty is ok, I guess I'm just looking for the least dirty solution ;).
Thanks in advance!

Related

How to create mock VaadinSession for integration tests?

My Issue:
This is my first time doing tests for Vaadin UI and I am also fairly new to Unit tests in general. My issue is that I can't do anything with my UI components Views because there is no VaadinSession which handles the UI beans. A VaadinSession is never created when using #SpringBootTest. I was able to create tests for my backend since Spring handles those beans, but I can't seem to figure out a way to get Vaadin to start up a session so I can then access the session and do different integration and unit tests.
What I've Tried
TestBench: The Vaadin testbench seemed like a very good option but the issue that I faced was that it doesn't seem to open a VaadinSession whenever I open a ChromeDriver() that goes to the website on my localhost.
Karibu Library: This library seemed like a very good option, but there was one issue, which was that it opens individual UI components that are instantiated, however a couple of my UI Components Classes, uses dependency injection to inject backend services. I cannot instantiate these classes because of the dependeny injection.
The UI Component that I need to access through the VaadinSession.
#Component
#UIScope
#CssImport("./styles/current-info-styles.css")
public class CurrentDayView extends VerticalLayout implements Updatable {
private static final long serialVersionUID = 1L;
//Some code here
#Autowired
public CurrentDayView(NowcastWeatherService nowcastWeatherService, GeoLocationService geoLocationService) {
this.nowcastWeatherService = nowcastWeatherService;
this.geoLocationService = geoLocationService;
//Some Code here
}
//Some code here
My Testbench approach
#RunWith(SpringRunner.class)
#SpringBootTest
public class CurrentDayViewTest extends TestBenchTestCase {
#Test
public void fakeTest() {
Assert.assertTrue(true);
}
#Before
public void startUp() {
System.setProperty("webdriver.chrome.driver", "src/main/resources/drivers/chromedriver.exe");
setDriver(new ChromeDriver());
getDriver().get("http://localhost:8080/");
populateViewWithInformation();
}
#After
public void tearDown() {
getDriver().quit();
}
private void populateViewWithInformation() {
CurrentDayView currentDayView = (CurrentDayView) VaadinSession.getCurrent().getAttribute("current-day-view");
//This is where I get an error because VaadinSession.getCurrent() is null
}
My Final Question:
Does anyone have any idea on how I could have a VaadinSession created or atleast get spring to keep track for Vaadin UI components? If this wasn't clear then please feel free to ask more clarifications relating to my question.
I suggest you give Karibu another shot, it's great for doing these kinds of tests that don't need the app to be running.
Take a look at the Karibu V14 Spring demo project. Pay attention to what Karibu dependency is used. The ApplicationTest#listOrders test contains navigation to a view with autowired dependencies.
The issue with your TestBench test is that TestBench is used to test against a running application, and the tests run in an entirely different process than the actual application.
So when you open the page with the driver, a Vaadin session is created in the application, but you will not be able to access it in your tests, nor will you be able to access any UI state or views. What it allows you to do, however, is to interact with the application as you would do through the browser (clicking buttons, filling in text fields etc.), and to check that the state in the browser is correct, without knowing anything about the server's internal state.
Generally speaking, when you're writing integration tests with TestBench (which is based on Selenium), what you're doing is directing the browser. You're writing Java code, yes, and the code may even be in the same project as your Vaadin UI code, but it can be executed against any URL and what you're interacting with is the browser's DOM. You're describing what the end-user would do: click a button, write some text in an input field, choose an option from a radio button group. The server-side is a black box. After all, if I submit a post on StackOverflow, I can't check if it gets stored in a database - all I can do is look at what I see after I press the "Post your answer" button. If you really want to nitpick, it doesn't even need to be a Vaadin application you're testing with TestBench, as long as the application behaves like one in the browser.
Secondly, you shouldn't store any Components in the VaadinSession. If you open a Vaadin application in multiple browser tabs, each of those tabs will share the same VaadinSession. A single Component instance should only be used inside one browser tab, where the root component is the current UI.

EJB-like communication of REST components

I'm designing software with different components, that need to communicate with each other through a REST interface.
I've seen and implemented solutions, where the different components of the software (deployed on the same cluster) would communicate by declaring and injecting EJB beans. This way, it's really easy to standardize the communication by defining common interfaces and DTOs in a separate .jar dependency.
This level of comfort and standardization is what I'd like to achieve with RESTful services, between Java-based components of my software.
Imagine something like this:
Let's say, I have a REST Client (C) and a REST Server (S).
I'd like to be able to communicate between them, via a common interface, which is implemented in S and called by C. This common interface is in an API component (I).
It would mean that I would have an interface:
#RestController
#RequestMapping("/rest/user")
public class UserController {
#GetMapping("list")
ResponseEntity<List<UsersModel>> getUserList(OAuth2LoginAuthenticationToken token);
}
In C it could be used like:
public class Sg {
private final UserController userController;
...
public void method(OAuth2LoginAuthenticationToken token) {
...
userController.getUserList(token);
...
}
}
Lastly, in S:
public class UserControllerImpl implements UserController {
#Override
public ResponseEntity<List<UsersModel>> getUserList(OAuth2LoginAuthenticationToken token) {
...
}
}
The only configuration needed is to tell the client the context root (and host address) of the server, everything else is present in the common interface in the form of annotations.
Since not all components are necessarily Java-based, it is important for the REST resource to be callable in a typical REST-like way, so those Java remote service calling mechanics are out of consideration.
I was looking into JAX-RS, which seems promising, but is missing a couple of features that would be nice. For example, there isn't a common interface telling the client which endpoint on the server can the REST resource be found, neither are the method names, etc. AFAIK, on the client, you can only call the method representing the HTTP method of the request, which is a bummer.
Am I out of my mind with this spec? I'm not really experienced with REST services yet, so I don't really know if I'm speaking of something that is out of the REST services scope. Is there an already existing solution to the problem I face?
After more thorough research, I found that RESTeasy already has a solution for this.
You need to use the ProxyBuilder to create a proxy of your interface and that's it.

How to develop a web application with a bunch of feature modules

I am developing a web application using spring framework and google app engine. I am wondering if there is a design pattern or framework with the help of which I can develop features of my application as pluggable modules. For example I have identified 4 features of the application:
Oauth Login
User Profile Management
User Group creation
User File management
Now what I need is to develop all these features as independent modules, so that i can detach any of them dynamically and they are as loosely coupled as possible. They can have their own database implementation, their own set of technologies etc. Is there a design principle to implement modules in such a way.
You can take a look at MQ systems (such as RabbitMQ, ActiveMQ).
MQ system will work as intermediate layer, which provide you loosely coupling.
Communication between modules will be implemented as posting messages to queue and listening for posting.
Also, OSGI may help you. It gives you possibility to make your application as a set of pluggable modules, which might be loaded dynamically.
As per my experience, I suggest, Use MVC pattern. Use Servlet filttersfor 1.Oauth Login.
Create service/POJOs to implement and inject each other according to your requirement for
2.User Profile Management
3.User Group creation
4.User File management
If you know Spring AOP, use. So that you can achive more dynamic integration between implementations of points 2,3, and 4.
You should split the feature in two components: API and implementation. The first one contain interfaces, the second their implementations. You pass the interface to web app controller and inject implementation via Spring or any other Dependency Injection framework. For example
web-app, UserController which handles requests from client and delegate to your components
#Component
public class UserController {
private FileManager fileManager;
#Autowired
public UserController(FileManager fileManager) {
this.fileManager = fileManager;
}
#GET("/user/{userId}/file/{fileId}")
public File getUserFile(long userId, long fileId) {
fileManager.getUserFile(userId, fileId);
}
}
file-mgt-api where you define interfaces to decouple web-app from implementation
public interface FileManager {
File getUserFile(long userId, long fileId);
}
file-mgt-impl where all the details of how to get requested file
#Component
public class FileManagerImpl implements FileManager {
#Override
public File getUserFile(long userId, long fileId) {
// get file by id from DB
// verify that provided user is the file owner
// do other useful stuff
// return the file or throw exception if something wrong
}
}
Do the same for group, profile management and other features. After that you can easily replace implementation by replacing single jar file. Your web-app is completely decoupled and don't know anything about implementation details, it only depends on interfaces.

wildfly have a ever running process run in the background

I'm making a html5/js game that will have online capabilities for my backend I've decided to use a wildfly server. The client will communicate with the server via web sockets.
I intended for my wildfly server to also be in charge of game logic decisions such as moving npc's. My plan was to have a #startup bean that would run a server game loop to handle this logic. The server loop would then talk to the serverEndPoint via HornetQ. My serverEndPoint and server loop look like this:
ServerEndPoint
#ServerEndpoint(value= "/game/{user-id}")
public class GameEndpoint {
#Inject
GameManager gameState;
GameWorld gameWorld;
Player p;
private Logger logger = Logger.getLogger(this.getClass().getName());
#OnOpen
public void onOpen(Session session){
//do stuff
}
#OnMessage
public void onMessage(Session session, String message){
//do stuff
}
#OnClose
public void onClose(CloseReason reason){
//do stuff
}
#OnError
public void error(Throwable t){
//do stuff
}
}
GameWorld
#Startup
#Singleton
public class GameWorld {
#Inject
GameManager gameState;
private Logger logger = Logger.getLogger(this.getClass().getName());
#PostConstruct
public void init(){
gameloop();
}
private void gameloop(){
while(true){
logger.info("This is a test!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#PreDestroy
public void terminate(){
//do stuff
}
}
the issue with this is that the server loop freezes everything as it is a infinite loop(for instance if I try and access the html web page I get a 404). obviously this could be solved if the serverLoop was on its own seperate thread but after doing some research it seems threading in jboss is very difficult as its hard to know what dependencies to inject e.t.c
Can anyone shed some light on how I can solve this issue? any help on the matter would be amazing.
What you have encountered has to do with what Java EE is and what it not is: Java EE is optimized for handling many concurrent, short-lived requests, each of which (usually) handle a single transaction. The containers do that very well, particularly with stateless beans, but also with stateful beans (cluster replication etc). As such, Java EE might be well-suited to process the requests coming from your HTML5/JS clients and feed the requests to the messaging infrastructure. Java EE is not, however, designed for long running, thread-blocking background processes like yours.
FWIW: Another issue that you have not yet encountered is, even if you could get that one fixed: Next you'll encounter the transaction timeout on your #PostConstruct method.
I think you are better of with moving the game engine out of the Java EE stack. You already mentioned you plan to use HornetQ - then why not put the game engine in a simple standalone application that receives messages from HornetQ and feeds replies back into HornetQ.
Another option might be a dedicated Java game server engine, see, e.g., this question and its accepted answer on programmers.stackoverflow.com. (Update: it seems the "RedDwarf Server" project mentioned in that answer was discontinued 3 years ago).
If you absolutely want to use the Java EE environment, I suggest you use a TimerService instead. Note, however, that this also requires that your game loop calculation is quick and guaranteed to finish until the next timeout is scheduled, otherwise the container will skip the scheduled invocation (with a "still running" message or similar).
Finally, let me mention that if I were to start a new game server today, I would definitely take a look at Akka, Node.js or similar projects that support "reactive" programming.

How to have the ability of invoking methods by http?

I've written an an API giving some methods like
runApp();
stopApp();
doSomethingElse();
currently I have a jar file with which I run these methods.
I want to be able to invoke these method by http.
For example, going to : http://localhost:8080/something/runApp
will invoke runApp() method.
I've heard that this should be done with webservices, and particularly REST API.
Is webservices the only way to achieve this?
And if so, can someone summarize the simplest ways to implement this ability, or point me to an existent summary?
Thanks.
Here's a RESTful API example based on your pseudocode, with JAX-RS:
#Path("/something")
public class MyApp {
#GET
#Path("/runApp")
public Response runApp() {
return Response.ok("Running app").build();
}
#GET
#Path("/stopApp")
public Response stopApp() {
return Response.ok("Stopping app").build();
}
#GET
#Path("/doSomethingElse") {
return Response.ok("Doing something else").build();
}
}
Which when built and deployed into any JEE5 or JEE6 web capable container will allow you to access services those services at:
http://localhost:8080/something/runApp
http://localhost:8080/something/stopApp
http://localhost:8080/something/doSomethingElse
Assuming your server is running on localhost:8080, of course. Having said that, nothing in this example is really RESTful, and would be better implemented using JAX-WS.
You've pretty much described exactly what a web service is. Code gets run when you hit a particular URL with a particular type of request.
As to how to build a web service in Java, there's a huge amount of documentation out there on the web (and SO) on that. You should not have any trouble finding useful articles.

Categories