2014-10-10 52 views
2

我們使用Eclipse Kepler IDE來開發我們的GWT應用程序,並且已經使用Ant腳本長時間部署到Tomcat容器。我們最近決定改用Hudson CI服務器來簡化GWT編譯和部署過程。我們遇到的問題是,當我們允許Eclipse執行它自己的連續構建時,然後執行GWT編譯/部署,我們的應用程序按預期工作。然而,當我們使用外部的javac程序編譯,無論是從一個獨立的JDK或使用Eclipse的編譯器(org.eclipse.jdt.core.JDTCompilerAdapter),我們收到以下錯誤信息:爲什麼我會收到以下錯誤? 「沒有定義類型的唯一bean:期望單個匹配的bean但發現3」

Error creating bean with name 'loginServiceImpl' defined in file [/opt/tomcat/webapps/ROOT##10616/WEB-INF/classes/com/company/ribeye/server/service/LoginServiceImpl.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.security.authentication.AuthenticationManager]: : No unique bean of type [org.springframework.security.authentication.AuthenticationManager] is defined: expected single matching bean but found 3: [org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0, org.springframework.security.authentication.ProviderManager#0, org.springframework.security.authenticationManager]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.security.authentication.AuthenticationManager] is defined: expected single matching bean but found 3: [org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0, org.springframework.security.authentication.ProviderManager#0, org.springframework.security.authenticationManager] 

我們沒有使用任何類型的依賴管理的,但Eclipse似乎處理java編譯沒有問題,我們不會遇到這個錯誤。當我們使用Ant任務和javac進行編譯時,我只想強調這個錯誤。同樣,即使使用Eclipse自己的捆綁編譯器,我們也會遇到問題。我還想補充一點,我不是Java開發人員,但是我是開發團隊的DevOps經理,所以CI服務器和部署策略屬於我的領域。我有一點Java知識,並且仍在學習,所以如果這是非常簡單的事情,我提前道歉。

這裏是我的相關代碼(未列出的所有進口,爲簡潔起見):

package com.company.ribeye.server.service; 


import org.springframework.security.authentication.AuthenticationManager; 
import org.springframework.security.authentication.BadCredentialsException; 
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.SimpleGrantedAuthority; 
import org.springframework.security.core.context.SecurityContextHolder; 
import org.springframework.security.web.context.HttpSessionSecurityContextRepository; 

@Controller 
@RequestMapping("/login") 
public class LoginServiceImpl extends GWTController implements LoginService { 

    private static final long serialVersionUID = 1L; 
    private final AuthenticationManager authenticationManager; 
    private final UserDao userDao; 
    private final UserPreferenceDao userPreferenceDao; 

    @Autowired 
    public LoginServiceImpl(AuthenticationManager authenticationManager, UserDao userDao, UserPreferenceDao userPreferenceDao) { 
     this.authenticationManager = authenticationManager; 
     this.userDao = userDao; 
     this.userPreferenceDao = userPreferenceDao; 
    } 

    @Override 
    public ApplicationData getApplicationData() { 
     ApplicationData ap = new ApplicationData(); 
     SimpleDateFormat df = new SimpleDateFormat("yyyy"); 
     ap.setCurrentYear(Integer.parseInt(df.format(new Date()))); 
     ap.setLoggedIn(false); 

     if (!ServerContext.isProductionServer() && ServerContext.isDevServer()) { 
      Pair<String, String> login = ServerContext.getDevAutoLogin(); 
      ap.setDevModeAutoUsername(login.getA()); 
      ap.setDevModeAutoPassword(login.getB()); 
     } 

     if (ServerContext.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY) == null) { 
      return ap; 
     } 

     User user = ServerContext.getCurrentUser(); 

     if (user == null) { 
      return ap; 
     } 
     ApplicationContext ctx = ServerContext.getApplicationContext(); 

     if (user.isPortalUser()) { 
      CustomerDao customerDao = (CustomerDao) ctx.getBean("customerDaoImpl"); 
      user.setCustomer(customerDao.getById(user.getCustomerId())); 
     } else if (user.isVendorUser()) { 
      VendorDao vendorDao = (VendorDao) ctx.getBean("vendorDaoImpl"); 
      user.setVendor(vendorDao.getById(user.getVendorId())); 
     } 

     ap.setLoggedIn(true); 
     ap.setDashDatabaseConnection(DashDataSourceContextHolder.getDatabaseType()); 
     ap.setBuildNumber(ServerContext.getBuildNumber()); 
     ap.setBuildDate(ServerContext.getBuildDate()); 
     ap.setNextReleaseDate(ServerContext.getNextReleaseDate()); 
     ap.setCurrentUser(user); 
     ap.setUserLinks(userPreferenceDao.getUserLinks(user.getId())); 
     ap.setMyContacts(userPreferenceDao.getMyContacts()); 
     if (!user.isSwitched()) { 
      UserDaoImpl.updateUserActivity(user.getId()); 
     } 
     ap.setUserActivity(UserDaoImpl.getAllUserActivity()); 

     SystemDao systemDao = (SystemDao) ctx.getBean("systemDaoImpl"); 
     ap.setEntityLinkers(systemDao.getEntityLinkers()); 
     PollUpdateData pud = new PollUpdateData(user.getId()); 
     ap.setNotificationSummary(systemDao.getPollData(pud).getNotificationSummary()); 
     ap.setNotificationEntityTypeColors(systemDao.getNotificationEntityTypeColors()); 
     ap.setUserPreferences(userPreferenceDao.getPreferencesByGroupName(user.getId(), null)); 

     ArgMap<FlagArg> flagArgs = new ArgMap<FlagArg>(); 
     flagArgs.put(FlagArg.USER_ID, user.getId()); 
     ap.setFlagDefinitions(Common.asArrayList(userPreferenceDao.getFlagDefinitions(flagArgs))); 

     DocumentDao documentDao = (DocumentDao) ctx.getBean("documentDaoImpl"); 
     ap.setLogoImage(documentDao.getLogoImage()); 

     return ap; 
    } 

這裏是我們的applicationContext-security.xml文件的相關部分:

<authentication-manager alias="authenticationManager"> 
    <authentication-provider ref="ldapAuthProvider" /> 
    <authentication-provider user-service-ref="customUserDetailsService"> 
     <password-encoder ref="passwordEncoder"> 
      <salt-source ref="saltSource" /> 
     </password-encoder> 
    </authentication-provider> 
</authentication-manager> 


<beans:bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider"> 
<beans:constructor-arg> 
    <beans:bean class="org.springframework.security.ldap.authentication.BindAuthenticator"> 
    <beans:constructor-arg ref="contextSource" /> 
    <beans:property name="userSearch"> 
     <beans:bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch"> 
      <beans:constructor-arg index="0" value="" /> 
      <beans:constructor-arg index="1" value="REDACTED" /> 
      <beans:constructor-arg index="2" ref="contextSource" /> 
     </beans:bean> 
    </beans:property> 
    </beans:bean> 
</beans:constructor-arg> 

<beans:constructor-arg> 
    <beans:bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"> 
     <beans:constructor-arg ref="contextSource"/> 
     <beans:constructor-arg value="REDACTED" /> 
     <beans:property name="groupRoleAttribute" value="cn" /> 
     <beans:property name="searchSubtree" value="false" /> 
     <beans:property name="convertToUpperCase" value="true" /> 
     <beans:property name="rolePrefix" value="ROLE_" /> 
     <beans:property name="groupSearchFilter" value="member={0}" /> 
     <beans:property name="defaultRole" value="ROLE_DASH" /> 
    </beans:bean> 
</beans:constructor-arg> 

and dispatcher-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?> 

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:security="http://www.springframework.org/schema/security" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 
     http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

    <context:component-scan base-package="com.company.ribeye.server.service" /> 
    <context:component-scan base-package="com.company.ribeye.server.dao" /> 
    <context:component-scan base-package="com.company.ribeye.server.util" /> 
    <context:annotation-config /> 
    <security:global-method-security pre-post-annotations="enabled" /> 
</beans> 

customUserDetailsS​​ervice,如要求:

package com.company.ribeye.server.spring; 

import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.util.ArrayList; 
import java.util.List; 

import javax.sql.DataSource; 

import org.springframework.dao.DataAccessException; 
import org.springframework.jdbc.core.JdbcTemplate; 
import org.springframework.jdbc.core.RowMapper; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.SimpleGrantedAuthority; 
import org.springframework.security.core.userdetails.User; 
import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.core.userdetails.UsernameNotFoundException; 

public class CustomUserDetailsService implements UserDetailsService { 
    private DataSource dataSource; 
    private JdbcTemplate sjt; 

    public DataSource getDataSource() { 
     return dataSource; 
    } 

    @Override 
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
     RowMapper<User> mapper = new RowMapper<User>() { 
      @Override 
      public User mapRow(ResultSet rs, int rowNum) throws SQLException { 

       return new User(rs.getString("Login"), rs.getString("PasswordDigest"), rs.getBoolean("IsEnabled"), rs.getBoolean("IsEnabled"), true, true, 
         getAuthorities(rs)); 
      } 
     }; 

     User user; 

     String sql = "select top 1 u.ID, u.Login, u.PasswordDigest, u.CustomerID, u.VendorID, u.IsPortalSuperUser, "; 
     sql += "dbo.IsActive(u.StartDate, u.EndDate, getdate()) as IsEnabled from Users u "; 
     sql += "where u.Login = ? and PasswordDigest is not null"; 

     try { 
      user = sjt.queryForObject(sql, mapper, username); 
     } catch (DataAccessException e) { 
      throw new UsernameNotFoundException(username); 
     } 

     return user; 
    } 

    public void setDataSource(DataSource dataSource) { 
     this.dataSource = dataSource; 
     sjt = new JdbcTemplate(dataSource); 
    } 

    private List<GrantedAuthority> getAuthorities(ResultSet rs) throws SQLException { 
     final List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(); 

     if (rs.getInt("VendorID") > 0) { 
      authList.add(new SimpleGrantedAuthority("ROLE_COMPANY_DASH_USERS")); 
      return authList; 
     } 
     authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_USER")); 
     if (rs.getBoolean("IsPortalSuperUser")) { 
      authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_SUPERUSER")); 
      authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_BILLING")); 
      authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_OPERATIONS")); 
      return authList; 
     } 

     // if not a superuser, fetch account-level roles from database 
     RowMapper<List<GrantedAuthority>> mapper = new RowMapper<List<GrantedAuthority>>() { 
      @Override 
      public List<GrantedAuthority> mapRow(ResultSet rs, int rowNum) throws SQLException { 
       if (rs.getInt("Billing") > 0) { 
        authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_BILLING")); 
       } 
       if (rs.getInt("Operations") > 0) { 
        authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_OPERATIONS")); 
       } 

       return authList; 
      } 
     }; 
     String sql = "select sum(cast(Billing as int)) as Billing, sum(cast(Operations as int)) as Operations "; 
     sql += "from PortalUserRoles "; 
     sql += "where UserID = ?"; 
     sjt.queryForObject(sql, mapper, rs.getInt("ID")); 

     return authList; 
    } 
} 
+0

,您可以複製CustomUserDetailsS​​ervice? – RanPaul 2014-10-10 20:56:09

+0

已添加CustomUserDetailsS​​ervice。 :) – LegendaryDude 2014-10-10 21:00:04

+0

您的LoginServiceImpl似乎是一個控制器,並且它沒有@Controller註釋 – RanPaul 2014-10-11 00:01:28

回答

1

一番搜索後,我能找到解決辦法,有人在#spring(freenode上)給了我。我仍然不知道爲什麼這不是Eclipse內部的問題,但至少現在它正在工作。

雖然我不能在我們的應用程序,其中正在創建的另外兩個豆類發現,加入@Qualifier("authenticationManager")註釋LoginServiceImpl解決了這個問題:

@Autowired 
    public LoginServiceImpl(@Qualifier("authenticationManager") AuthenticationManager authenticationManager, UserDao userDao, 
      UserPreferenceDao userPreferenceDao) { 
     this.authenticationManager = authenticationManager; 
     this.userDao = userDao; 
     this.userPreferenceDao = userPreferenceDao; 
    } 
相關問題