To summarize the answer shown here Code assist in (jsp /jstl) view for Spring MVC model objects in Eclipse
is not working for me at all, is there a setting that I need to change ?
I have just downloaded the sample spring-mvc-showcase on github, and it doesn't work out of the box on that project (with either 11.1.3 or EAP 12 version both full enterprise editions), see below (I have no idea where it gets formBean from) :
Here is an example from my own project,the screen shot below (bottom frame) shows my controller adding a string attribute to model and returning correct view name. I would then expect shopString to be offered up as autocomplete option when editing that view, however it is not :
sg is a javascript variable - so great it should be there, but where is "shopString" ?.
Is there a setting I need to change or something else I am missing to get this functionality (using 11.1.3 enterprise edition with all the spring plugins).
It is also failing on spring specific variables :
IS their an open source (one of the spring tutorial projects?) where this definitely works ... or is there a setting I need change in my Intellij install (I have tested with a brand new download of the version 12 EAP) ?
One more screenshot below shows all my spring coifg files set up correctly via autodetection, but the code inspections fails ... this is the spring-mvc-showcase project :
There's a standard way to do this, which is not IntelliJ-specific.
<jsp:useBean id="someModel" scope="request" type="foo.bar.SomeModelClass"/>
The type attribute here does not need to be a concrete class, it can be an interface type as well. Typically you'd put these declarations at the start of your JSP/JSPX files, to provide something like a "declaration of model inputs".
Using JSPs in such a declarative way was recommended in the original book on Spring, in fact (Expert One-on-One J2EE Design and Development.). IntelliJ has been providing full code completion for such pages since at least 7 years.
Note that there are additional relevant convenience features in IntelliJ: if an EL variable reference is marked as undefined, you can press Alt-Enter to select a QuickFix, which will insert a declaration like above. It will even try to figure out the actual type, based on the properties you're accessing.
As I understand Spring, there is no declaration for definitions of variables that you may put into your model. The call model.addAttribute() may add an object to the model, either identified by a parameter or automatically generated by the class name of the object.
So imagine the following case where you have more than one method:
#RequestMapping("foo") public String foo(Model model) {
model.addAttribute("model", new Foo());
return new Random().nextBoolean() ? "page" : "someOtherPage";
}
#RequestMapping("bar") public String bar(Model model) {
model.addAttribute("model", new Bar());
model.addAttribute("model", new Foo());
model.addAttribute("model", new Bar());
return new Random().nextBoolean() ? "page" : "someOtherPage";
}
and the JSP would be something like
<c:out ${model.value} />
Since there is no proper mapping of which controllers may under some circumstances forward to which views, nor what exactly lies within the model, your IDE has no real chance to provide you with proper information.
But to support the IDE in suggesting you some useful information, you can use type hints. Therefore, you have to copy the whole reference of an object, e. g. foo and add a JSP comment like:
<%--#elvariable id="foo" type="com.mycompany.SomeObject"--%>
The warning will vanish and the full IDE support is on your side, allowing you to traverse the fields of foo.
One of the nicest things is that the unused getter warnings will vanish, too. You can directly call the show usages action directly from the JSP or the POJO.
This also works with JSF and particularly within JSF components. Pretty neat feature to have this kind of code completion, showing warnings and errors.
Hope that helps you with your switch to Intellij Idea.
Edit: I also reported this finding to a friend wo wrapped the whole thing into a nice blog entry. Maybe you're interested in reading it: open link
This got fixed in the latest release of intellij 122.694
I faced with similar issue when start writing my own interceptor. Problem was that I start using refference in my view resolver configuration
don't use contruction like this
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" ref="prefix"/>
<property name="suffix" ref="suffix"/>
</bean>-
Related
I'm currently using the session() of play framework in my template :
#if(session().get("email")==null){
<li>Login</li>
}else{
<li>Logout</li>
}
This template is used in all of my views. Some of these views are controlled by a Java controller, and some are with a Scala controller.
When I click on links that lead to Java controllers, I have no problems, the links for login and logout are correctly handled.
When I click on links that lead to Scala controllers, I get a [RuntimeException: There is no HTTP Context available from here.]
From what I read in here about scala controllers, I understood that they didn't return the http context when rendering a page, but I really want to be able to use the session in my template.
I thought about using an argument session() in my view, templates and controllers, but I believe that there will be a conflict between the java session (play.mvc.http.session) and the scala session (play.api.mvc.session) when play will compile the html pages.
Am I stuck? Is there a possibility to force scala controllers to give back the http context ?
The root cause maybe the Java controllers and Scala controllers are handled differently.
I have my project in Java first, and then try to add more Scala controllers. I also came across this problem (BTW, I am using Play 2.3.2).
I tried to fix this by setting my own Http.Context in the TheadLocal variable using my own ActionBuilder.
import play.api.mvc._
import scala.concurrent.Future
import play.mvc.Http.Context
import play.core.j.JavaHelpers
object ContextAction extends ActionBuilder[Request] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
Context.current.set(JavaHelpers.createJavaContext(request))
block(request)
}
}
Then my Scala controller actions simply use this ContextAction instead:
class TestController extends Controller {
def test = ContextAction { implicit request =>
Ok(views.html.index())
}
}
And this way the index template can access all request() / session() / etc.
I may be wrong, but I think that your Scala controllers should look like:
def myaction() = Action { implicit request =>
...
}
instead of:
def myaction() = Action {
...
}
Ie, you have to add the request to the scope of your Action.
And add it also to your view, at the beginning of the file:
#(...)(implicit session:Session)
Okay I found a workaround this problem.
This is not really aesthetic, but it works, and gets rid of the problem entirely.
I created two different main templates : scalamain.scala.html and javamain.scala.html.
The scalamain template is used by all views that are controlled by a Scala controller, and used the usual trick to use the session (implicit arguments, see more here).
The javamain template is used by all view that are controlled by a Java controller. (these view use the session easily).
The two templates are of course, the same once rendered by play.
I end up with some redundancy in my code and it took to separate all the actions so that view are controlled by only one type of controller(scala or java).
I hope this will help others with the same problem. I validate this answer, as it solves the problem, but feel free to answer if you find a more gracious way to solve it.
I'm working on a JSR-303 validation framework for GWT. Some of you may have heard of it even though it is a small project. Here is gwt-validation.
In the old days (v1.0) it used a marker interface for each class and each class had metadata generated separately. This was bad because it was not part of the JSR-303 standard and we moved on to the next idea.
In version 2.0 it scans the classpath at runtime using Reflections. This is great. The downside is that it doesn't seem to be able to work inside of containerized environments or those with special restrictions.
This is probably my fault, look at the following code:
//this little snippet goes through the classpath urls and ommits jars that are on the forbidden list.
//this is intended to remove jars from the classpath that we know are not ones that will contain patterns
Set<URL> classPathUrls = ClasspathHelper.forJavaClassPath();
Set<URL> useableUrls = new HashSet<URL>();
for(URL url : classPathUrls) {
boolean use = true;
for(String jar : this.doNotScanJarsInThisList) {
if(url.toString().contains(jar)) {
use = false;
break;
}
}
if(use) {
useableUrls.add(url);
}
use = false;
}
ConfigurationBuilder builder = new ConfigurationBuilder()
.setUrls(useableUrls)
.setScanners( new TypeAnnotationsScanner(),
new FieldAnnotationsScanner(),
new MethodAnnotationsScanner(),
new SubTypesScanner()
)
.useParallelExecutor()
;
this.reflections = new Reflections(builder);
I'm using the filter to remove jars that I know can't have annotations in them that I'm interested in. As I mention this gives a huge speed boost (especially on large classpaths) but the ClasspathHelper.forJavaClassPath() that I'm basing this on probably isn't the best way to go in container environments. (e.g. Tomcat, JBoss)
Is there a better way or at least a way that will work with a container environment and still let my users filter out classes they don't want?
I've looked, some, into how the Hibernate Validation project (the reference implementation for JSR-303) and they appear to at least be using (at least in part) the Annotations Processing in Java 6. This can't be all of the story because that didn't show up until JDK6 and Hibernate Validator is JDK5 compatible. (See: hibernate documentation)
So, as always, there's more to the story.
I've read these threads, for reference:
About Scannotation which has been pretty much replaced by Reflections.
This one but it uses File and I'm not sure what the implications are of that in things like GAE (Google App Engine) or Tomcat.
Another that goes over a lot of the things I've talked about already.
These threads have only helped so much.
I've also read about the annotation processing framework and I must be missing something. It appears to do what I want but then again it appears to only work at compile time which I know isn't what is done by Hibernate Validator. (Can anyone explain how it does scanning? It works on GAE which means it can't use any of the IO packages.)
Further, would this code work better than what I have above?
Set<URL> classPathUrls = ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader());
Could that correctly get the classloader inside of a Tomcat or JBoss container? It seems scan a smaller set of classes and still finish okay.
So, in any case, can anyone help me get pointed in the right direction? Or am I just stuck with what I've got?
You could take a look at Spring's annotation support.
Spring can scan annotations in files (using asm IIRC), and works in and out of a container.
It may not be easy because it goes through Spring's Resource abstraction, but it should be doable to reuse (or extract) the relevant code.
I'm using Play Framework and setting a cache value as such:
String sessionId = Scope.Session.current().getId();
Cache.set(sessionId + "_user", "Doser");
and I want to ouput the value in my main.html without adding the value to every single controller in my application.
How do I achieve this in Play?
The other option you have for this, is to create an action in your controller that uses the #Before annotation, and then add the value using renderArgs().
I answered a previous question which I think is very similar to your requirements.
Does Play Framework support "snippets"?
You should also be aware that all session variables are available within your template, by default. You can see all the implicit objects that are available in the template in the Template Documentation here -- http://www.playframework.org/documentation/1.2.2/templates#implicits.
I need to stop answering my own questions.
I've created a tag as described in the link below, and it works perfectly:
http://www.playframework.org/documentation/1.2.2/templates#tags
I'm trying out MyFaces CODI with it's wonderful features. A very useful thing is the typesafe navigation. I can specify the outcome of an action method in my controller bean like this:
public Class<? extends ViewConfig> goBack() {
return Pages.ListView.class;
}
That is really cool because the excessive refactoring ability of every development IDE.
But when I want to use this feature I have a problem with passing viewParameter to the next view. I have to use a commandbutton for calling this action method like this:
<h:commandButton id="backButton" value="#{msgs.Button_Back}"
action="#{viewBean.goBack()}" />
If I use this commandbutton I cannot pass parameters. A "normal" button or a link would do it:
<h:button id="backButton" value="#{msgs.Button_Back}" outcome="siteBefore.xhtml">
<f:param name="itemId" value="5" />
</h:button>
The disadvantage is that the "normal" button don't use the action method and therefore I cannot participate on the advantage of typesafe navigation of CODI.
So is there any possibility to combine these two features? (passing viewparams and use typesafe navigation)
Thanks in advance!
They implemented what you are looking for. See https://issues.apache.org/jira/browse/EXTCDI-216
#StevenR
CODI does not support inclusion of viewParams when using typesafe navigation, however if you follow their issue tracking system it seems like a prospective feature:
https://issues.apache.org/jira/browse/EXTCDI-171
From the issue's history you can tell they just updated the status recently (~4 weeks ago) and it might be included soon. Maybe one of the comitters is following this post and can update us with a rough time line for this new feature?
Moreover the feature of type safe navigation has been discussed in the JSF spec:
http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-977
As a workaround I'd suggest do follow the hint in the CODI wiki (see part of the URL below) and use Pages.ListView.class.getName() where you could concatenate additional viewParams within your backing bean's action method. This way your navigation is type safe and you leverage your IDE's refactoring capabilities. Only the params would not be type safe this way...
I would suggest you use the <f:attribute/> tag, so you don't have to walk trough like this
String viewParam = "";
for (UIComponent comp : event.getComponent().getChildren()) {
if (comp instanceof UIParameter ) {
UIParameter myParameter = (UIParameter) comp;
if (myParameter.getName().equals("myParameterName")) {
viewParam = myParameter.getValue());
}
}
}
// add your viewParam to the navigation string here
The downside here is the hard coded name of the parameter somewhere deep inside your code. So it might be worthwhile to refactor once CODI comes with the new feature
cwiki.apache.org/EXTCDI/jsf-usage.html#JSFUsage-TypesafeNavigation
What is the best way to enable my webapplication to use JSF files stored in the database?
I'd like to be able to dynamically (during runtime) create new JSF pages which will be made available without having to redeploy the application.
So in other words: I would like to store the bigger part of my JSF pages in the database and would like JSF to use the database as a datasource for getting JSF files.
I've thought long about a solution and found some possible ways. However, I haven't been able to implement either of them.
Whenever a new page has to be added/removed: manipulate the files in the classpath (e.g. remove or add a file to the .war file)
Extending the classpath of the webapplication so it will be able to get files from an at runtime defined location (i.e. /tmp or directly using a database connection)
Provide JSF with a way to find resources another way ( this doesn't seem possible? )
My environment:
Java SE 6
Jetty as servlet container
Mojarra as jsf implementation
Now, my question:
Is it possible for someone to let JSF find pages at a location other than the default classpath, preferably the database?
Any response is greatly appreciated!
1: Whenever a new page has to be added/removed: manipulate the files in the classpath (e.g. remove or add a file to the .war file)
This is definitely possible if the WAR is expanded. I am not sure about Jetty, but it works for me with Mojarra 2.x on Tomcat 7 and Glassfish 3. Just writing the file to the expanded WAR folder the usual Java IO way suffices.
File file = new File(servletContext.getRealPath("/foo.xhtml"));
if (!file.exists()) {
OutputStream output = new FileOutputStream(file);
try {
output.write(bytes); // Can be bytes from DB.
} finally {
output.close();
}
}
This needs to be executed before the FacesServlet kicks in. A Filter is a perfect place. See also this related answer:
How to create dynamic JSF form fields
2: Extending the classpath of the webapplication so it will be able to get files from an at runtime defined location (i.e. /tmp or directly using a database connection)
You can package Facelets files in a JAR file and put it in the classpath and provide a Facelets ResourceResolver which serves the files from the JAR on when no match is found in WAR. You can find complete code examples in the following answers:
how to share a jsf error page between multiple wars
How to create a modular JSF 2.0 application?
3: Provide JSF with a way to find resources another way ( this doesn't seem possible? )
You've plenty of play room in the custom ResourceResolver.
Nice question. BalusC's answer is - as always - complete and right.
However, if your point is to create an application where gui is built dynamically, there is a way that might serve you better (depending on what you really want to achieve).
JSF views are similar to Swing forms - they are just a bunch of JavaBeans(tm) glued together. The big difference is that when a field is bound to an EL expression, you do not use standard accessors, but rather a special method (setValueExpression).
This means you can build your GUI from objects (the concrete classes can be found in javax.faces.component.html) in a pure programmatic way and then use binding attribute to show it on page. Something like:
<h:form>
<h:panelGrid binding="#{formBuilder.component}"/>
</h:form>
And then in the managed formBuilder bean:
#PostConstruct
public void init() {
HtmlInputText hit = new HtmlInputText();
// properties are easy:
hol.setStyle("border: 2px solid red");
// binding is a bit harder:
hit.setValueExpression("value", expression("#{test.counter}", String.class));
HtmlOutcomeTargetLink hol = new HtmlOutcomeTargetLink();
hol.setValue("link leading to another view");
hol.setOutcome("whatever");
component = new UIPanel();
component.getChildren().add(hit);
component.getChildren().add(hol);
}
private ValueExpression expression(String s, Class c){
return FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(
FacesContext.getCurrentInstance().getELContext(),
s, c
);
}
The example above builds a static panel, but it would be possible to:
create an object model of your GUI
map the model to database (with hibernate or another orm)
write some kind of adapter or bridge to build JSF objects from your object model
make a managed bean that receives the form id, grabs the relevant form from database, builds a JSF panel out of it and presents it as a property, ready to be bound.
This way you could have just one static xhtml with a single tag and use it to present any number of dynamic forms.
As I said, this method could be better than just storing files, but not necessarily. If you just want to save yourself the hassle of redeployment, this is a huge overkill (then again, you do NOT need to redeploy JSF applications just to change forms). If on the other hand your goal is to have something like user-defined and edited forms, having a good object model and storing it in a proper way could be a good idea.
The bumps ahead would be:
navigation (perhaps a custom navigation handler would suffice?)
problems with generating plain html
possibly some problems with lifecycle of view scoped forms