JSON response is not working after upgrade to struts2.5.8 - json

before I upgrade the struts from 2.3.x to 2.5.8, the JSON can return data to me,but now return JSON value is empty in struts2.5.8, whatever what type i have put. here is my code:
TestController.java
public class TestingController implements ModelDriven<Object> {
private ArrayList<Test> testList = null;
public ArrayList<Test> getTestList() { return testList;}
public String tableData() {
jsonMap = new HashMap<String, Object>();
testList = getTestListBySomething();
if(testList!=null && testList.size()>0){
jsonMap.put("test", testList);
}
}
also my struts.xml:
<package name="default" namespace="" extends="rest-default,struts-default" strict-method-invocation="false">
<result-types>
<result-type name="json" class="org.apache.struts2.json.JSONResult"/>
</result-types>
</package>
I have checked that the testList have data and size, but in the response on ajax , it show:
{"test":""}
What wrong of my coding?

In your strust xml add below parameter.
<param name="root">#action</param>
EX :
<result-types>
<result-type name="json" class="org.apache.struts2.json.JSONResult">
<param name="noCache">true</param>
<param name="excludeNullProperties">true</param>
<param name="root">#action</param>
<param name="ignoreHierarchy">false</param>
<param name="excludeProperties">errors</param>
</result-type>
</result-types>

Related

How to upload video in file system and mysql database using struts2 and hibernate [duplicate]

Hi am struggling to play video file in jsp file from system location using struts2. But if i place video file(Sample.mp4) under web-content in eclipse and just use the video tag in jsp with fileName like below it will get play.
<source src="Sample.mp4" type="video/mp4"/>
How do i play the video which is there in system location example d:/video/sample.mp4 ?
Action class
public class DownloadAction extends ActionSupport {
private InputStream fileInputStream;
private String fileToDownload = "D://video//Sample.mp4";
private String fileName;
private String contentType = "video/mp4";
public String execute() throws Exception {
fileInputStream = new FileInputStream(fileToDownload);
return SUCCESS;
}
public InputStream getFileInputStream() {
return fileInputStream;
}
public void setFileInputStream(InputStream fileInputStream) {
this.fileInputStream = fileInputStream;
}
public String getFileToDownload() {
return fileToDownload;
}
public void setFileToDownload(String fileToDownload) {
this.fileToDownload = fileToDownload;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
}
struts.xml
<action name="download" class="com.sample.actions.DownloadAction">
<result name="success" type="stream">
<param name="contentType">${contentType}</param>
<param name="inputName">fileInputStream</param>
<param name="contentDisposition">attachment;filename="${fileName}"</param>
<param name="bufferSize">1024</param>
</result>
</action>
in Jsp
<body>
<%
String url = request.getScheme() + "://" + request.getServerName()
+ ":" + request.getServerPort() + request.getContextPath();
url = url + "//download";
%>
<video width="320" height="240" controls>
<source src=<%=url%>>
</video>
</body>
Here is an jsp page to for video display
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<video width="400" controls>
<source src="<s:url value="videoStream" />" type="video/mp4"/>
<source src="mov_bbb.ogg" type="video/ogg">
Your browser does not support HTML5 video.
</video>
</body>
</html>
Map the s:url request to struts action action in struts.xml
<struts>
<package name="user" namespace="/" extends="struts-default">
<action name="videoStream" class="com.pradeep.videostream.VideoStreamingAction">
<result name="success" type="stream">
<param name="contentType">${yourContentType}</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">attachment;filename="${yourFileName}"</param>
<param name="bufferSize">1024</param>
</result>
</action>
</package>
</struts>
in the action class am fething video file from file system and doing streaming
public class VideoStreamingAction extends ActionSupport {
private InputStream inputStream;
private String yourContentType;
// getters and setters
public String execute() throws Exception {
yourContentType = "video/mp4";
File file =new File("D://svn videos//Create Java Spring Web MVC Project With Maven [EDITED].mp4");
setInputStream(new ByteArrayInputStream(FileUtils.readFileToByteArray(file)));
return SUCCESS;
}
}

Receiving List object from javascript to Java Struts2 using json [duplicate]

I am trying to understand how to use JSON and in the process I'm trying to get a JSON response from Struts2 action and display an alert for the response. For this I'm using Ajax POST in JavaScript as follows:
function checkButtonClick(id){
var btnSave = 'saveAttendees';
var atNameList = $('#attName'+id).val();
var ptNameList = $('#postName'+id).val();
var aId = $('#at_id'+id).val();
alert("here");
var arr = {buttonName: btnSave,
attendeesNameList: atNameList,
attendeesPostList: ptNameList,
hidden_At_id: aId
};
$.ajax({
data: arr,
type: 'POST',
dataType: 'json',
url:"meeting_record_form",
success:function(result){
alert(result.myMsg);
},
error:function(result){
alert("error");
}
});
}
My Action class contains a String field that I'm trying to display in alert as JSON response. But I'm finding problem doing this. What am I missing or doing wrong?
My action class is as follows:
private String myMsg;
public String getMyMsg() {
return myMsg;
}
public void setMyMsg(String myMsg) {
this.myMsg = myMsg;
}
private String updateAttendeesRecord() {
meetingRecordService.updateAttendeesRecord(attendeesListMethod(), meeting_record);
setMyMsg("Update Successful!");
return SUCCESS;
}
struts.xml file:
<package name="default" extends="struts-default, json-default">
<result-types>
<result-type name="json" class="org.apache.struts2.json.JSONResult" />
</result-types>
<interceptors>
<interceptor name="json" class="org.apache.struts2.json.JSONInterceptor" />
</interceptors>
<action name="meeting_record_form" class="com.task.action.MeetingRecordAction" method="updateAttendeesRecord">
<result name="success" type="json" />
</action>
</package>
My pom.xml:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.3.15</version>
</dependency>
In the action configuration you should not override the default configuration from json-default package just extend it and all. Also json-default extend a struts-default, so multiple inheritance is not required.
<package name="default" extends="json-default">
<action name="meeting_record_form" class="com.task.action.MeetingRecordAction" method="updateAttendeesRecord">
<result name="success" type="json" />
</action>
</package>
The problem in your Action class MeetingRecordAction, method updateAttendeesRecord is private, it should be public
public String updateAttendeesRecord() {
meetingRecordService.updateAttendeesRecord(attendeesListMethod(), meeting_record);
setMyMsg("Update Successful!");
return SUCCESS;
}
I've solved my problem by adding myMsg on the json result. Thanks for all the help

#restcontroller and #responsebody not working in Spring MVC + Thymeleaf

In my spring MVC 4.1.5 application configured to use Thymeleaf 2.1.4 (before it was using JSP and it worked fine), i am unable to return a JSON response.
It always returns a full HTML page weather my request mapping is in a #RestController or if its annotated with #responsebody
Here are the controllers
in an #controller class, i have below mapping
#RequestMapping(value = { "/", "/land", "/login" }, method = RequestMethod.GET)
public String getLogin(Model model, HttpSession session) {
session.setAttribute("login", "none");
System.out.println(programId);
model.addAttribute("signUpForm", new SignUpForm());
return "login";
}
and in #RestController class, below is the post method for same URL
#RequestMapping(value = {"/login" }, method = RequestMethod.POST )
public #ResponseBody HashMap<String, Object> login2(#RequestBody SignUpForm signUpForm, HttpServletRequest request,
HttpServletResponse httpServletResponse, HashMap<String, Object> mo, HttpSession session ) {
User user = userDao.findUserByName(signUpForm.getUserName());
if (user != null && encoder.matches(signUpForm.getPassword(), user.getPassword())&& user.getProgram_id()==3) {/* && user.getProgram_id()==3*/
session.setMaxInactiveInterval(1200);
System.out.println(session.getMaxInactiveInterval()+":"+session.getLastAccessedTime()+":"+session.getCreationTime()+":"+session.getServletContext().getContextPath());
session.setAttribute("login", "success");
mo.put("redirect", "/home");
String ipAddress = request.getHeader("X-FORWARDED-FOR");
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}
session.setAttribute("urip", ipAddress);
return mo;
} else {
mo.put("error", "Login failed. Please check your credentials");
return mo;
}
}
Below is my xml configuration
<context:component-scan base-package="com.company.cardholder" />
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="serializationInclusion">
<value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<mvc:default-servlet-handler />
<mvc:interceptors>
<bean class="com.company.cardholder.session.interceptors.URLInterceptor" />
</mvc:interceptors>
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/thymeleaf/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<!-- Template cache is set to false (default is true). -->
<property name="cacheable" value="false" />
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
</bean>
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
</bean>
Here is my JSON call
$.ajax({
type: 'POST',
url: $form.attr('action'),
data: JSON.stringify({
userName: $form.find('#userName').val(),
password: $form.find('#password').val(),
}),
contentType: "application/json",
/*dataType: 'json',*/
complete: function(data) {
console.log(data);
if (data.redirect) {
// data.redirect contains the string URL to redirect to
window.location.href = data.redirect;
}else if(data.error){
$messageError.text(data.error);
$messageError.removeClass('hidden');
$messageSuccess.addClass('hidden');
}
}
});
Ok. Here is what i figured out to make it work but i still am not sure of the reason.
public #ResponseBody HashMap<String, Object> login2(#RequestBody SignUpForm signUpForm, HttpServletRequest request,
HttpServletResponse httpServletResponse, HashMap<String, Object> mo, HttpSession session ){
////
}
In the above method signature, i was "injecting" a hashmap. And spring framework default or some unknown config decided to inject a "Binding Result aware Hashmap." I am not sure what difference it would have made. But to fix it, i had to do a
HashMap<String, Object> mo=new HashMap<String, Object>;
inside the method body and remove the injected hashmap.
If anyone is able to understand this behaviour, please explain it. I feel i missed something basic in my awareness of spring framework.

Struts2 JasonInterceptor Content type must be 'application/json' or 'application/json-rpc'

Can anyone enlighten me in what scenarios I would get the following error in the log?
Struts2 JasonInterceptor Content type must be 'application/json' or 'application/json-> rpc'. Ignoring request with content type application/x-www-form-urlencoded
I also notice that in the IE it shows a debug message as follows(not sure if these 2 messages are related):
DEBUG: please consider using a mimetype of text/json-comment-filtered to avoid potential >security issues with JSON endpoints
DEBUG: [SyntaxError: Syntax error]
I specifically changed my s:form enctype attribute as follows and still couldnt get rid of this message:
<s:form id="dealerForm" action="AjaxAutocompleterAction"
enctype="text/json-comment-filtered">
</s:form>
and this as well (didnt work again)
<s:form id="dealerForm" action="AjaxAutocompleterAction"
enctype="application/json">
</s:form>
any ideas?
*************Update - 1*****************
More information about the code I am working with follows:
My AjaxAutocompleter.jsp containing the linked autocompleters:
<s:form id="dealerForm" action="AjaxAutocompleterAction"
enctype="text/json-comment-filtered">
<sx:autocompleter id="dealer" name="dealer" searchType="substring"
label="Dealer" list="dealerList" listKey="name" listValue="name"
showDownArrow="false" valueNotifyTopics="/notifyBranch"
errorNotifyTopics="/error" beforeNotifyTopics="/before"
forceValidOption="true" loadMinimumCount="3" />
<sx:autocompleter id="branch" name="branch" searchType="substring"
label="Branch" list="branchList" showDownArrow="false"
listenTopics="/notifyBranch" formId="dealerForm"
formFilter="function(paramName){return true;}"
valueNotifyTopics="/notifyRep" beforeNotifyTopics="/before"
afterNotifyTopics="/after" forceValidOption="true"
loadMinimumCount="0" loadMinimumCount="3" />
<sx:autocompleter id="representative" name="representative"
searchType="substring" label="Rep" list="repList"
showDownArrow="false" forceValidOption="true" loadMinimumCount="0"
formId="dealerForm" formFilter="function(paramName){return true;}"
listenTopics="/notifyRep" beforeNotifyTopics="/before"
afterNotifyTopics="/after" loadMinimumCount="3" />
<textarea name="mytextarea" id="mytextarea" rows="25" cols="190"></textarea>
</s:form>
struts.xml
<package name="ajax" extends="json-default">
<action name="AjaxAutocompleterAction" class="com.frk.gid.action.AjaxAutocompleterAction">
<interceptor-ref name="json"/>
<interceptor-ref name="params">
<param name="ordered">true</param>
</interceptor-ref>
<interceptor-ref name="prepare" />
<result type="json" />
<result name="success">/AjaxAutocompleter.jsp</result>
</action>
</package>
my model classes
public class Representative {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return name;
}
}
public class Branch {
private String name;
private List<Representative> representatives;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setRepresentatives(List<Representative> representatives) {
this.representatives = representatives;
}
public List<Representative> getRepresentatives() {
return representatives;
}
#Override
public String toString() {
return name;
}
}
public class Dealer {
private String name;
private List<Branch> branches;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setBranches(List<Branch> branches) {
this.branches = branches;
}
public List<Branch> getBranches() {
return branches;
}
#Override
public String toString() {
return name;
}
}
my prepare method
#Override
public void prepare() throws Exception {
logger.info("Prepare Started ...");
ServletActionContext.getResponse().setContentType(
"text/json-comment-filtered");
dealerList = new ArrayList<Dealer>();
int branchCounter = 0;
int repCounter = 0;
for (int i = 0; i < 5; i++) {
Dealer d = new Dealer();
List<Branch> branches = new ArrayList<Branch>();
for (int j = 0; j < 3; j++) {
Branch b = new Branch();
b.setName("BRANCH-" + branchCounter++);
List<Representative> representatives = new ArrayList<Representative>();
for (int k = 0; k < 2; k++) {
Representative rep = new Representative();
rep.setName("REP-" + repCounter++);
representatives.add(rep);
}
b.setRepresentatives(representatives);
branches.add(b);
}
d.setName("DEALER-" + i);
d.setBranches(branches);
dealerList.add(d);
if (this.dealer == null && i == 0) {
setDealer(d.getName());
}
// Populate DBR Hierarchy for the selected dealer.
if (this.dealer != null && this.dealer.equals(d.getName())) {
branchList = new ArrayList<String>();
int bCount = 0;
for (Branch b : branches) {
branchList.add(b.getName());
if (this.branch == null && bCount++ == 0) {
setBranch(b.getName());
}
if (this.branch != null && this.branch.equals(b.getName())) {
repList = new ArrayList<String>();
for (Representative r : b.getRepresentatives()) {
repList.add(r.getName());
}
if ((this.representative == null && repList.size() > 0)
|| (this.representative != null && !repList
.contains(this.representative))) {
setRepresentative(repList.get(0));
}
}
}
}
}
Ok .. finally after much struggle, I did manage to solve this myself . the clue lies in my autocompleter definition where I had to use dataFieldName always whenever I used the href.
Also, I couldnt get to load the first level hierarchy (in my case Dealer) to work with the href -i had to explicitly call the action and use the local variable.
I am posting my modified code so it could come in handy for other learners :-) Have fun !!!
My Updated jsp
<s:url id="dbrList" action="AjaxAutocompleterAction"
encode="text/json-comment-filtered"/>
<s:action name="AjaxAutocompleterAction" id="myDBRAction" />
<sx:autocompleter id="dealerList" name="dealer" searchType="substring"
label="Dealer" showDownArrow="false" valueNotifyTopics="/notifyBranch"
errorNotifyTopics="/error" beforeNotifyTopics="/before"
forceValidOption="true" loadMinimumCount="1"
list="%{#myDBRAction.dealerList}" />
<sx:autocompleter id="branchList" name="branch" searchType="substring"
label="Branch" list="branchList" showDownArrow="false"
listenTopics="/notifyBranch" formId="dealerForm"
formFilter="function(paramName){return true;}"
valueNotifyTopics="/notifyRep" beforeNotifyTopics="/before"
afterNotifyTopics="/after" errorNotifyTopics="/error"
forceValidOption="true" loadMinimumCount="1" href="%{dbrList}"
list="branchList" dataFieldName="branchList" />
<sx:autocompleter id="repList" name="representative"
searchType="substring" label="Rep" list="repList"
showDownArrow="false" forceValidOption="true" formId="dealerForm"
formFilter="function(paramName){return true;}"
listenTopics="/notifyRep" beforeNotifyTopics="/before"
errorNotifyTopics="/error" afterNotifyTopics="/after"
loadMinimumCount="1" href="%{dbrList}" dataFieldName="repList" />
My updated struts.xml
<package name="ajax" extends="json-default">
<result-types>
<result-type name="json" class="org.apache.struts2.json.JSONResult" />
</result-types>
<action name="AjaxAutocompleterAction" class="com.frk.gid.action.AjaxAutocompleterAction">
<interceptor-ref name="json">
<param name="contentType">application/json</param>
</interceptor-ref>
<interceptor-ref name="jsonValidation" />
<interceptor-ref name="params">
<param name="ordered">true</param>
</interceptor-ref>
<interceptor-ref name="prepare" />
<result name="success" type="json">
<param name="contentType">text/html</param>
</result>
</action>
</package>

log4net filtering on exception message?

How can I filter logging based on a logged exception's message?
Code looks like this:
try {
someService.DoSomeWorkflow();
} catch(Exception e) {
log.Error("Hey I have an error", e);
}
Config looks like this:
<appender name="EventLogger" type="log4net.Appender.EventLogAppender">
<applicationName value="foo" />
<layout type="log4net.Layout.PatternLayout" value="PID:%P{pid}: %message" />
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="TextInsideTheException" />
</filter>
</appender>
I'm finding that I can filter only on the logged message ("Hey I have an error") but it seemingly ignores the exception's message. Since this is in our production environment I can't make any code changes so I can't change the logged message. Is there some configuration that would specify to also check the exception's message?
By subclassing FilterSkeleton, you can implement a filter that evaluates the exception text. Or exception type for that matter.
Here are basic implementations based on Peter's accepted answer
using System;
using log4net.Core;
namespace log4net.Filter
{
public abstract class ExceptionFilterBase : FilterSkeleton
{
public override FilterDecision Decide(LoggingEvent loggingEvent)
{
if (loggingEvent == null)
throw new ArgumentNullException("loggingEvent");
var str = GetString(loggingEvent);
if (StringToMatch == null || string.IsNullOrEmpty(str) || !str.Contains(StringToMatch))
return FilterDecision.Neutral;
return AcceptOnMatch ? FilterDecision.Accept : FilterDecision.Deny;
}
protected abstract string GetString(LoggingEvent loggingEvent);
public string StringToMatch { get; set; }
public bool AcceptOnMatch { get; set; }
}
public class ExceptionMessageFilter : ExceptionFilterBase
{
protected override string GetString(LoggingEvent loggingEvent)
{
return loggingEvent.ExceptionObject == null
? null : loggingEvent.ExceptionObject.Message;
}
}
public class ExceptionTypeFilter : ExceptionFilterBase
{
protected override string GetString(LoggingEvent loggingEvent)
{
return loggingEvent.ExceptionObject == null
? null : loggingEvent.ExceptionObject.GetType().FullName;
}
}
public class ExceptionStackFilter : ExceptionFilterBase
{
protected override string GetString(LoggingEvent loggingEvent)
{
return loggingEvent.ExceptionObject == null
? null : loggingEvent.ExceptionObject.StackTrace;
}
}
}
Configuration file
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Client.log" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{yyyy/MM/dd HH:mm:ss,fff} [%-5level] %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="Token is not valid." />
<acceptOnMatch value="false" />
</filter>
<filter type="log4net.Filter.ExceptionMessageFilter, YourAssembly">
<stringToMatch value="Application is not installed." />
<acceptOnMatch value="false" />
</filter>
<filter type="log4net.Filter.ExceptionTypeFilter, YourAssembly">
<stringToMatch value="System.Deployment.Application.DeploymentException" />
<acceptOnMatch value="false" />
</filter>
<filter type="log4net.Filter.ExceptionStackFilter, YourAssembly">
<stringToMatch value="at System.Deployment.Application.ComponentStore.GetPropertyString(DefinitionAppId appId, String propName)" />
<acceptOnMatch value="false" />
</filter>
</appender>
Try this:
log.Error("Hey I have an error: " + e.Message);
Edit: Sorry, didn't see that you cannot change that line...