Search code examples
javaspringsap-commerce-cloudremember-me

Context initialization failed. Spring error NoSuchMethodException


I obtain this error when I try to launch Hybris platform at runtime:

WARN  [localhost-startStop-1] [TenantIgnoreXmlWebApplicationContext] Exception encountered during context initialization - cancelling refresh at
tempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'checkoutController': Injection of resource depend
encies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'autoLoginStrategy' de
fined in ServletContext resource [/WEB-INF/config/common-spring-security-config.xml]: Cannot resolve reference to bean 'rememberMeServices' whil
e setting bean property 'rememberMeServices'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean w
ith name 'defaultRememberMeServices' defined in ServletContext resource [/WEB-INF/config/common-spring-security-config.xml]: Instantiation of be
an failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.sap.hybris.fs.storefront.securit
y.AcceleratorRememberMeServices]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.sap.hybris.fs.storefron
t.security.AcceleratorRememberMeServices.<init>()

The AcceleratorRememberMeServices class is this:

 /*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2015 hybris AG
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of hybris
 * ("Confidential Information"). You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the
 * license agreement you entered into with hybris.
 *
 *
 */
package com.sap.hybris.fs.storefront.security;

import de.hybris.platform.acceleratorservices.urlencoder.UrlEncoderService;
import de.hybris.platform.acceleratorstorefrontcommons.constants.WebConstants;
import de.hybris.platform.commercefacades.customer.CustomerFacade;
import de.hybris.platform.commercefacades.storesession.StoreSessionFacade;
import de.hybris.platform.commerceservices.security.SecureTokenService;
import de.hybris.platform.commerceservices.strategies.CheckoutCustomerStrategy;
import de.hybris.platform.servicelayer.i18n.CommonI18NService;
import de.hybris.platform.servicelayer.user.UserService;
import com.sap.hybris.fs.storefront.web.wrappers.RemoveEncodingHttpServletRequestWrapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;


public class AcceleratorRememberMeServices extends TokenBasedRememberMeServices
{
    public AcceleratorRememberMeServices(String key, UserDetailsService userDetailsService) {
        super(key, userDetailsService);
        // YTODO Auto-generated constructor stub
    }

    private UserService userService;
    private CustomerFacade customerFacade;
    private CheckoutCustomerStrategy checkoutCustomerStrategy;
    private StoreSessionFacade storeSessionFacade;
    private CommonI18NService commonI18NService;
    private UrlEncoderService urlEncoderService;
    private SecureTokenService secureTokenService;

    @Override
    protected void setCookie(final String[] tokens, final int maxAge, final HttpServletRequest request,
                             final HttpServletResponse response)
    {
        if (!getCheckoutCustomerStrategy().isAnonymousCheckout())
        {
            super.setCookie(tokens, maxAge, new RemoveEncodingHttpServletRequestWrapper(request, getUrlEncodingPattern(request)),
                    response);
        }
    }

    @Override
    public void logout(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication)
    {
        super.logout(new RemoveEncodingHttpServletRequestWrapper(request, getUrlEncodingPattern(request)), response, authentication);
    }

    @Override
    protected Authentication createSuccessfulAuthentication(final HttpServletRequest request, final UserDetails user)
    {
        getUserService().setCurrentUser(getUserService().getUserForUID(user.getUsername()));

        if (StringUtils.isNotEmpty(getUrlEncoderService().getUrlEncodingPattern()))
        {
            getCustomerFacade().rememberMeLoginSuccessWithUrlEncoding(getUrlEncoderService().isLanguageEncodingEnabled(),
                    getUrlEncoderService().isCurrencyEncodingEnabled());
        }
        else
        {
            getCustomerFacade().loginSuccess();
        }
        final RememberMeAuthenticationToken auth = new RememberMeAuthenticationToken(getKey(), user, user.getAuthorities());
        auth.setDetails(getAuthenticationDetailsSource().buildDetails(request));
        return auth;
    }

    @Override
    protected String retrievePassword(final Authentication authentication)
    {
        return getUserService().getUserForUID(authentication.getPrincipal().toString()).getEncodedPassword();
    }

    protected String getUrlEncodingPattern(final HttpServletRequest request)
    {
        final String encodingAttributes = (String) request.getAttribute(WebConstants.URL_ENCODING_ATTRIBUTES);
        return StringUtils.defaultString(encodingAttributes);
    }

    protected UserService getUserService()
    {
        return userService;
    }

    @Required
    public void setUserService(final UserService userService)
    {
        this.userService = userService;
    }

    protected CustomerFacade getCustomerFacade()
    {
        return customerFacade;
    }

    @Required
    public void setCustomerFacade(final CustomerFacade customerFacade)
    {
        this.customerFacade = customerFacade;
    }

    protected CheckoutCustomerStrategy getCheckoutCustomerStrategy()
    {
        return checkoutCustomerStrategy;
    }

    @Required
    public void setCheckoutCustomerStrategy(final CheckoutCustomerStrategy checkoutCustomerStrategy)
    {
        this.checkoutCustomerStrategy = checkoutCustomerStrategy;
    }

    protected UrlEncoderService getUrlEncoderService()
    {
        return urlEncoderService;
    }

    @Required
    public void setUrlEncoderService(final UrlEncoderService urlEncoderService)
    {
        this.urlEncoderService = urlEncoderService;
    }


    protected StoreSessionFacade getStoreSessionFacade()
    {
        return storeSessionFacade;
    }

    @Required
    public void setStoreSessionFacade(final StoreSessionFacade storeSessionFacade)
    {
        this.storeSessionFacade = storeSessionFacade;
    }

    protected CommonI18NService getCommonI18NService()
    {
        return commonI18NService;
    }

    @Required
    public void setCommonI18NService(final CommonI18NService commonI18NService)
    {
        this.commonI18NService = commonI18NService;
    }

    protected SecureTokenService getSecureTokenService()
    {
        return secureTokenService;
    }

    @Required
    public void setSecureTokenService(final SecureTokenService secureTokenService)
    {
        this.secureTokenService = secureTokenService;
    }
}

The bean is declared in this way:

<alias name="defaultRememberMeServices" alias="rememberMeServices"/>
    <bean id="defaultRememberMeServices" class="com.sap.hybris.fs.storefront.security.AcceleratorRememberMeServices" >
        <property name="userDetailsService" ref="originalUidUserDetailsService" />
        <property name="key" value="fsstorefront" />
        <property name="cookieName" value="fsstorefrontRememberMe" />
        <property name="alwaysRemember" value="true" />
        <property name="userService" ref="userService"/>
        <property name="useSecureCookie" value="false"/>
        <property name="customerFacade" ref="customerFacade"/>
        <property name="checkoutCustomerStrategy" ref="checkoutCustomerStrategy"/>
        <property name="urlEncoderService" ref="urlEncoderService"/>
        <property name="storeSessionFacade" ref="storeSessionFacade"/>
        <property name="commonI18NService" ref="commonI18NService"/>
        <property name="secureTokenService" ref="secureTokenService"/>
    </bean>

There's something wrong in the constructor method? Or is a problem of the Spring configuration? Thank you for the precious help to anyone.


Solution

  • It is looking for the default constructor, hence the <init>(). You need to either create a default constructor, or utilize constructor arguments when you declare the bean.

    In this case, since you are extending the existing TokenBasedRememberMeServices class, you will need to declare the bean with the relevant constructor arguments (key, userDefaultsService) instead of injecting them as properties. Your declaration should look something like this:

    <bean id="defaultRememberMeServices" class="com.sap.hybris.fs.storefront.security.AcceleratorRememberMeServices" >
        <!-- constructor arguments -->
        <constructor-arg index="0" value="fsstorefront"/>
        <constructor-arg index="1" ref="originalUidUserDetailsService" />
    
        <!-- rest of the properties -->
        <property name="cookieName" value="fsstorefrontRememberMe" />
        <property name="alwaysRemember" value="true" />
        <property name="userService" ref="userService"/>
        <property name="useSecureCookie" value="false"/>
        <property name="customerFacade" ref="customerFacade"/>
        <property name="checkoutCustomerStrategy" ref="checkoutCustomerStrategy"/>
        <property name="urlEncoderService" ref="urlEncoderService"/>
        <property name="storeSessionFacade" ref="storeSessionFacade"/>
        <property name="commonI18NService" ref="commonI18NService"/>
        <property name="secureTokenService" ref="secureTokenService"/>
    </bean>
    

    See more about constructor argument injection and Spring dependency injection in general here