I need some advice about planning the application's architecture. I want to upgrade my console version of Chat Application to JavaFX. So I started planning. Now I have one main class to manage client and one to manage server. And the problem appears at first glance. I want to make login/register window where "I" will connect to the server and validate data from input fields such as login etc. And when everything is correct I want to pass my already created connection (socket, streams, etc.) to the main chat window.
How do I do that in the CORRECT way?
I mean how to manage one class Client through multiple windows?
When/Where instantiate the Client object?
Because you said :
I need some advice about planning the application's architecture
There are many patterns for JavaFx applications such as abstract MVC(Model-View-Controller),MVVM(Model-View-View-Model),MVC with Service layer,MVP(Model-View-Presenter) and the choice of pattern or the architecture depends on your project and what do you want achieve.
Based on #James_D comment ,it is better to use MVC model with Service layer (if you need Service Layer to manage your connection) .I made this schema for you to describe aproxiamtly the benefits of this pattern:
Now for client login you can validate your data in Login controller by checking client inputs and make your test (true or false) (it must having a stored data ) to manage many clients because if you use static test if(userNameField.getText()=="Ala Eddine") in this state you will handle many clients with same shared data after that you can show Dialog if iputs are false ..etc.
In your ServerController when you launch your server create a loop that recieve each time a new connection and in this state you have two choice :
Handle client in ServerContoller by creating Inner classes
Add ServiceImp Class to handle clients
For MVC model ,you should respect relationships OneToOne and OneToMany... etc between your models.Your model depends on real life,for example:
Father has many children
Child has one father
In your example
Server has many Clients.
Client has many Messages
Message has content,attachments,date as properties..
Now you can see aproxiamtly the tree of packages :
In the end you can see the communication between controllers :
I did it this way:
//loading main chat window fxml
FXMLLoader loader = new FXMLLoader(ClientMain.class.getResource("your_path.fxml"));
Parent mainSceneFXML = loader.load();
//getting controller object
MainController ctrl = (MainController)(loader.getController());
Now you can access needed attributes or methods from ctrl. Replace MainController with classname of your controller of main chat window.
Related
I have two instances of clients with different configs that I am creating (timeout, threadpool, etc...), and would like to leverage Dropwizard's metric on both of the clients.
final JerseyClientBuilder jerseyClientBuilder = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration());
final Client config1Client = jerseyClientBuilder.build("config1Client");
environment.jersey().register(config1Client);
final Client config2Client = jerseyClientBuilder.build("config2Client");
environment.jersey().register(config2Client);
However, I am getting
org.glassfish.jersey.internal.Errors: The following warnings have been detected:
HINT: Cannot create new registration for component type class org.glassfish.jersey.client.JerseyClient:
Existing previous registration found for the type.
And only one client's metric shows up.
How do I track both clients' metrics or is it not common to have 2 clients in a single dropwizard app?
Never mind, turned out I was an idiot (for trying to save some resource on the ClientBuilder).
2 Things that I did wrong with my original code:
1. You don't need to register Jersey clients, just the resource is enough... somehow I missed the resource part in my code and just straight up trying to register the client
2. You need to explicitly build each JerseyClientBuilder and then build your individually configured clients, then dropwizard will fetch by each JerseyClientBuilder's metrics
In the end, I just had to change my code to the following:
final Client config1Client = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration()).build("config1Client");
final Client config2Client = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration()).build("config2Client");
Doh.
environment.jersey().register() has a javadoc listing of Adds the given object as a Jersey singleton component meaning that the objects registered become part of the jersey dependency injection framework. Specifically this method is used to add resource classes to the jersey context, but any object with an annotation or type that Jersey looks for can be added this way. Additionally, since they are singletons you can only have one of them per any concrete type (which is why you are getting a "previous registration" error from Jersey).
I imagine that you want to have two Jersey clients to connect to two different external services via REST/HTTP. Since your service needs to talk to these others to do its work, you'll want to have the clients accessible wherever the "work" or business logic is being performed.
For example, this guide creates a resource class that requires a client to an external http service to do currency conversions. I'm not saying this is a great example (just a top google result for dropwizard external client example). In fact, I think this not a good to structure your application. I'd create several internal objects that hide from the resource class how the currency information is fetched, like a business object (BO) or data access object (DAO), etc.
For your case, you might want something like this (think of these as constructor calls). JC = jersey client, R = resource object, BO = business logic object
JC1()
JC2()
B1(JC1)
B2(JC2)
R1(B1)
R2(B2)
R3(B1, B2)
environment.jersey().register(R1)
environment.jersey().register(R2)
environment.jersey().register(R3)
The official Dropwizard docs are somewhat helpful. They at least explain how to create a jersey client; they don't explain how to structure your application.
If you're using the Jersey client builder from dropwizard, each of the clients that you create should be automatically registered to record metrics. Make sure you're using the client builder from the dropwizard-client artifact and package io.dropwizard.client. (Looks like you are because you have the using(config) method.)
I'm using the Play framework for Java for an app. I am attempting to make it distributed by deploying copies of the application across several servers and having a configurable list of nodes in the database, which must be able to communicate between each other. In MongoDB, the list is stored in JSON like so:
{
"master": "host1.com:2678",
"nodes": ["host2.com:2678", "host3.com:2678", "host4.com:2678"]
}
The code deployed on each server is identical, but the scheduler is enabled only on the master node and will schedule particular work to nodes depending on how busy they are. Code not provided here as the specifics of the scheduler's operation isn't important for my question.
In order to know how busy they are, to schedule things and for other status updates, the nodes need to be able to communicate with each other.
Play Framework's Web Service client allows me to do this by making HTTP requests from within one node to the other like so
HttpResponse res = WS.url("http://host2.com").get();
But the idea is for specific HTTP requests (such as those used for scheduling) to be allowed only if coming from another one of the nodes (Be it the master or slave nodes) but not from a web browser, curl, etc. How do I do that securely? I can check for the host of the incoming request or particular headers but surely those are easy to forge?
If you want this to be enforced on all controllers, Check out play allowed hosts filter.
If you want to enforce this filter on a specific Controller \ method you can try to do this:
class MyController #Injects()(filter: AllowedHostsFilter) extends Controller {
def get = filter.apply(Action.async { implicit request =>
Future.successful(Ok)
})
}
You could have a look into pac4j.org they have a lot of options to implement security features on play.
You could maybe filter by ip address:
http://www.pac4j.org/1.9.x/docs/authenticators/ip.html
When developing a Web Application in Java, launching in Tomcat, I need to be able to create (dynamically) a new static address (link,URL) in the server that will be used to view the information of a new item, let's call it new_item_001, which have been just created by one user.
Say I want to create a new address
www.domain.com/webapp/items/new_item_001
which can be used to render a view of the contents of new_item_001.
Which is the best approach to do this?
Should I dynamically create a new servlet class for this view?
Should I dynamically create the folder items and one html file new_item_001 for this item inside of it?
Should I edit the server address mapping rules to create this static address and map it to a central servlet which somehow knows which item to display?
I understand the question is ill posed, and that I am far from even understanding the issue, so I would like some guidelines on what to look for.
None of the above.
You should simply have a servlet mapped to /items/*. When a request come to this servlet, analyze the actual path of the request, extract the part after /items/ to know the actual value (new_item_001) in your example, get the data corresponding to this item from the database, and send it to the browser.
Using a true MVC framework like Spring MVC would make that much easier. You could simply map a method of a controller using
#RequestMapping("/items/{itemId}")
public Item getItem(#PathVariable("itemId") String itemId) {
...
}
and let the framework do all the URL parsing for you.
I would like to tackle this in a simple way. Creating a servlet for each created item would be overkill and become quite cumbersome to manage after a successful run of the application for some time.
Changing/editing server mapping URL looks very naive approach and is not scaling too. Let configuration be there and change them only when you actually need to change them.
My suggestion is to create one servlet that handles all these requests. For example, you may save item information on a datastore or on file system(i.e images uploaded by user etc..). Next time a GET request is received by the application to fetch saved information of an item, servlet should be able to reference the item on database associated with the item id on the URL. If you don't wish to expose item id/surrogate key in the database, you can also have a simple mapping between them by implementing your own logic. Frameworks like Spring MVC do a good job in mapping URLs to resources like this should you wish to use a framework.
Additionally to minimize the number of requests to the same item, you can also implement an HTTP caching strategy(i.e. ETAG, If-Modified-Since) by instructing your web server at the time of first GET request from a user.
I am having some trouble understanding this. Can someone help me better understand this?
MVC
Model --> Java- Spring Framework
View ---> templating language(JSP velocity) & Javascript
DB --> SQL
Q-1)
Now, When I open a particular page, I can't visualize the flow. I've read about DAO, controller , service etc and I understand them individually but I am really confused when I club all together what's the order of execution? Whats the flow exactly ? Is it that first the view is loaded then it sends JS request to fetch the necessary data from backend and then the controller and service are invoked and the DAO queries the db? Then how does the API come into picture? DAO deals with the API?
Q-2)
Why do we need xyz.properties? I have removed a module from my page. If I remove a particular js file(related to that module) from the scripts.properties, then ideally that js should not get executed at all right? Then still why would I see the api call to fetch the data related to that module? I don't see the module but I sure see the api call. Why is that?
DB doesn't enter in MVC model. And you're forgetting a principal element in your analysis: the Controller. The flow goes like this:
Client performs a request to an URL
The application server gets the URL and passes the handling to the web application.
The web application using Spring MVC will handle the URL processing to the Controller: DispatchServlet, which is a Servlet.
The DispatchServlet will try handle the URL. If there's an URL mapping, then it will pass it to the class (mapped in the spring.xml config or decorated with #Controller annotation).
This controller (which in fact is part of the model) will handle the request. It will call services, daos, etc (Model) and return the necessary data to complete the response to the DispatchServlet.
The DispatchServlet will finish the request handling and, in the end, will generate the results e.g. a text/json response, or it will forward to a JSP file (View).
For question two, I never have used such scripts.properties file, so I don't know what you're talking about. Usage of a properties file is to store application properties that should not change until an application redeploy. They have 3 main advantages:
They can be easily manipulated by human users. It's no rocket science to add, edit or remove values.
Since it is a plain text, it's easier to version using a version control system like SVN, Git or another of your preference.
It provides a faster access since it is usually in the same disk as the application, so there's no much time penalty when accessing to its contents compared to a database configuration. But since it is in disk, it still has a disadvantage against RAM access only.
In simple layman's term, MVC explained in pictorial form
(inputing data) (data related part) (display rendering)
-request mapping -classes -JSP (Script,CSS,HTML)
-request param -interface -velocity
Controller ------------->Model--------------->View
||
\/
(data processing logic) (access to Databse)
-optimization -JDBC
-business logic -SQL
Service--------------------->DAO
Im am planning on creating a desktop application with JavaFX. I would like to use JavaFX only for the UI, and all backend work should be done by java(with spring).Im not sure how to develop the frontend to call the service layer, and also receive the response and display the response on the next page.
Basically I need to know the following(just an example of want i want to accomplish).
1) to call the controller class I would do something like below in 'Login.fx'?
function btnLoginAction(): Void {
var loginController = LoginController {};
loginController.authenticateUser(txtboxUsername.text.trim(), pwdboxPassword.text.trim());
}
2) LoginController would be my java class and would call the service layer. after authentication, i would want to call another page('Welcome.fx') and pass the firstname of the logged-in user as a parameter. How do I accomplish this?
Im new to javafx(java gui development as a whole), hence let me know if there is a better approach to go about this, and some links to help me better understand.
NOTE: I am using javafx 1.3.
You can use java classes from javafx, e.g. the way you suggested is correct.
To achieve that you can just add a parameter to Welcome class and set it during creation/accessing with value received from LoginController instance.
P.S.: but I really suggest you to move to JavaFX 2.0. JavaFX 1.3 script language is not supported unfortunately, so no new functionality would be accessible.