JSP MVC Model 2 Architecture Question - java

I want to develop a web application and I have access this API. In the API there are methods that allow you to get the userId of the current user via context objects. Maybe I'm overthinking this, but I'm very confused as to where to put my CurrentUserId() method. Does that method go in the controller or the model? I was thinking it goes in the model, but it seems redundant to write a property called "getUserId" to return a string called getUserId().toString(). Is this normal and I'm overthinking or am I correct? My co-worker told me to put the logic in the view, but from everything I've read you never put java code or scriplets in the view. I hope this makes sense.
Also here's a method I wrote to return the userId as a string
protected String CurrentUserId(HttpServletRequest request)
{
ContextManager ctxMgr = ContextManagerFactory.getInstance();
Context ctx = ctxMgr.setContext(HttpServletRequest request);
Id userID = ctx.getUserId();
return userID.toString();
}

It should go to Controller.
Create a utility class having this method as static
Because here HttpServletRequest is this model specific(jsp,servlet) , suppose tomorrow if you want to apply the same model to your desktop application then it would fail so better place is controller.

Related

Best way to pass a POJO to a spring MVC controller

I have done a few MVC controllers now and used the spring form tags to pass data back and forth but I realise now my actual understanding is a little thin. In my current case I could actually just send the response as url parameters but there are about 15 and I would prefer to send it as a pojo if possible.
My actual question... is ... is it possible to set up a spring style model attribute in a jsp without the attribute having been passed in and without using the form tags ?
So for example something along the lines of
//Pojo
Class personclass
{
private String name + getters and setters
private String address + getters and setters
private String phone + getters and setters
...
}
////first mvc call
#RequestMapping ("/")
Public ModelAndView LandingPage()
{
// no mention of Person pbject
Return mandvobject;
}
//jsp page
//This is the question!
SET ModelAttribute that wasn't passed in to the page
personclass = X
//New MVC call without a submit
window.open ("/NewMVCCall")
//New mvc call
#RequestMapping ("/NewMVCCall")
Public void newMVCPage(#ModelAttribute ("pc") personclass pc, Model model)
{
//process pc object
}
Or am I missing the point and I would have to send it as a json string parameter? Sorry my grasp of this is pretty rudimentary and I'm not sure whether I could quite easily set my own http form content or whether it is because I have used Spring form objects so far that I haven't grasped the complexity of what is going on behind the scenes (i.e form tags converting pojos to json and so on) ?
Many thanks if anyone has the time to set me on the right path...
I am not sure if I am understood your question correctly but you can link a Model to your controller without having to manually pass it to a the view every time you need it, spring will take care of that:
in your Controller :
public class MyController{
#ModelAttribute("pc")
public PersonneClass getPersonnelClass(){
return new PersonneClass();
}
#RequestMapping ("/NewMVCCall")
Public void newMVCPage(#ModelAttribute ("pc") personclass pc, Model model)
{
//process pc object
}
//other methods
}
It is a good practice to stick to java conventions when naming classes so
(personneClass ) must start with an uppercase (PersonneClass) .

Assigning/Passing value from Java function to JS/JQuery function

Lets say I have a Java function something like
public int getNumber(){
}
which returns some value based on it's logic. And I have a JS file something like
Tapestry.Validator.amountValidator = function(field, message) {
field.addValidator(function(value) {
if (value != null) {
// code here
}
}
});
};
Now I am asking myself is it possible in JS or JQuery to pass value from Java function to it's function(value) in JS and if so, how can it be achieved?
UPDATE: As suggested by abalos answer, Tap for myself has already done 3 out of 4 stages for it. I am providing a function that deals with server side and logic behind it.
#InjectComponent
private TextField amount;
#Inject
private FieldValidatorSource fieldValidatorSource;
public FieldValidator<?> getAmountValidator()
{
return fieldValidatorSource.createValidators(amount, "required,max=" + getBroj());
}
Now here validator is taken from a logic inside a function getBroj(), which is maximum number of what it takes. And this works like a charm on server side. Now I was thinking that what I don't have( using my logic ) is only Client side, and I can achieve it by updating current Validation class from Tapestry that will handle with this kind of request yet known to that class. And to do it I would need to call a js file with a function calling something like above in the example, but I am not quite sure how to pass value from getNumber() function to the JS function above.
You don't need Jersey or DWR or any other framework at all for invoking a method in Tapestry. You just need to ask your questions properly.
final private static String EVENT_NAME = "whateverEventNameYouWant";
#Inject
private ComponentResources resources;
#Inject
private JavaScriptSupport javaScriptSupport;
/** Method that will provide the value you want to pass to JS. */
#OnEvent(EVENT_NAME)
public JSONObject provideValue() {
JSONObject object = new JSONObject();
object.put("value", /* the value you want to pass to JS */);
// other values you may want to pass
return object;
}
void afterRender() {
// This creates an URL for the event you created. Requesting it will
// invoke any event handler methods for that event name.
Link link = resources.createEventLink(EVENT_NAME);
javaScriptSupport.addScript("var eventUrl = '%s';", link.); // the JavaScript variable name doesn't matter. You can choose any you want
}
Then, in your JavaScript, do an AJAX request using the URL in the eventUrl variable. I'll leave this part for you to figure out from the jQuery documentation. The received data is exactly the JSONObject or JSONArray you'll return in your event handler method.
I think you have some very heavy misconceptions into what types of languages Java and jQuery/Javascript are. First off, with the exception of node.js, jQuery/Javascript are used for client-side operations. Java is used for server-side operations. This means that you will need to pass a value from the server to the client.
Now, what you are asking for looks initially like it is trying to perform validation. This should not be completed only on the client-side. There are ways to get around client validation and it is best to leave information from the client in an "untrusted" state until it is validated on the server.
With all that said, to do what you are trying to do will require the use of some method for the client to communicate with the server. My favorite way to do this for simple operations is through a web service.
Here are steps to do what you require, but note that this is not the only way.
Create a web service with Jersey.
Pass the value to the web service via AJAX with either JSON or XML with a request that contains the value.
Perform your validation on the server-side with the information from the service.
Pass a response from the rest service back to the client-side AJAX call and use it for your JS/jQuery code.
Let me know if you have any questions.

Dynamic instance-level authorization with Jersey (based on id)

Apologies as I am fairly new to Jersey. I've been trying to find a way to have instance-level access authorization using Jersey resources, but the most granularity I'm seeing is Role or static instance-level permissions. I'm a little puzzled because it
To describe better what I mean: suppose an User owns a group of Post resources - presumably this user has the role Author. I don't want every User who is an Author to be able to modify every Post, though. What is the easiest way to control this?
Is this the kind of authorization that's dealt with within the resource class method? Should I be creating a custom Authorization filter? If so, are there any examples of such a thing out there? I'm a little puzzled as it seems like such a common use case.
Thanks!
The reason there isn't much out there in terms of examples is that it's probably down to your own data model as to how you handle this.
Taking a simple example, if each Post has an owner then your resource would probably look something like this:
#PUT
#Path("{id: [A-Fa-f0-9]+}")
#Consumes(MediaType.APPLICATION_JSON)
public T update(#Context HttpServletRequest request, final T item, #PathParam("id") final String id)
{
final Post post = getPostbyId(id);
if (!post.allowedToUpdate(request.getUserPrincipal())
{
throw new UnauthorizedException();
}
// Authorized, carry on
}
There are no end of variations on this theme, but if you're doing resource-level authorization you probably want to do it in something like this way, where you obtain the resource given its ID and then decide if the user is authorized to carry out the requested operation.

View Models in Servlets / MVC

I am building an application with simple Servlets and the MVC pattern. I am not using any framework like Spring.
I have some Model classes like this:
public class BlogPost {
private List<Comment> _comments;
// Things
}
and
public class Comment {
// Code
}
Posts can have zero or more comments associated with them in that collection.
However, I want to attach some additional information to the BlogPost Model before it is passed to the View, namely a value I set in a Cookie once a user makes a comment on a BlogPost. Strictly speaking, this is not a part of the BlogPost Model itself -- it is unrelated, incidental information, however I am not sure if I should make it easy on myself and just add it to the BlogPost class or do something to abstract this out a bit more.
So, should I add a field to the BlogPost class to handle this additional value, OR should I make a "View Model" along the lines of this which gets passed to the JSP view:
public class BlogPostView {
public BlogPostView(BlogPost bp, String message) {
// Constructor stuff, save these to instance variables
}
public BlogPost getBlogPost() { /* ... */ }
public String getMessage() { /* ... */ }
}
If BlogPost and your cookie data are unrelated, it is a bad idea to put the cookie data in your BlogPost class. The BlogPost class should represent what it's called - a blog post. It would be confusing to have other data associated.
Your second option of creating a class specifically to pass to the view is a better idea, though I'm curious to know why you need to pass the blog post and the cookie data as one object to your view? If you're using raw servlets:
request.setAttribute("blogPost",blogPost);
request.setAttribute("cookieData",cookieData);
Using a model class (e.g. Spring MVC ModelMap):
model.addAttribute("blogPost",blogPost);
model.addAttribute("cookieData",cookieData);
Your view will have access to both pieces of data, which you can manipulate using JSTL or other tag libraries.
If there's something I'm missing, can you elaborate more?
Create a HashMap model - and pass it along with the response to view.
model.put("blog", blog)
model.put("message", "some message")

JSF: navigation

I have to warn you: the question may be rather silly, but I can't seem to wrap my head around it right now.
I have two managed beans, let's say A and B:
class A
{
private Date d8; // ...getters & setters
public String search()
{
// search by d8
}
}
class B
{
private Date d9; //...getters & setters
public String insert()
{
// insert a new item for date d9
}
}
and then I have two JSP pages, pageA.jsp (the search page) and pageB.jsp (the input page).
What I would like to do is placing a commandbutton in pageB so to open the search page pageA passing the parameter d9 somehow, or navigating to pageA directly after b.insert(). What I would like to do is showing the search result after the insertion.
Maybe it's just that I can't see the clear, simple solution, but I'd like to know what the best practice might be here, also...
I though of these possible solutions:
including **A** in **B** and linking the command button with **b.a.search**
passing **d9** as a **hiddenInput** and adding a new method **searchFromB** in **A** (ugly!)
collapsing the two beans into one
JSF 1.1/1.2 raw doesn't provide an easy way to do this. Seam/Spring both have ways around this and there are a couple of things you can do. JSF 2 should also have solutions to this once it is released.
Probably the easiest and most expedient would be to collapse the two beans into one and make it session scoped. The worry, of course, is that this bean will not get removed and stay in session until the session times out. Yay Memory leaks!
The other solution would be to pass the date on as a GET parameter. For instance, you action method could call the
FacesContext.getCurrentInstance().getExternalContext().redirect("pageB?d9=" + convertDateToLong(d9));
and then get the parameter on the other side.
You should configure the navigation flow in faces-config.xml. In ideal scenario you would return a "status" message which would decide the flow. Read more at following link:
http://www.horstmann.com/corejsf/faces-config.html
http://publib.boulder.ibm.com/infocenter/rtnlhelp/v6r0m0/index.jsp?topic=/com.businessobjects.integration.eclipse.doc.devtools/developer/JSF_Walkthrough8.html
As far as passing the values from one page to another is concerned you can use backing beans. More about backing beans here:
http://www.netbeans.org/kb/articles/jAstrologer-intro.html
http://www.coderanch.com/t/214065/JSF/java/backing-beans-vs-managed-beans
Hope i have understood and answered correctly to your question
Way to share values between beans
FacesContext facesContext = FacesContext.getCurrentInstance();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = facesContext.getELContext();
ValueExpression valueExp = elFactory.createValueExpression(elContext, expression, Object.class);
return valueExp.getValue(elContext);
In above code "expression" would be something like #{xyzBean.beanProperty}
Since JSF uses singleton instances, you should be able to access the values from other beans. If you find more details on this technique, I am sure you'll get what you are looking for.
Add commandButton action attribute referencing to B'insert method
<h:commandLink action="#{b.insert}" value="insert"/>
In B'insert method,add d9 parameter as request parameter. Then return an arbitrary string from insert method.
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().getRequestMap().put("d9", d9);
Then go to faces context and add navigation from B to A with "from-outcome" as the arbitrary String you returned from insert method. But don't add redirect tag to navigation tags as it will destroy the request coming from B and the parameter you added (d9) will be cleared.
<from-outcome>return string of insert method</from-outcome>
<to-view-id>address of A</to-view-id>
Then you might get the "d9" in A class by fetching it from request map at its constructor or in a place where its more appropriate (getters). You might add it into a session scope or place it to a hidden variable if you want to keep track of it later.
in class A, when page is navigated, A should be initialized as it will be referenced.
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().getRequestMap().get("d9", d9);
Sorry i cant give full code, as i have no ide at here, its internet machine at work. I could not give details therefore.
In my opinion, the simplest way is 3-rd option - have both query and insert methods in same class. And you can do something like that:
public String query () {
//...
}
public String Insert() {
//insert
return Query(); }
If your classes are managed Beans you can load class A from class B and call A.query() in your insert method at the end. Also class A can have
<managed-bean-scope>session</managed-bean-scope>
parameter in faces-config.xml and it wouldn't be instantiated again when loaded.

Categories