unable to render index or mobile page with spring mobile - spring-boot

I was able to get my project to run just fine until I brought in spring-mobile. Now only Strings will return in the browser that the spring-mobile method is returning:
#Controller
public class DeviceDetection {
private Logger logger = LoggerFactory.getLogger(DeviceDetection.class);
#RequestMapping(value="/index")
public String detectDevice(Device device) {
if (device.isNormal()) {
System.out.println("Inside isNormal()");
return "index";
} else if (device.isMobile()) {
System.out.println("Inside isMobile()");
return "mobilePage";
} else if (device.isTablet()) {
return "mobilePage";
}
return "index";
}
}
So I decided I needed internalResourceViewResolver but that just gives me the following error:
Error creating bean with name 'viewResolver' defined in class path resource
[org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoCon
figurationAdapter.class]: Initialization of bean failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating bean
with name 'org.springframework.boot.autoconfigure.mobile
and
DeviceDelegatingViewResolverAutoConfiguration$DeviceDelegatingViewResolverConfigur
ation$InternalResourceViewResolverDelegateConfiguration.viewResolver; nested
exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
qualifying bean of type
[org.springframework.web.servlet.view.InternalResourceViewResolver] is
defined: expected single matching bean but found 2:
getViewResolver,defaultViewResolver
Resolver class
#Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".html");
return resolver;
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Main Class
#SpringBootApplication
public class StidhamFinancialApplication extends SpringBootServletInitializer {
public static void main(String[] args) throws UnknownHostException {
SpringApplication app = new SpringApplication(StidhamFinancialApplication.class);
Environment env = app.run(args).getEnvironment();
System.out.println(String.format("Access URLs:\n----------------------------------------------------------\n\t" +
"Local: \t\thttp://127.0.0.1:%1s\n\t" +
"External: \thttp://%2s:%3s\n----------------------------------------------------------",
env.getProperty("server.port"),
InetAddress.getLocalHost().getHostAddress(),
env.getProperty("server.port")));
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(StidhamFinancialApplication.class);
}
}
project structure:
I am running it on Tomcat 8...
--------Update 1---------------
I deleted my configuration package and add #ResponeBody to my detectDevice method like so:
//If I remove #ResponseBody it complains of a Circular view path [index] with
#ResponseBody it just renders a String and not a view
#RequestMapping(value="/index")
public #ResponseBody String detectDevice(Device device) {
if (device.isNormal()) {
System.out.println("Inside isNormal()");
return "index";
} else if (device.isMobile()) {
System.out.println("Inside isMobile()");
return "mobilePage";
} else if (device.isTablet()) {
return "mobilePage";
}
return "index";
}
Only the String index or mobilePage will render in the browser. If I delete the #ResponseBody then the project gives an error saying the following:
2016-05-29 08:55:03.682 ERROR 8230 --- [nio-8080-exec-1]
o.s.boot.context.web.ErrorPageFilter : Forwarding to error page
from request [/index.html] due to exception [Circular view path
[index]: would dispatch back to the current handler URL [/index] again.
Check your ViewResolver setup! (Hint: This may be the result of an
unspecified view, due to default view name generation.)]
If I remove the /index then the method is ignored completely and spring-boot just maps my index file and works again but I need the mobile site to work.
-------------------UPDATE 2-------------------
Ok I added thymeleaf and my index page is rendering again. Even better the DeviceDetection is working but once my project looks for my mobilePage I get the following error:
Error resolving template "mobile/index", template might not exist or might not be accessible by any of the configured Template Resolvers
I had to add the follow ing #Configuration to get the project to work. The spring-boots defaultViewResolver was causing me to many issues. Here is the project structure now:
I updated the project on GIT too.

First I needed to use something like Thymeleaf and create a viewResolver. Spring-boots defaultViewResolver was causing me issues:
#Configuration
public class WebConfiguration extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public DispatcherServlet dispatcherServlet(){
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
return dispatcherServlet;
}
#Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setOrder(1);
return resolver;
}
}
Since I was using Thymeleaf I needed bindingResult and a few other things. This is also where I implemented springs mobile Device interface to detect the device.
#Controller
public class FormController {
#RequestMapping(value="/", method= RequestMethod.GET)
public String contactForm(#Valid #ModelAttribute("person") Contact contact, BindingResult bindingResult,
HttpServletRequest request, Model model, Device device) throws IOException {
if(bindingResult.hasErrors()){
System.out.println("There was a error "+bindingResult);
return "error";
}
model.addAttribute("contact", new Contact());
if(device.isNormal()){
System.out.println("I am normal");
return "index";
} else if(device.isMobile()){
System.out.println("I am a mobile");
return "mobilePage";
} else if (device.isTablet()){
System.out.println("I am a tablet");
return "mobilePage";
}
return "index";
}
Now I just needed to put the different views in the correct directories like so:
That was it and it is working perfectly.
Here is the form I created to use implement Thymeleaf:
<!-- Contact form -->
<form action="#" th:action="#{/contact}" th:object="${contact}" method="POST" class="contact-form clear-fix">
<div class="clear-fix">
<ul class="list-0 clear-fix">
<!-- Name -->
<li>
<div class="block field-box">
<label for="contact-form-name" class="text-color-black">Your Name</label>
<input type="text" th:field="*{name}" class="contact noMarr col-md-6 text-color-black" id="contact-form-name" />
</div>
</li>
<!-- /Name -->
<!-- E-mail address -->
<li>
<div class="block field-box">
<label for="contact-form-mail" class="text-color-black">Your E-mail</label>
<input type="text" th:field="*{email}" class="contact noMarr col-md-6 text-color-black" id="contact-form-mail" />
</div>
</li>
<!-- /E-mail address -->
<!-- Website URL -->
<li>
<div class="block field-box">
<label for="contact-form-subject" class="text-color-black">Subject</label>
<input type="text" th:field="*{subject}" class="contact noMarr col-md-6 text-color-black" id="contact-form-subject" />
</div>
</li>
<!-- /Website URL -->
<!-- Message -->
<li>
<div class="block field-box ">
<label for="contact-form-message" class="text-color-black">Your message</label>
<textarea name="comment" class="contact col-md-12 text-color-black" th:field="*{message}" id="contact-form-message"></textarea>
</div>
</li>
<!-- /Message -->
<!-- Submit button -->
<li>
<div class="block field-box field-box-button text-color-black">
<input type="submit" id="contact-form-submit" name="contact-form-submit" class="button text-color-black" value="Submit"/>
</div>
</li>
<!-- /Submit button -->
</ul>
</div>
</form>

Related

Primefaces Theme change to user specific

When I use the below code it's working fine and change the theme, but the problem is if one of the user logged and change the theme it effects to the every user in the system. what I want is to effect the theme only for the particular user but not for every one.
Web.xml
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>#{settingsController.userTheme}</param-value>
</context-param>
primeface (.xhtml)
<h:outputLabel for="userTheme" value="Theme Name *:" style="width: 300px"/>
<p:selectOneMenu id="userTheme" value="#{settingsController.userTheme}" style="width:200px"
required="true" requiredMessage="Theme Name is Required" >
<f:selectItems value="#{settingsController.themeMap}"/>
</p:selectOneMenu>
SettingsController.java class
#ManagedBean(name = "settingsController")
#SessionScoped
#Controller
public class SettingsController {
private String userTheme = "start" ;
private Map<String , String> themeMap ;
#PostConstruct
public void init (){
setThemeMapInit( );
}
public String getUserTheme() {
return userTheme;
}
public void setUserTheme(String userTheme) {
this.userTheme = userTheme;
}
public Map<String, String> getThemeMap() {
return themeMap;
}
public void setThemeMapInit() {
themeMap = new LinkedHashMap<String, String>();
themeMap.put("Aristo", "aristo");
themeMap.put("After-noon", "afternoon");
themeMap.put("After-Work", "afterwork");
themeMap.put("Black-Tie", "black-tie");
themeMap.put("Blitzer", "blitzer");
themeMap.put("Bluesky", "bluesky");
themeMap.put("Bootstrap", "bootstrap");
themeMap.put("Casablanca", "casablanca");
themeMap.put("Cupertino", "cupertino");
themeMap.put("Dark-Hive", "dark-hive");
themeMap.put("Delta", "delta");
themeMap.put("Excite-Bike", "excite-bike");
themeMap.put("Flick", "flick");
themeMap.put("Glass-X", "glass-x");
themeMap.put("Home", "home");
themeMap.put("Hot-Sneaks", "hot-sneaks");
themeMap.put("Humanity", "humanity");
themeMap.put("Overcast", "overcast");
themeMap.put("Pepper-Grinder", "pepper-grinder");
themeMap.put("Redmond", "redmond");
themeMap.put("Rocket", "rocket");
themeMap.put("Sam", "sam");
themeMap.put("Smoothness", "smoothness");
themeMap.put("South-Street", "south-street");
themeMap.put("Start", "start");
themeMap.put("Sunny", "sunny");
themeMap.put("Swanky-Purse", "swanky-purse");
themeMap.put("UI-Lightness", "ui-lightness");
}
public void setThemeMap(Map<String, String> themeMap) {
this.themeMap =themeMap;
}
public void sumbitUserSettings (){
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
try {
ec.redirect(((HttpServletRequest) ec.getRequest()).getRequestURI());
} catch (IOException ex) {
Logger.getLogger(SettingsController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Every Spring bean is a Singletone by default, that's why all users are affected, despite of #SessionScoped.
You can't use #ManagedBean and #Controller at the same time, see why.
The best way to combine Spring and JSF in the same app, is to use Joinfaces.
With Joinfaces your bean will end up looking like this
#Named
#SessionScoped
public class SettingsController {
Related:
JSF vs. Spring MVC

Trying to create a dropdown in my jsp page

I am trying to create a dropdown which will have dynamic values in my jsp page but getting an exception, i am trying to use spring form tags here.
WebController.java
#RequestMapping(value="/addAchivement",method=RequestMethod.GET)
public String addAchievements(){
Object object=null;
try {
object = genericAppProcessor.checkLogin(username, password,null,null);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SchoolLoginDetails sld=new SchoolLoginDetails();
sld=(SchoolLoginDetails)object;
List<GroupDetails> list=new ArrayList<GroupDetails>();
list=(List<GroupDetails>) sld.getGroupDetails();
Set<Object> addedClass = new HashSet<Object>();
Set<Object> addedSection = new HashSet<Object>();
Map referenceData = new HashMap();
Map<Object,Object> classs = new LinkedHashMap<Object,Object>();
for(int i=0;i<list.size();i++){
Object obj=list.get(i).getClazz();
Object objj=list.get(i).getSection();
addedClass.add(obj);
addedSection.add(objj);
List<Object> convertTolist=new ArrayList<Object>(addedClass);
classs.put(convertTolist.get(0),convertTolist.get(0));
addedClass.clear();
}
referenceData.put("classList",classs);
return "addAchivement";
}
addAchivement.jsp
<form:form method="POST" role="form" action="/GenericApp/addWebAchievement" enctype="multipart/form-data">
<form:select path="classs">
<form:options items="${classList}" />
</form:select>
Exception :-
org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/jsp/addAchivement.jsp at line 72
<div class="input-field col s12 m4 l3" >
<!--Line 72 --> <form:select path="classs" class="text-black custom-select">
<form:options items="${classList}" />
</form:select>
you need to return model and view instead of just returning a view Use Below Code :
// Java Code
#RequestMapping(value="/addAchivement",method=RequestMethod.GET)
public ModelAndView addAchievements(){
Object object=null;
try {
object = genericAppProcessor.checkLogin(username, password,null,null);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SchoolLoginDetails sld=new SchoolLoginDetails();
sld=(SchoolLoginDetails)object;
List<GroupDetails> list=new ArrayList<GroupDetails>();
list=(List<GroupDetails>) sld.getGroupDetails();
Set<Object> addedClass = new HashSet<Object>();
Set<Object> addedSection = new HashSet<Object>();
Map referenceData = new HashMap();
Map<Object,Object> classs = new LinkedHashMap<Object,Object>();
for(int i=0;i<list.size();i++){
Object obj=list.get(i).getClazz();
Object objj=list.get(i).getSection();
addedClass.add(obj);
addedSection.add(objj);
List<Object> convertTolist=new ArrayList<Object>(addedClass);
classs.put(convertTolist.get(0),convertTolist.get(0));
addedClass.clear();
}
referenceData.put("classList",classs);
ModelAndView mav = new ModelAndView("addAchivement", referenceData);
return mav;
}
You are assigning a path to classs in your jsp
<!--Line 72 --> <form:select path="classs" class="text-black custom-select">
but you are not sending anything from model on which this class variable can map so you need to use modelAttribute in your spring form so that this class variable can map .
for eg .
: you need to make a class object which has a class as member :
below is java code change :
referenceData.put("classList",classs);
referenceData.put("classObject",class); // Here class is a object that has class attribute by which that value in jsp will bind .
ModelAndView mav = new ModelAndView("addAchivement", referenceData);
Here is Jsp Code change :
<form:form method="POST" role="form" action="/GenericApp/addWebAchievement" enctype="multipart/form-data" modelAttribute="classObject">
<form:select path="classs">
<form:options items="${classList}" />
</form:select>
Sample class object :
public Class{
String classs ;
// getter setter for classs member variable .
}

Why update method isn't calling?

I have a problem. When I click to update image on form, update method isn't calling. I see that in my output logs window. Only may update image in first row in my table.
When I updating first row:
Hibernate: update shoe_goods set description=?, image=?, in_stock=?,
name=?, price=?, size=?, web_store_id=? where id=?
When other rows - nothing.
I save my images in db as byte.
This is my method to display images:
Controller:
#RequestMapping(value = "/imageController/{id}")
#ResponseBody
public byte[] getImages(#PathVariable int id) {
return shoeGoodsService.getById(id).getImage();
}
JSP:
<img src="/imageController/${goods.id}" alt="Image" />
Code in DAO class:
#Override
public void update(ShoeGoods shoeGoods) {
sessionFactory.getCurrentSession().merge(shoeGoods);
sessionFactory.getCurrentSession().getTransaction().commit();
}
Code in Service class:
#Override
public void update(ShoeGoods shoeGoods) {
shoeGoodsDAO.update(shoeGoods);
}
Code in controller, when update method is call only for first row in table:
#RequestMapping(value="/upload_shoe_image", method = RequestMethod.POST)
public #ResponseBody ModelAndView handleFileUpload1(#RequestParam("file") MultipartFile file){
...
try {
ShoeGoods shoeGoods = shoeGoodsService.getById(goodsId);
shoeGoods.setImage(file.getBytes());
//not call always
shoeGoodsService.update(shoeGoods);
} catch (Exception e) {
e.printStackTrace();
}
...
}
In JSP:
<form id="send-image-form" method="POST" enctype="multipart/form-data"
action="/upload_shoe_image">
Edit: <input type="file" name="file">
<br />
Save: <input type="submit" id="save-image" value="Upload">
</form>

Validation Spring confusion to render error message

I try to render error message but it's not appears:
I have validator:
#Component
class ValidatorFBOSSearch implements Validator {
#SuppressWarnings("rawtypes")
#Override
public boolean supports(Class clazz) {
return FormBackObjectSearch.class.equals(clazz);
}
#Override
public void validate(Object obj, Errors error) {
FormBackObjectSearch fbos = (FormBackObjectSearch)obj;
if ("".equals(fbos.particularDate)){
error.rejectValue("particularDate", "required.listOfDates", "This field is required");
}
}
}
it have to cheak does my field in backing object for form have value inputed or not. rejectValue has three param. First - looks for a value in Model Attribute in my backing object, Secong looks for error message in properties file(my properties file located in resourses/error forlder) Third param in methos says if it won't be able to find message in error properties file will render it as default, here is my sniped of code in my servlet-context.xml
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
And this my xml config for messageSourse to get errors for Validator in servlet-context.xml:
<!-- Resolves error messages for validator from /Education/src/main/webapp/resources/errors-->
<beans:bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basename" value="errors/errormessages"/>
</beans:bean>
Here peace of my controller code for dealing with requests:
#RequestMapping(value="/search", method=RequestMethod.GET)
public void search(Model model) {
FormBackObjectSearch fbos = new FormBackObjectSearch();
model.addAttribute("fbosAttribute", fbos);
}
#RequestMapping(value ="/result", method=RequestMethod.POST)
public String extract(#RequestParam String nameOfInstitution,
#RequestParam String particularDate,
#RequestParam String typeOfInstitution,
#ModelAttribute("fbosAttribute") FormBackObjectSearch fbos,
BindingResult result, RedirectAttributes redirectAttributes,
Model model) throws Exception {
ValidatorFBOSSearch validatorFBOS = new ValidatorFBOSSearch();
validatorFBOS.validate(fbos, result);
if(result.hasErrors()) {
redirectAttributes.addFlashAttribute("fbosAttribute", fbos);
return "redirect:/search";
} else {
if(particularDate !="" && nameOfInstitution !="" && typeOfInstitution =="") {
controllerSupportClass.findWithDateAndName(nameOfInstitution, particularDate, model);
} else if(particularDate !="" && nameOfInstitution =="" && typeOfInstitution !="") {
controllerSupportClass.findWithAddedDateAndType(typeOfInstitution, particularDate, model);
} else if(particularDate !="" && nameOfInstitution =="" && typeOfInstitution ==""){
controllerSupportClass.findWithAddedDate(particularDate, model);
} else if(particularDate !="" && nameOfInstitution !="" && typeOfInstitution !="") {
throw new Exception("Search by choose all parameters is not exceptable");
} else {
throw new Exception("You didn't put any search parameters");
}
}
return "search";
}
And here is peace of my jsp:
<form:form action="result" method="post" modelAttribute="fbosAttribute" >
<table>
<tr>
<th>Date for extracting:</th>
<td><form:select path="particularDate">
<form:option value=""> -Choose date-</form:option>
<form:options items="${listOfDates}"></form:options>
</form:select> <td><form:errors path="particularDate" cssClass="error"/></td>
</td>
</tr>
</table>
</form:form>
The problem is thet I can not see error messages show up. I tried to use Flash Attributes to have error appears after riderect, but nothing heppend. cuz I found here that when I use rederect it makes my model and errors deleted and start new one. But How can I have advantage to use flash attibutes to solve my problem. Thank you
To register the validator for an specific controller you need can use the `#InitBimder' annotation.
#InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(new ValidatorFBOSSearch());
}
For mor details how to register the validator see my answer at:
Validation in Spring MVC
I think your check statement is wrong:
if ("".equals(fbos.particularDate)){
If a user enters nothing, then a String will not be empty ( "" ), it will be null. Therefore use:
if (fbos.particularDate == null || fbos.particularDate.isEmpty())

Error in onSubmit, feedback not rendering

I have some logic in onSubmit of the button (which is in Form), which may fail, so I would like to show a message using error(myMessage). But it doesn't work, and it seems that it is normal:
Feedback panel added but does not show all messages
Is there any possibility to render feedback panels with errors reported in onSubmit?
There is no ajax used on the page. I am using wicket 1.5.6
EDIT:
MyPage.java
public class MyPage extends WebPage {
private static final Logger logger = Logger.getLogger(MyPage.class);
private static final long serialVersionUID = -8874964120018036584L;
public MyPage(PageParameters parameters) {
super(parameters);
logger.debug("Creating new login page");
add(new MyLoginForm("loginForm"));
}
}
MyLoginForm.java
public class MyLoginForm extends StatelessForm<Void> {
private static final Logger logger = Logger.getLogger(MyLoginForm.class);
private static final long serialVersionUID = -8694389090804630170L;
private MyUser user = new MyUser();
public MyLoginForm(String id) {
super(id);
setOutputMarkupId(true);
logger.debug("Creating new stateless login form");
add(new RequiredTextField<String>("login", new PropertyModel<String>(user, "login")));
add(new PasswordTextField("password", new PropertyModel<String>(user, "password")));
add(new Button("submit"));
add(new FeedbackPanel("feedback"));
}
#Override
public void onSubmit() {
info("test info");
}
}
MyPage.html
<body>
<form wicket:id="loginForm">
<fieldset>
<legend><wicket:message key="form.login.legend"/></legend>
<input type="text" wicket:id="login" />
<input type="password" wicket:id="password" />
<input type="submit" wicket:id="submit" />
<span wicket:id="feedback"></span>
</fieldset>
</form>
</body>
catalina.out
16 May 2012 15:24:20:860 WARN [http-8080-2] [WebSession:135] Component-targetted feedback message was left unrendered. This could be because you are missing a FeedbackPanel on the page. Message: [FeedbackMessage message = "test info", reporter = loginForm, level = INFO]
The same happens when I try to overwrite the onSubmit method in Button instead of the one in MyLoginForm...
You need to add a FeedbackPanel to your Page. Feedback messages 'bubble' up in the component hierarchie. The easiest way is to have one feedbackpanel on your page.
But, you can also display errors close to the FormComponent that reports the error. See this pdf for inspiration or for a possible implementation.
Edit: I just build a very simple test, using the wicket quickstart. Changed the HomePage as below and it worked (I saw all error / info messages)
html:
<form wicket:id="form">
<div wicket:id="feedback"></div>
<input wicket:id="submit" type="button" value="submit">
</form>
Java:
Form<Void> form = new Form<Void>("form") {
#Override
protected void onSubmit() {
super.onSubmit();
error("test error from form");
error("test info from form");
}
};
add(form);
form.add(new FeedbackPanel("feedback"));
form.add(new SubmitLink("submit") {
#Override
public void onSubmit() {
super.onSubmit();
error("an error occurred in button submit");
info("test info from the button");
}
});
Edit 2: It turns out, that a StatelessForm is used (I overlooked that detail). Switching back to (normal) Form, the messages should be displayed correctly.
I have checked twice, Wicket 1.5.6 FeedbackPanel (and SignInForm where I have problem) works worse than 1.5.4
I have no idea, what is backgroud of this behaviour.
EDIT: version 1.5.5 work good.
EDIT2: https://issues.apache.org/jira/browse/WICKET-4536
I found another way for anyone else who stumbles into this issue..
I have a base class that I inherit from and then I have the feedback messages print out as part of the base class.. I too ran into this issue, and just had a method inside my base class return an instance of itself (return this), and then I just access the info method through this method... so, getMethod().info("some message").. and it worked for me. My feedbackPanel is also set in the base class..
So I'd imagine you can do the same thing.. Just get access to an instance of the page you want to stamp the feedback message to.

Resources