Edit: Working with Angular2 -
I'm trying to implement OAuth2 to make users log in using Facebook/Github.
When I'm at localhost:4200/login I simply click "log in with facebook" and it tries to redirect to localhost:4200/login/facebook BUT then it gives me the error:
ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'login/facebook'
Error: Cannot match any routes. URL Segment: 'login/facebook'
What could be wrong? I've spent hours trying to figure it out but with no luck. Am I missing anything?
In my OAuth2Index.ts file I have the following:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'OAuth2Index',
templateUrl: './auth-server/src/main/resources/static/index.html',
// styleUrls: ['./navbar.component.css']
})
export class OAuth2IndexComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
It displays the index.html file, which has:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Demo</title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />
<base href="/" />
<link rel="stylesheet" type="text/css"
href="/webjars/bootstrap/css/bootstrap.min.css" />
<script type="text/javascript" src="/webjars/jquery/jquery.min.js"></scr>
<script type="text/javascript"
src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</head>
<body ng-app="app" ng-controller="home as home">
<h1>Login</h1>
<div class="container" ng-show="!home.authenticated">
<div>
With Facebook: click here
</div>
<div>
With Github: click here
</div>
</div>
<div class="container" ng-show="home.authenticated">
Logged in as: <span ng-bind="home.user"></span>
<div>
<button ng-click="home.logout()" class="btn btn-primary">Logout</button>
</div>
</div>
<script type="text/javascript" src="/webjars/angularjs/angular.min.js"></script>
<script type="text/javascript">
angular
.module("app", [])
.config(
function($httpProvider) {
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
}).controller("home", function($http, $location) {
var self = this;
$http.get("/user").success(function(data) {
if (data.name) {
self.user = data.name;
self.authenticated = true;
} else {
self.user = "N/A";
self.authenticated = false;
}
}).error(function() {
self.user = "N/A";
self.authenticated = false;
});
self.logout = function() {
$http.post('logout', {}).success(function() {
self.authenticated = false;
$location.path("/");
}).error(function(data) {
console.log("Logout failed")
self.authenticated = false;
});
};
});
</script>
Please notice the: "With Facebook: click here
xxxx"
I have some beans in my SocialApplication.java file that should handle the action when user clicks login with facebook (i.e. /login/facebook).
/*
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example;
import java.security.Principal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.filter.CompositeFilter;
#SpringBootApplication
#RestController
#EnableOAuth2Client
#EnableAuthorizationServer
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SocialApplication extends WebSecurityConfigurerAdapter {
#Autowired
OAuth2ClientContext oauth2ClientContext;
#RequestMapping({ "/user", "/me" })
public Map<String, String> user(Principal principal) {
Map<String, String> map = new LinkedHashMap<>();
map.put("name", principal.getName());
return map;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.antMatcher("/**").authorizeRequests().antMatchers("/", "/login**", "/webjars/**").permitAll().anyRequest()
.authenticated().and().exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")).and().logout()
.logoutSuccessUrl("/").permitAll().and().csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
// #formatter:on
}
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.antMatcher("/me").authorizeRequests().anyRequest().authenticated();
// #formatter:on
}
}
public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}
#Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
#Bean
#ConfigurationProperties("github")
public ClientResources github() {
return new ClientResources();
}
#Bean
#ConfigurationProperties("facebook")
public ClientResources facebook() {
return new ClientResources();
}
private Filter ssoFilter() {
CompositeFilter filter = new CompositeFilter();
List<Filter> filters = new ArrayList<>();
filters.add(ssoFilter(facebook(), "/login/facebook"));
filters.add(ssoFilter(github(), "/login/github"));
filter.setFilters(filters);
return filter;
}
private Filter ssoFilter(ClientResources client, String path) {
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
path);
OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
filter.setRestTemplate(template);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(
client.getResource().getUserInfoUri(), client.getClient().getClientId());
tokenServices.setRestTemplate(template);
filter.setTokenServices(tokenServices);
return filter;
}
}
class ClientResources {
#NestedConfigurationProperty
private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
#NestedConfigurationProperty
private ResourceServerProperties resource = new ResourceServerProperties();
public AuthorizationCodeResourceDetails getClient() {
return client;
}
public ResourceServerProperties getResource() {
return resource;
}
}
I'm my app-routing.module.ts I have:
const routes: Routes = [
// {path: 'index.html ', data: {title: 'Login'}, component: LoginComponent},
// {path: 'login', data: {title: 'Login'}, component: LoginComponent},
// {path: 'index ', data: {title: 'Login'}, component: OAuthIndexComponent},
{path: 'login', data: {title: 'Login'}, component: OAuth2IndexComponent},
{path: 'signup', data: {title: 'Login'}, component: UserRegistrationComponent},
{path: '', pathMatch: 'full', redirectTo: '/login'},
{
path:'',component: AppWrap,
children:[
{path: 'cars', data: {title: 'Car'}, component: ProductsComponent},
{path: 'cars/:id', data: {title: 'Car'}, compoent: ProductSingleDetailComponent},
// {path: 'login/facebook', data: {title: 'facebookLogin'}, component: OAuth2IndexComponent}
]
}
];
In my app.module.ts I have remembered to declare OAuth2IndexComponent.
Related
I want then user logined(authorize) in header menu displayed menu with username(login) like at picture.
For this purpose i have the corresponding code in angular:
File header.component.html:
<nav class="navbar">
<a routerLink="" id="nav_logo">
DishOnline
</a>
<div id="nav_right_section">
<a routerLink="/loginPage">
Вход
</a>
<button [hidden]=" receivedAnswer!==undefined && receivedAnswer!==null" mat-button [matMenuTriggerFor]="menu">{{receivedAnswer.login}}</button>
<mat-menu #menu="matMenu">
<button mat-menu-item>Мой кабинет</button>
<button mat-menu-item>Выйти</button>
</mat-menu>
</div>
</nav>
File header.component.ts:
import {Component,OnInit } from '#angular/core';
import { LoginNameService} from '../services/loginName.service';
import {LoginName} from '../classes/loginName';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls : ['./header.component.scss'],
providers: [LoginNameService]
})
export class HeaderComponent implements OnInit
{
receivedAnswer: LoginName;
loginNameObject: LoginName=new LoginName();
constructor(private loginNameService: LoginNameService) {}
submit() {
this.loginNameService.postData()
.subscribe((data: LoginName) => {},
error => console.log(error)
);
}
ngOnInit(): void {
this.receivedAnswer=this.loginNameObject;
this.submit();
}
}
I send on server(backend - Spring Boot) empty POST request, using for this service loginName.service.ts.
File loginName.service.t:
import {Injectable} from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
#Injectable()
export class LoginNameService {
constructor(private http: HttpClient) { }
postData() {
// tslint:disable-next-line:prefer-const
let baseUrl = 'http://localhost:8089';
return this.http.post(baseUrl + '/loginName', null);
}
}
From service i have the answer in JSON:
{"login":"DishOnline"}
But received login not displayed in header.
Code receiving login on backend(Spring Boot):
package com.greatproject.dishonline.controller;
import com.greatproject.dishonline.service.MyUserDetailsService;
import com.greatproject.dishonline.service.MyUserPrincipal;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
#RestController
public class AuthorizationController {
#RequestMapping("/loginName")
public #ResponseBody
Map<String,String> loginName(Model model,
Authentication authentication,
HttpSession session,
MyUserPrincipal principal
) {
String login = "";
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
login = auth.getName(); //get logged in username
Map<String, String> mapLoginName = new HashMap<String, String>();
mapLoginName.put("login", login);
return mapLoginName;
}
}
Please help me resolve this problem.
You can get the username off the principal. Try adding the principal.username to the model and retrieving it on the ui that way.
My Angular application is running on http://localhost:4200 port and Spring Boot on http://localhost:8080 port.
When I PUT request from client side I get this error.
I tried to create headers by doing:
headers = new HttpHeaders({'Access-Control-Allow-Origin' : '*'})
and then put headers variable in PUT request like this:
this.http.put("//localhost:8080/save-account", accountForm,
{headers: this.headers}).subscribe(
res => console.log(res),
err => console.log(err)
)
But nothing worked out.
My code :
Server side controller:
package com.tigran.chagmo.controllers;
import com.tigran.chagmo.models.AccountRepository;
import java.util.Collection;
import com.tigran.chagmo.entities.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#CrossOrigin(origins="http://localhost:4200")
public class HomeController{
#Autowired
AccountRepository accRepo;
#PutMapping("/update-account")
public Account putAccount(#RequestBody Account account){
accRepo.save(account);
return account;
}
}
Client side Typescript files.
Angular app.module.ts file:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { Routes, RouterModule } from '#angular/router';
import { HomeComponent } from './home/home.component';
import { NotFoundComponent } from './not-found/not-found.component';
import { SignUpComponent } from './sign-up/sign-up.component';
import { LinksService } from './links/links.service';
import { FormsModule } from '#angular/forms';
import { AccountService } from './account-service/account.service';
import { HttpClientModule } from '#angular/common/http';
const appRoutes: Routes = [
{
path: '',
component: HomeComponent
},
{
path: 'home',
component: HomeComponent
},
{
path: 'sign-up',
component: SignUpComponent
},
{
path: '**',
component: NotFoundComponent
}
]
#NgModule({
declarations: [
AppComponent,
HomeComponent,
NotFoundComponent,
SignUpComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot(appRoutes)
],
providers: [
LinksService,
AccountService
],
bootstrap: [AppComponent]
})
export class AppModule { }
Angular sign-up component ts file:
import { Component, OnInit } from '#angular/core';
import { LinksService } from '../links/links.service';
import { AccountService } from '../account-service/account.service';
#Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent implements OnInit {
constructor(private links: LinksService,
private accountService: AccountService) { }
getHome(){
this.links.getHome();
}
save(accountForm: any){
this.accountService.update(accountForm);
}
ngOnInit(){
this.accountService.getAll();
}
}
Account service ts file:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class AccountService {
constructor(private http: HttpClient) { }
getAll(){
return this.http.get("//localhost:8080/accounts")
}
getOne(id: number){
return this.http.get("//localhost:8080/account/"+id);
}
update(accountForm: any) {
this.http.put("//localhost:8080/save-account",
accountForm).subscribe(
res => console.log(res),
err => console.log(err)
)
}
}
Sign-up component html file:
<form #accountForm="ngForm" (ngSubmit)="save(accountForm.value)" class="text-center border border-light p-5" >
<label for="gmail" >Gmail</label>
<input
ngModel name="gmail"
id="gmail"
class="form-control mb-4"
tpye="text" >
<label for="name" >Name</label>
<input
ngModel name="name"
id="name"
class="form-control mb-4"
tpye="text" >
<label for="username" >Username</label>
<input
ngModel name="username"
id="username"
class="form-control mb-4"
tpye="text" >
<label for="password" >Password</label>
<input
ngModel name="password"
id="password"
class="form-control mb-4"
tpye="text" >
<label for="repeat-password" >Repeat password</label>
<input
ngModel name="repeat-password"
id="repeat-password"
class="form-control mb-4"
tpye="text" >
<button [disabled]="!accountForm.valid" class="btn btn-info btn-block my-4" >Sign up</button>
<p class="text-left" >Already have an account? <a routerLink="{{ getHome() }}" class="text-primary text-right">Log in</a></p>
</form>
After filling the form via browser and sending data. I get this error.
Failed to load resource: the server responded with a status of 403 ()
Access to XMLHttpRequest at 'http://localhost:8080/save-account'
from origin 'http://localhost:4200' has been blocked by CORS
policy: Response to preflight request doesn't pass access control
check: No 'Access-Control-Allow-Origin' header is present on the
requested resource.
HttpErrorResponse
error: ProgressEvent {isTrusted: true, lengthComputable: false, loaded:
0, total: 0, type: "error", …}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null,
headers: Map(0)}
message: "Http failure response for (unknown url): 0 Unknown Error"
name: "HttpErrorResponse"
ok: false
status: 0
statusText: "Unknown Error"
url: null
__proto__: HttpResponseBase
Please help me to get rid of this error and explain why is it happening.
Thanks in advance.
Add this code in Application.java
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
This worked for me. I just added this bean to a WebConfig Spring class that extended through WebMvcConfigurationSupport. And here the imports for me.
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.cors.CorsConfiguration;
Two errors in the link (no http: and save-account instead of update-account):
this.http.put("//localhost:8080/save-account", accountForm,
{headers: this.headers}).subscribe(
res => console.log(res),
err => console.log(err)
)
The link should be
http://localhost:8080/update-account
By putting HTTP methods in a list as below, you can solve your problem. Add this code to the Application.java file.
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
config.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS", "DELETE", "PUT", "PATCH"));
config.setAllowCredentials(true);
config.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
While trying to do a simple program about the Spring MVC I got always the same error when running http://localhost:8080/project_name/:
404 - the requested resource is not available
This is the architecutre of the project:
src
| +--com
| +--memorynotfound
| +--config
| |--ServletInitializer.java
| |--WebConfig.java
| +--controller
| |--HomeController.java
| +--resources
| +--webapp
| +--WEB-INF
| +--views
| |--index.jsp
Here is the files in the package com.memorynotfound.config:
ServletInitializer.java
package com.memorynotfound.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
}
WebConfig.java
package com.memorynotfound.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="com.memorynotfound")
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver viewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
Files in the package com.memorynotfound.controller:
HomeController.java
package com.memorynotfound.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.ui.ModelMap;
#Controller
#RequestMapping("/")
public class HomeController {
#RequestMapping(method = RequestMethod.GET)
public String index(ModelMap model){
System.out.println("This is a test ================>");
model.addAttribute("message", "Spring MVC Java Configuration Example");
return "index";
}
}
And finally the Jsp file:
index.jsp
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Spring MVC Java Configuration Example</title>
</head>
<body>
${message}
</body>
</html>
I thought that when you were using Spring MVC without a web.xml file, you needed to supply an implementation of WebApplicationInitializer
Without such an initializer, you would still need to provide a web.xml file.
Minimally your WebApplicationInitializer instance should probably use setLoadOnStartup(1) and provide a mapping for the dispatcher.
From the referenced web page above
public class MyWebApplicationInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
registration.setLoadOnStartup(1);
registration.addMapping("/example/*");
}
}
I solved the problem by doing :
right click on the project name and select properties
Select Deployment assembly
Add spring and JTL jars
I'm new to Spring Web MVC and I tried to try Hello world app.
I followed an example from "Spring In Action 4th ed" book which only uses java config (without any XML file). I use Tomcat v7.0 server and servlet 3.
The problem is when I try to go to the home page I get Http 404 error.
The used Java classes are :
DispatcherServlet configuration:
package config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class FirstWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
}
Spring MVC configuration :
package config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#EnableWebMvc
#ComponentScan("web")
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Configuration used to get other Beans (doesn't do any thing in the hello world app)
package config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
#Configuration
#ComponentScan(basePackages={"lgmi_cr"},excludeFilters={#Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)})
public class RootConfig {
}
Home page controller
package web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class HomeController {
#RequestMapping(value="/")
public String home() {
return "home";
}
}
A JSP file "home" uneder /WEB-INF/views/
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>First app</title>
</head>
<body>
<h1>Hello world</h1>
</body>
</html>
Since it 404 error, my first impression is that it could not find any controller but I don't know why.
Thank you for any help
I have just found the problem.
Actually, I added the external Spring jar files to the project classpath and I forget to add them to myProject/WebContent/WEB-INF/lib.
in my Icefaces 3 application i have a drop down menu. I would like to populate it dynamicaly. In my ManagedBean i have a methode which define the menuItem. it get the label and actionMethod, and valued them on the MenuItem. When i launch my application, the item of drop down menu are always empty.
ManagedBean :
package com.omb.view;
import java.io.Serializable;
import javax.el.MethodExpression;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.icesoft.faces.component.menubar.MenuItem;
#Controller
#Scope("session")
public class MyBean implements Serializable {
private static final Log logger = LogFactory.getLog(MyBean.class);
private MenuItem menuItem1;
public String initMyBean() {
try {
initMenuItem();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
private void initMenuItem() {
menuItem1 = new MenuItem();
menuItem1.setValue("Menu 1");
MethodExpression actionExpression = FacesUtils.createAction("#{menu1Bean.display}", String.class);
menuItem1.setActionExpression(actionExpression);
}
public MenuItem getMenuItem1() {
return this.menuItem1;
}
public void setMenuItem1(MenuItem menuItem1) {
this.menuItem1 = menuItem1;
}
}
FaceUtils
package com.omb.view;
import javax.el.MethodExpression;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.MethodExpressionActionListener;
/**
* JSF utilities.
*/
public class FacesUtils {
public static MethodExpression createAction(String actionExpression, Class<?> returnType) {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().getExpressionFactory()
.createMethodExpression(context.getELContext(), actionExpression, returnType, new Class[0]);
}
public static MethodExpressionActionListener createActionListener(String actionListenerExpression) {
FacesContext context = FacesContext.getCurrentInstance();
return new MethodExpressionActionListener(context
.getApplication()
.getExpressionFactory()
.createMethodExpression(context.getELContext(), actionListenerExpression, null,
new Class[] {ActionEvent.class}));
}
}
screen.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition>
<ice:form id="headerForm" xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ice="http://www.icesoft.com/icefaces/component"
xmlns:ace="http://www.icefaces.org/icefaces/components"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<div class="menu">
<ace:menuButton id="menuButton" effect="slide" effectDuration="200" value="Menu Button">
<ace:menuItem binding="#{myBean.menuItem1}"/>
</ace:menuButton>
</div>
</ice:form>
</ui:composition>
</body>
</html>
I finally use a the standard solution :
<ace:menuButton id="menuButton" effect="slide" effectDuration="200" value="Menu Button">
<ace:menuItem value="Menu 1" action="#{myBean.display}"/>
</ace:menuButton>