Dynamic update of SparkJava website - java

I develop a web app with Spark famework. On one of the sites I want to enable dynamic content loading. What I mean by that is that in Java controller I search for some info in the server and I want to update the website when search finishes, e.g.:
// this is called by get("/module", (req, resp)-> ...);
public static ModelAndView getModules(Request req, Response res) {
Map<String, Object> model = new HashMap<String, Object>();
List<Module> modules = new ArrayList<>();
model.put("modules", modules);
lookForModules(this);
return new ModelAndView(model, "pathToSiteSource");
}
private lookForModules(Listener listener){
// modules search in the background thread
// when any module is found I inform the listener;
// different modules can be found in various times
}
public void onModulesFound(List<Module> modules){
// I want to update the site using the modules that I got
}
I read that WebSockets are a way to go, but examples with WebSockets on Spark website uses AJAX calls, and my search has to be done in my java class. Are WebSockets the correct way to do this anyway?

I managed to solve my problem in some way.
Tha Java code is as above, plus in onModuleFound method I update a static list of modules that I store in my controller class (not as a variable in getModules method).
Then in the site code I added AJAX call that updates this specific div every three seconds. That causes calling getModules, and setting the most recent modules list into my site's model.
Not sure if this is the best solution, but it works pretty OK for me.

Related

Create a database-service in AWS Lambda

I am developing a web-application using java and spring-boot on AWS Lambda Service.
I am designing it to have one database-service. This will be collections of Entity(table) and JPARepositories classes. So If I need to have any database schema changes I just have to make the change only in this service.
The other services which will be exposed through an API-gateway will be using this database-service as a Lambda Layer.
parent-project
|
|---database-service
|
|---API-service1
|
|---API-service2
...
The Problem is I need to create the tables before any of the Lambda Service is deployed. So that this API-Services can use them. One way to solve this is to deploy the database-service as a Lambda function and invoke the function which will call a method like below to create all the tables.
#SpringBootApplication
public class DatabaseServiceApplication implements CommandLineRunner {
private DynamoDBMapper dynamoDBMapper;
private final AmazonDynamoDB amazonDynamoDB;
public DatabaseServiceApplication(AmazonDynamoDB amazonDynamoDB) {
this.amazonDynamoDB = amazonDynamoDB;
}
public static void main(String[] args) {
SpringApplication.run(DatabaseServiceApplication.class, args);
}
#Override
public void run(String... strings) {
dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
CreateTableRequest tableRequest = dynamoDBMapper
.generateCreateTableRequest(Association.class);
tableRequest.setProvisionedThroughput(
new ProvisionedThroughput(1L, 1L));
TableUtils.createTableIfNotExists(amazonDynamoDB, tableRequest);
}
}
Or use a script to create the tables. I am not sure which is a better option or is there any better option.
Can anyone suggest me if anyone has faced this problem before and fixed it?
To me the best way to do this is on Lambda cold start. Your code needs to be smart enough to not care if the DB is already correct. Based on the code you're showing I would do something on the order of:
public class LambdaExample implements RequestStreamHandler {
// only called on cold start
public LambdaExample() {
dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
CreateTableRequest tableRequest = dynamoDBMapper
.generateCreateTableRequest(Association.class);
tableRequest.setProvisionedThroughput(
new ProvisionedThroughput(1L, 1L));
TableUtils.createTableIfNotExists(amazonDynamoDB, tableRequest);
}
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) {
// handle request. this lambda type requires reading the inputStream
// yourself but use whatever you normally have here.
}
If you're using a traditional relational database, you could use Flyway instead. It too knows if a DB has already been updated.
Note that if you have thousands of Lambdas they will all call this, slowing the cold start of every single one of them. That is why #MarkB is suggesting a process to externalize the DB creation as really only the very first Lambda kicked off does anything useful. After that you're wasting a bit of time/money with every new Lambda.
Since you are deploying via Terraform then the correct way to do this is to have Terraform create the DynamoDB tables as well. You would configure your aws_lambda_function resources in Terraform with depends_on property referencing the aws_dynamodb_table resource, so that Terraform would ensure the table is created before the Lambda functions.
Can you please answer the below questions?
1) Are you deploying your springboot application in lambda?
If Yes, that doesn't sound like a good use of Springboot, Springboot application should be hosted in EC2/ECS instance to be up and running (24/7).
Think about Lambda as a function that runs to handle a simple task. To achieve that, you can write a simple Java application, and deploy the jar to lambda function.
2) CloudFormation, TerraForm and other languages are used to create the infrastructure, you usually run the infrastructure job first, and the deployment after it.
Here's a link of a terraform structure I built for a personal project.
https://github.com/saifmasadeh/terraform-project-structure

Switch between AWS, Azure. Design pattern

We have developed some lambda function and deployed on AWS which are working fine,
Anyhow, client is now planning for AZURE.
They may even switch back to AWS or any other vendor in future.
We have a separate maven project for AWS related stuff.
Hence, our business logic and classes remains same.
What I have done is created a maven project and added individual lambda functions to this project as dependencies.
Then made a factory class which will get impl based on property AZURE or AWS(using class.forName and reflection).
SO, I can switch to Azure by just removing maven dependency and adding AZURE dependency.
According to picture my plan was to create new AzureUtils and AzureWrapper project and Directly use Azure Cloud, by switching cloud in cloudFactory which is present in Generic utils and that would even work hopefully (Not tested) AWS is working anyhow like that.
Now the problem is client does not want everything packed up in 1 jar, i.e no no to all lambdas in a single jar. He want some layer where the switching should take place.
Now Which design patter would be useful, what would be the approach.
Currently my Lambda function looks like below
public class Hello implements RequestHandler<S3Event, Context > {
public String handleRequest(S3Event s3event, Context context) {
.................
call to business processor as in diag
}
}
And azure function looks somewhat like a simple class with annotations
public class Function {
#FunctionName("hello")
public HttpResponseMessage run(
#HttpTrigger(name = "req", methods = { HttpMethod.GET, HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("Java HTTP trigger processed a request.");
// Parse query parameter
String query = request.getQueryParameters().get("name");
String name = request.getBody().orElse(query);
if (name != null) {
call to business processor as in diagram
}
}
}
After all this I have only 2 questions
I would like to know first if the design in diagram is right thing to do.
And what my client is asking for a wrapper something magical which should handle both type of cloud implementations. is this even possible?
if possible guide me in right direction
Any help is greatly appreciated.
about you secound question how to handle both type of cloud, please check this 3rd part solution serverless.com. It's a company that create own serverless wrapper, so that you can be free of vendor lock

How to make server-side domain models available to client-side web browser?

In my web application utilizing Spring MVC, I have a rich domain model.
I would like to make this domain model available to a client web browser. For example, as my domain model includes a class Person with methods Set<Person> getFriends() and DateTime getBirthday(), I would like to use these methods on the client side. Usage scenarios include
dynamically updating the visiting browser's HTML to list all friends when requested so by the user, or
sort persons in the HTML by their birthday.
Please notice I'm not looking here for accessing my domain model in the "view rendering stage" (e.g. JSP). I am looking here for accessing my domain model on my web application's users' browsers. So for example I don't want to sort Person instances during the "view rendering stage". I want this sorting to happen later, on my user's browser.
What are solutions to my challenge?
Javascript - there are frameworks that could help ease the burden. The scenario you have described is an Ajax call to some service. You could represent the data as json which would be lightweight and easy enough to add to the page using javascript.
Ember.js (specifically its Models) and Grails do exactly what you want when used together. I'm sure that you can use any Java framework to do this, but Grails makes it stupidly easy. Below are a few patterns to get you started, but here's a complete example app!
Domain class:
class Person {
String name
}
Controller:
class PersonsController {
def index() { render (["person": Person.list()] as JSON) }
}
Ember.js App:
App.Store = DS.Store.extend({
revision: 11,
adapter: DS.RESTAdapter.create({
namespace: 'app'
})
)};
App.Person = DS.Model.extend({
name: DS.attr('string')
)};
In your browser, this single command will populate the in-browser data store by fetching /app/persons from the backend. Modifying the in-browser instances will automatically HTTP POST the updated instance to your Controller.
App.Person.list()
You'll want to check out my answer on getting the two to play together in perfect harmony for more complex applications.
Abdull have you looked at GWT(Google Web ToolKit) http://bit.ly/YYz2Yx?
Here is some sample code that illustrates creation of client side components.
e.g. loading contacts
VerticalPanel contactsPanel = new VerticalPanel();
contactsPanel.setSpacing(4);
String[] contactNames = constants.cwStackPanelContacts();
String[] contactEmails = constants.cwStackPanelContactsEmails();
for (int i = 0; i < contactNames.length; i++) {
final String contactName = contactNames[i];
final String contactEmail = contactEmails[i];
final Anchor contactLink = new Anchor(contactName);
contactsPanel.add(contactLink)
http://bit.ly/12MOhZQ (for actual code sample)
If you were not limited to the browser - and thus javascript, I'd scream RMI about now. Luckily, there seems to be a solution to make it work. I have not tried it, but it might be worthwhile:
jabsorb is a simple, lightweight JSON-RPC library for communicating
between Javascript running in the browser and Java running on the
server. It allows you to call Java methods on the server from
Javascript as if they were local, complete with automatic parameter
and result serialization.
https://code.google.com/p/jabsorb/
Two populer javascript MVC frameworks:
http://backbonejs.org/
http://knockoutjs.com/
You can try them personally. suggestion are always subjective, your choice are always subjective as well. so just feel it yourself.

Server side access data for smartGWT rpc

On the server side I want to know how to access data used in an RPCRequest from SmartGwt.
Here is the SmartGwt client code:
private void update() {
RPCRequest request = new RPCRequest();
request.setData("RPC text from client");
request.setActionURL("/Empi-MT/resources/empi/update");
request.setContentType("text/xml");
RPCManager.sendRequest(request,
new RPCCallback() {
public void execute(RPCResponse response, Object obj, RPCRequest request) {
SC.say("Response from the server:" + obj);
}
});
}
Here is the RESTful java server code .
#POST
#Consumes("text/xml")
#Produces("text/xml")
#Path("/update")
public String update() {
return "We got to here";
}
This trivial code works fine, but now I need to know how to access the data that was put into the RPCRequest. How do I do that in the server code?
Thanks,
You look like you may be heading in the wrong direction; if this "update" operation is a CRUD operation on some object, you want to using DataSources - take a look at the QuickStart overview of Data Integration, focusing on RestDataSource.
http://www.smartclient.com/releases/SmartGWT_Quick_Start_Guide.pdf
Also you seem to be starting down the road of using generated REST services, this is almost always wrong - see this FAQ:
http://forums.smartclient.com/showthread.php?t=8159#aExistingRest
Finally if this really is not a CRUD operation, you want to set useSimpleHttp on the RPCRequest, and then the docs for this property explain the different ways data can be sent.
http://www.smartclient.com/smartgwtee/javadoc/com/smartgwt/client/rpc/RPCRequest.html#getUseSimpleHttp()

Is there a way to generate boilerplate code for RESTful stacks?

As I get more into RESTful APIs, the (good) simplicity of the approach means that you generate a LOT of boilerplate code, and code that has to match in three or four different places, e.g. for a Jersey-based stack:
HTML on the web page which provides controls (a button Create Foo)
JS on the web page which formulates the JSON and the request to create a Foo
A FooRest class method to handle the request and create a Foo
A Foo class to instantiate, which will manipulate the data structure
Are there tools which provide a starting point for some or all of this code automatically, possibly starting from something straightforward like a JSON data structure? E.g., provide:
card: {
methods: [GET],
}
handOfCards: {
methods: [GET POST PUT DELETE],
}
and at the very least end up with Ajax requests, CardRest and HandOfCardsRest classes with the specified methods stubbed out, and Card and HandOfCards classes with properties or getters/setters?
Have you tried Backbone.js? It is a JavaScript library that handles REST Ajax requests for you. It allows you to define your models to wrap the data and provides setters, getters, save and delete functions, etc.
It also allows you to bind the models to views which generate the UI HTML.
I think nearly any *rails application does all of this for you. Grails is my favorite right now, and once you get the initial setup done (a single command) you create domain classes with another command.
Once those are created, you can generate both views (html) and controllers for handling all of these actions with a single command, and the boiler plate is sufficient for a lot of initial sites. It will even create test cases for you, although you'll need to define what the actual tests do. You can program it by convention very easily, or create your own mappings from URLs -> controller actions. It has a ton of plugin support and easily handles remote submission of forms (via javascript) built in.
It doesn't take a json data structures for creation, but the domains are very easily created (using groovy) and it autowires getter/setters, service injections, etc as it is based on the Spring Framework.
Your goal should probably not be code generation of boilerplate but actually writing less code.
Spark is a Java micro web framework based on Sinatra.
Here's some example code:
import static spark.Spark.*;
import spark.*;
public class HelloWorld {
public static void main(String[] args) {
get(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. Show something ..
}
});
post(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. Create something ..
}
});
put(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. Update something ..
}
});
delete(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. annihilate something ..
}
});
options(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. appease something ..
}
});
}
}
An alternate (or addition) to Juan's answer, you might want to check out Knockback.js , which takes the best of Knockout and adds the best of Backbone.js . Backbone has support for RESTful API's via it's "sync" functions. Quoting their website:
The method signature of Backbone.sync is sync(method, model,
[options])
method – the CRUD method ("create", "read", "update", or "delete")
model – the model to be saved (or collection to be read)
options – success and error callbacks, and all other jQuery request options
You might want to try a different approach altogether and try somethink like project lombok. It will at least let you nix all your getters and setters.

Categories

Resources