Struts2 - How to use the Struts2 Annotations? - struts2

I'm trying to implement the Struts 2 Annotations in my project, but I don't know how.
I added the convention-plugin v 2.1.8.1 to my pom
I modified the web.xml
...
<init-param>
<param-name>actionPackages</param-name>
<param-value>org.apache.struts.helloworld.action</param-value>
</init-param>
...
My Action
package org.apache.struts.helloworld.action;
import org.apache.struts.helloworld.model.MessageStore;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
#Results({
#Result(name="success", location="HelloWorld.jsp")
})
public class HelloWorld extends ActionSupport {
public String execute() throws Exception {
messageStore = new MessageStore() ; return SUCCESS;
}
The jsp page from where I'm trying to use my action.
<body>
<h1>Welcome To Struts 2!</h1>
<p>Hello World</p>
</body>
When I press the link associated to the action helloWorld, but it's sends me to the exactly the same page. So, from index.jsp, it's sends to index.jsp.
The way it should behave: it should send me to HelloWorld.jsp.
I uploaded the project (a very simple HelloWorld app) to FileFront, maybe someone sees where is the problem. http://www.filefront.com/16364385/Hello_World.zip

Convention uses a different convention to convert CamelCaseAction names to url's and jsp's names. If you are using Convention's defaults, I believe you should have used the following names:
ActionClass: HelloWorldAction.java
JSP: hello-world.jsp
Action: hello-world
Also, notice that by default convention will look for your JSPs on WEB-INF/content . The documentation is a bit shallow, you have to understand by the examples, but you can consult all default values there: http://struts.apache.org/2.x/docs/convention-plugin.html

I havent used Struts2 with annotations (which Struts2 version? are you following some tutorial or doc?) . But should not that location attribute (in the Result annotation) be instead value ?

What do the logs say? Have you tried using /HelloWorld.jsp for "success". I think that struts framework does not find the resource and is loading the same page.
When you use /HelloWorld.jsp, hopefully you will see the result page.

Related

Spring Boot 1.3 WebSocket JSON converter Produces Invalid JSON

After upgrading to Spring Boot 1.3 (via Grails 3.1), the JSON output is rendered incorrectly. I believe it is because of the new auto-configured WebSocket JSON converter.
For example, with previous versions of Spring Boot (via Grails 3.0), using the following code:
#MessageMapping("/chat")
#SendTo("/sub/chat")
protected String chatMessage() {
def builder = new groovy.json.JsonBuilder()
builder {
type("message")
text("foobar")
}
builder.toString()
}
This would produce:
{"type": "message", "text": "foobar"}
With Spring Boot 1.3 (via Grails 3.1), that web socket produces the following:
"{\"type\":\"message\",\"text\":\"foobar\"}"
This is not valid JSON. How can I get rid of this new behavior and have it render the JSON as it was before? Please let me know if you have any suggestions.
I tried overriding the new configureMessageConverters method, but it did not have any effect.
looks like you are right. referenced commit shows questionable autoconfiguration imho.
especially b/c in the past, the converter ordering was intentionally changed to that StringMessageConverter takes precedence before MappingJackson2MessageConverter: https://github.com/spring-projects/spring-framework/commit/670c216d3838807fef46cd28cc82165f9abaeb45
for now, you can either disable that autoconfiguration:
#EnableAutoConfiguration(exclude = [WebSocketMessagingAutoConfiguration])
class Application extends GrailsAutoConfiguration { ... }
or, you add yet another StringMessageConverter to the top of the configured converters (maybe because you do want the boot autoconfiguration behavior because it is using the jackson ObjectMapper bean instead of creating a new one):
#Configuration
#EnableWebSocketMessageBroker
class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
boolean configureMessageConverters(List<MessageConverter> messageConverters) {
messageConverters.add 0, new StringMessageConverter()
return true
}
...
}
hope that helps.
I don't know how to do it in Grails but in Java you have to now pass the object instead of an object in the String class. I believe the old behavior was actually incorrect as it was returning a string as an object so there was no way to return a String that had JSON inside it as a String. So create an object with the structure you want and return it and you should be fine. I went through the same issue when upgrading from 1.2.X to 1.3.X. I am not exactly sure what change caused this but I think in the long run it is the correct thing to do.

Angular 2 Dependency Injection

I have read several articles on dependency injection and cannot seem to get it working the way I think it should. From what I have read, you can use the #Injectable decorator on a class and then the metadata is created for the DI like so:
import {Hero} from './hero.model';
import {Injectable} from 'angular2/angular2'
#Injectable()
export class HeroService {
constructor() {
console.log('Hero Service Created');
}
}
Then in your component, you can use it in your constructor (with the proper import) like this:
constructor(heroService: HeroService) {
console.log('App Component Created');
}
However, I get the following error: Cannot resolve all parameters for AppComponent(?). Make sure they all have valid type or annotations.
I am able to get it working properly if I remove the #Injectable syntax from the service and instead have my constructor like this:
constructor(#Inject(HeroService) heroService: HeroService) {
console.log('App Component Created');
}
With everything that I've read, these should do the same thing, but they aren't. Any ideas as to why? I am using Typescript 1.6.2 with VS 2013, angular 2 v2.0.0-alpha.46, and systemjs v0.19.5.
Make sure that you've specified "emitDecoratorMetadata" option in your TypeScript configuration.

How to connect interface<T> and implementation<T> in autofac .config file

I have following class
namespace MyApplication.Services
{
public class TagEqualityComparer : IEqualityComparer<Tag>{/*code goes here*/}
}
Now what I would like to register it in autofac using .config file based configuration:
<autofac>
<components>
<component type="MyApplication.Services.TagEqualityComparer, MyApplication.Services"
service="System.Collections.Generic.IEqualityComparer, mscorlib" />
</components>
</autofac>
I have already spent whole sunday searching for solution I failed to find any. Other registrations, non templates, works perfectly but this one refuses.
Any idea how to solve it?
You need to define the rest of the generic type to specify the parameter type. Something like this:
<component type="MyApplication.Services.TagEqualityComparer, MyApplication.Services"
service="System.Collections.Generic.IEqualityComparer`1[[MyApplication.Services.Tag, MyApplication.Services]], mscorlib" />

How do I add a page to Jenkins?

I am looking to write a jenkins plugin that lets me add a new link that links to a new page of my creating. I have determined how to create the new link by extending RootAction and I can get it to link to a static resource in the webapp directory. My problem is many fold though. I think I need to use a jelly page because of the nature of action I want to do on this new page of mine and even if I could do what I wanted to with static web content the link pops me out of the jenkins interface to a page only containing my static web content.
What I need to know is, how do you go about creating a brand new page? I have been scowering the JavaDoc looking for an interface and the internet for more documentation on how to write plugins. But the internet seems to be sadly lacking on information pertaining to Jenkins plugin development.
What I want to do is be able to click my new link and have it take me to my new page, still with all the Jenkins navigation and such, and on this new page I am going to have a form for performing some actions on files.
Any help or pointers to documentation I have not found would be greatly appreciated.
As you found, the first step is to extend a RootAction or Action, depending on where you want the page to be located: globally or per-project, respectively.
A simple RootAction:
package my.package;
#Extension
public class MyNewPage implements hudson.model.RootAction
{
#Override
public String getDisplayName()
{
return "My Custom Page";
}
#Override
public String getIconFileName()
{
return (Jenkins.RESOURCE_PATH + "/images/48x48/terminal.png").replaceFirst("^/", "");
}
#Override
public String getUrlName()
{
return "my-url"; // the url path
}
}
Next, add an associated jelly file located at src/main/resources/my/package/MyNewPage/index.jelly
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define"
xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<l:layout norefresh="true">
<l:header title="My New Page" />
<l:main-panel>
<h1>Put content here</h1>
</l:main-panel>
</l:layout>
</j:jelly>
See the jenkins jelly tag reference for more tags. Note that the l:layout tag is completely optional, you don't have to use jenkins tags at all and can instead dump static HTML content in the jelly
Those two files will then be used to render requests for http://localhost:8080/jenkins/my-url
Alternatively, for completely dynamic content, use the stapler library built into jenkins to render arbitrary urls. Here is a silly little example that prints back the url:
public void doDynamic(StaplerRequest req, StaplerResponse resp) throws IOException
{
resp.setStatus(418);
resp.getOutputStream().print("I'm a teapot! You requested this path: " + req.getRestOfPath());
}
Just add that method, or any of the stapler methods, to the MyNewPage (or any extension that supports it). It will respond to all urls under http://localhost:8080/jenkins/my-url/*
Some other good references I've found:
How to extend Jenkins job page with new links and icons
The build-failure-analyzer plugin source, notably CauseManagement.java

Date conversion exception inside JSF composite component

When I access a JPA managed date value from JSF, it comes back with an javax.faces.component.UdateModelException saying
'Cannot convert 01.01.10 00:00 of type class java.util.Date to class org.apache.openjpa.util.java$util$Date$proxy
Using a JPA-managed date value (which means it is proxied) works fine when it is used directly from the EL likes this:
'<h:outputLabel value="MyDateValue" for="input"/>
'<h:inputText id="inputDate" value="#{bean.myDate}"/>
However, it causes trouble when trying to use it with composite components
and gives back the following converter exception and thus can't update the model...
The (simplified) JSF composite component inputDate.xhtml
<head>
<title>A date input field</title>
</head>
<composite:interface>
<composite:attribute name="dateValue"/>
</composite:interface>
<composite:implementation>
<h:outputLabel value="MyDateValue" for="input"/>
<h:inputText id="input" value="#{cc.attrs.dateValue}"/>
</composite:implementation>
Assumption:
It seems the proxy replacement in OpenJPA is handled differently when the value is being accessed from inside a composite. My guess is the EL-resolver handles calls to object values differently when it is passed to composites. Passing it to composites means it is first accessed within the composite, which is too late and the required replacement of the proxy is not accomplished (thus the converter exception)
So I tried to change the Expression Language for MyFaces, but it didn't work in Websphere, even though I changed the class loading to parent last and provided el-impl and el-api from glassfish in the lib folder and inserted the necessary context-param for MyFaces
How do you guys use JPA-managed dates (or other proxied entities) in composite components???
If you are using the sun EL implementation you might use the following ELResolver which works around this issue:
public class BugfixELResolver extends ELResolver {
//...
#Override
public Class<?> getType(ELContext anElContext, Object aBase, Object aProperty) {
if (aBase.getClass().getCanonicalName().equals("com.sun.faces.el.CompositeComponentAttributesELResolver.ExpressionEvalMap")){
Object tempProperty=((Map)aBase).get(aProperty);
if (tempProperty!=null&&tempProperty.getClass().getCanonicalName().equals("org.apache.openjpa.util.java.util.Date.proxy")) {
anElContext.setPropertyResolved(true);
return java.util.Date.class;
}
}
return null;
}
}
Add it to the faces-config this way:
<el-resolver>
xxx.BugfixELResolver
</el-resolver>
This workaround can also be used in environments where you can not change the EL implementation (like websphere etc.).
Here is the workaround. The problem seems to be WebSpheres' ExpressionLanguage Implementation or rather the order resolvers are executed. Registering the JBoss EL implementation works and resolves the date proxies before calling the composite component. I also tried the Glassfish EL, but it didn't work either...
Registering a alternative EL is quite strange: The setting in web.xml for MyFaces is
<context-param>
<param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
Additionally under WebContent/META-INF/services/ a file named javax.el.expressionFactory is needed with this single line org.jboss.el.ExpressionFactoryImpl. The class comes from jboss-el-2.0.2.CR1.jar
(sorry, couldn't find the link to a maven repo)
I will keep you updated once I find a better solution...

Resources