Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

java.lang.IllegalStateException

I have a spring boot project in which I am trying to integrate Firestore.

Firebase.config:

package spring.framework._2fa_application.config;


import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.firestore.Firestore;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.cloud.FirestoreClient;
import org.springframework.cloud.gcp.data.firestore.repository.config.EnableReactiveFirestoreRepositories;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.FileInputStream;
import java.io.IOException;

@Configuration
@EnableReactiveFirestoreRepositories(basePackages = "spring.framework._2fa_application.totp.codeOTP")
public class FirebaseConfig {
@Bean
public void firebaseApp() {
try{
FileInputStream serviceAccount = new FileInputStream("./ConnectionString.json");

FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.build();

FirebaseApp.initializeApp(options);

Firestore db = FirestoreClient.getFirestore();

}catch(IOException e)
{
throw new RuntimeException("Could not initialize Firebase Admin SDK: " + e.getMessage());
}
}
}




CodeRepository:

package spring.framework._2fa_application.totp.codeOTP;

import org.springframework.cloud.gcp.data.firestore.FirestoreReactiveRepository;
import reactor.core.publisher.Flux;

public interface CodeRepository extends FirestoreReactiveRepository<CodeData> {
}


CodeGeneratorServiceImpl:

package spring.framework._2fa_application.totp.codeOTP;

import lombok.RequiredArgsConstructor;
import org.springframework.cloud.gcp.data.firestore.FirestoreTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;


@Service
@RequiredArgsConstructor
public final class CodeGeneratorServiceImpl implements CodeGeneratorService {

private final CodeRepository codeRepository;
private final CodeMapper codeMapper;

private final int[] DIGITS_POWER = {1,10,100,1000,10000,100000,1000000,10000000,100000000};

// functie inspirata din RFC6238
private Mono<byte[]> hmacFunction(AlgorithmHash algorithm, byte[] keyValue, byte[] text)
{
return Mono.defer(() -> {
try{
Mac hmac = Mac.getInstance(algorithm.toString());
SecretKeySpec macKey = new SecretKeySpec(keyValue, "RAW");
hmac.init(macKey);
return Mono.just(hmac.doFinal(text));
}
catch(NoSuchAlgorithmException | InvalidKeyException exp){
return Mono.error(exp); // trateaza exceptia si o propaga ca eroare Mono
}
});
}


// functie luata din RFC6238
private Mono<byte[]> hexStr2Bytes(String hex){

return Mono.fromCallable(() -> {
// Adaugam 10 la inceputul sirului pentru a asigura ca valoarea este interpretata ca fiind pozitiva, deoarece BigInteger asteapta o valoarea
// pozitiva pentru valoarea hexa
byte[] bArray = new BigInteger("10" + hex, 16).toByteArray();
// eliminam octetul de semn
byte[] ret = new byte[bArray.length - 1];
for (int i = 0; i < ret.length; i++)
ret[i] = bArray[i + 1];
return ret;
});
}


// functie inspirata din RFC6238
@Override
public Flux<String> generateCode(String keyHex, final String time) {

return codeRepository.findAll()
.map(codeMapper::codeDataToCodeDataDto)
.flatMap(codeDataDTO -> {
String algorithm = codeDataDTO.getAlgorithm();
int numberOfDigitsCode = codeDataDTO.getNrDigits();

return Mono.defer(() -> {
String modifierTime = time;
while (modifierTime.length() < 16) {
modifierTime = "0" + modifierTime;
}

return hexStr2Bytes(modifierTime)
.flatMap(timeText -> hexStr2Bytes(keyHex)
.flatMap(key -> hmacFunction(AlgorithmHash.valueOf(algorithm), key, timeText)
.map(hash -> {
// alegere bytes pe care o sa ii punem in TOTP code

int offset = hash[hash.length - 1] & 0xF;
int binary =
((hash[offset] & 0x7f) << 24) |
((hash[offset + 1] & 0xff) << 16) |
((hash[offset + 2] & 0xff) << 8) |
(hash[offset + 3] & 0xff);

int otp = binary % DIGITS_POWER[numberOfDigitsCode];

String result = Integer.toString(otp);
while (result.length() < numberOfDigitsCode) {
result = "0" + result;
}

return result;
})
.onErrorMap(error -> new Exception(error.getMessage()))
)
);
});
});
}
}

And it keeps giving me the same error no matter what I do:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in spring.framework._2fa_application.totp.codeOTP.CodeGeneratorServiceImpl required a bean named 'firestoreTemplate' that could not be found.


Action:

Consider defining a bean named 'firestoreTemplate' in your configuration.

Solved Solved
0 9 4,780
3 ACCEPTED SOLUTIONS

The error message indicates that the CodeGeneratorServiceImpl constructor is asking for a bean named firestoreTemplate, but Spring Boot cannot find a bean with that name in the application context. To resolve this issue, you need to create a bean of type FirestoreTemplate and add it to the application context.

You can do this by adding the following code to your FirebaseConfig class:

@Configuration
@EnableReactiveFirestoreRepositories(basePackages = "spring.framework._2fa_application.totp.codeOTP")
public class FirebaseConfig {

    @Bean
    public FirebaseApp initializeFirebaseApp() throws IOException {
        FileInputStream serviceAccount = new FileInputStream("./ConnectionString.json");

        FirebaseOptions options = new FirebaseOptions.Builder()
                .setCredentials(GoogleCredentials.fromStream(serviceAccount))
                .build();
return FirebaseApp.initializeApp(options);
    }

    @Bean
    public Firestore firestore(FirebaseApp firebaseApp) {
        return FirestoreClient.getFirestore(firebaseApp);
    }

    @Bean
    public FirestoreTemplate firestoreTemplate(Firestore firestore) {
        return new FirestoreTemplate(firestore);
    }
}

This code will create a
FirestoreTemplate bean and inject the Firestore instance that you created in the firebaseApp() method. The CodeGeneratorServiceImpl will then be able to use this bean to interact with Firestore.
 

View solution in original post

Hi @Bianca12334 ,

Just to clarify 

The FirestoreTemplate constructor requires a Firestore instance, not a FirestoreStub. The Firestore instance is responsible for communicating with the Cloud Firestore backend. The FirestoreStub is used for testing purposes and is not required for production applications.

The firestoreTemplate() function should only receive one argument, which is the Firestore instance. Here's the corrected code:

 

import com.google.cloud.bigtable.data.v2.BigtableDataClient;
import com.google.cloud.bigtable.data.v2.models.Filters;
import com.google.cloud.bigtable.data.v2.models.Query;
import com.google.cloud.bigtable.data.v2.models.Row;
import com.google.api.gax.rpc.ServerStream;

public class BigtableReadWithFilters {

  public static void main(String[] args) {

    // Initialize the Bigtable data client
    try (BigtableDataClient dataClient = BigtableDataClient.create("your-project-id", "your-instance-id")) {

      // Create a query with filters
      Query query = Query.create("mobile-time-series")
          .filter(Filters.FILTERS.chain()
              .filter(Filters.FILTERS.qualifier().exactMatch("data_plan_05gb"))
              .filter(Filters.FILTERS.value().exactMatch("true"))
              .filter(Filters.FILTERS.qualifier().exactMatch("connected_wifi"))
              .filter(Filters.FILTERS.value().exactMatch("1"))
              .filter(Filters.FILTERS.qualifier().exactMatch("connected_cell"))
              .filter(Filters.FILTERS.value().exactMatch("0"))
          );

      // Read rows using the query
      ServerStream<Row> rows = dataClient.readRows(query);

      for (Row row : rows) {
        // Process each row
        // ...
      }
    } catch (Exception e) {
      // Handle exception
    }
  }
}

View solution in original post

It seems you're encountering several issues with the configuration of FirestoreTemplate in a Spring Boot application. Let's address them step by step:

  1. FirestoreClassMapper: You're correct that FirestoreClassMapper is an abstract class and cannot be instantiated directly. However, you typically do not need to provide your own implementation. Spring Boot's auto-configuration should provide a default implementation for you when you include the spring-cloud-gcp-starter-data-firestore starter dependency. If you need to customize the behavior, you would extend it and provide your custom implementation.

  2. TransportChannel to Channel: If you need to manually create a FirestoreGrpc.FirestoreStub, you would typically get a Channel from the FirestoreOptions, not a TransportChannel. However, this is usually unnecessary because the spring-cloud-gcp-starter-data-firestore starter should auto-configure this for you.

  3. UnsatisfiedDependencyException: This exception indicates that Spring Boot's auto-configuration is not kicking in as expected. This could be due to several reasons, such as missing annotations, incorrect package structure, or incompatible versions of dependencies.

Here are some steps to troubleshoot and resolve the issue:

  • Check your configuration: Ensure that your main application class is annotated with @SpringBootApplication and is in the root package above your other packages. Spring Boot's auto-configuration scans the packages below your main application class.

  • Check your annotations: Ensure that your configuration class is annotated with @Configuration and that you have @EnableReactiveFirestoreRepositories pointing to the correct base package where your repositories are located.

  • Check FirestoreTemplate bean: If you have a custom configuration class for Firestore, make sure you're not trying to manually configure FirestoreTemplate unless you have a specific reason to do so. The starter should auto-configure it for you.

  • Check your Maven dependencies: Ensure that you have the correct and compatible versions of spring-cloud-gcp-starter-data-firestore and google-cloud-firestore. You might want to start with a known set of compatible versions from a guide or example project.

  • Clean and rebuild: Sometimes, Maven dependencies can get out of sync. Make sure to clean your project and rebuild it. You can use mvn clean install to do this.

  • Check for beans: Use the /actuator/beans endpoint to check which beans are being created by Spring Boot. If firestoreTemplate is not there, it means it's not being auto-configured as expected.

  • Check the logs: Spring Boot usually logs auto-configuration issues at startup. Check the logs for any warnings or errors related to Firestore configuration.

View solution in original post

9 REPLIES 9

The error message indicates that the CodeGeneratorServiceImpl constructor is asking for a bean named firestoreTemplate, but Spring Boot cannot find a bean with that name in the application context. To resolve this issue, you need to create a bean of type FirestoreTemplate and add it to the application context.

You can do this by adding the following code to your FirebaseConfig class:

@Configuration
@EnableReactiveFirestoreRepositories(basePackages = "spring.framework._2fa_application.totp.codeOTP")
public class FirebaseConfig {

    @Bean
    public FirebaseApp initializeFirebaseApp() throws IOException {
        FileInputStream serviceAccount = new FileInputStream("./ConnectionString.json");

        FirebaseOptions options = new FirebaseOptions.Builder()
                .setCredentials(GoogleCredentials.fromStream(serviceAccount))
                .build();
return FirebaseApp.initializeApp(options);
    }

    @Bean
    public Firestore firestore(FirebaseApp firebaseApp) {
        return FirestoreClient.getFirestore(firebaseApp);
    }

    @Bean
    public FirestoreTemplate firestoreTemplate(Firestore firestore) {
        return new FirestoreTemplate(firestore);
    }
}

This code will create a
FirestoreTemplate bean and inject the Firestore instance that you created in the firebaseApp() method. The CodeGeneratorServiceImpl will then be able to use this bean to interact with Firestore.
 

The firestoreTemplate function asks me for a FirestoreStub. I tried with several versions for the google-cloud-firestore dependency and I can't find any function that returns me a FirestoreStub from a Firestore.Plus my firestoreTemplate function must receive 4 arguments.

Hi @Bianca12334 ,

Just to clarify 

The FirestoreTemplate constructor requires a Firestore instance, not a FirestoreStub. The Firestore instance is responsible for communicating with the Cloud Firestore backend. The FirestoreStub is used for testing purposes and is not required for production applications.

The firestoreTemplate() function should only receive one argument, which is the Firestore instance. Here's the corrected code:

 

import com.google.cloud.bigtable.data.v2.BigtableDataClient;
import com.google.cloud.bigtable.data.v2.models.Filters;
import com.google.cloud.bigtable.data.v2.models.Query;
import com.google.cloud.bigtable.data.v2.models.Row;
import com.google.api.gax.rpc.ServerStream;

public class BigtableReadWithFilters {

  public static void main(String[] args) {

    // Initialize the Bigtable data client
    try (BigtableDataClient dataClient = BigtableDataClient.create("your-project-id", "your-instance-id")) {

      // Create a query with filters
      Query query = Query.create("mobile-time-series")
          .filter(Filters.FILTERS.chain()
              .filter(Filters.FILTERS.qualifier().exactMatch("data_plan_05gb"))
              .filter(Filters.FILTERS.value().exactMatch("true"))
              .filter(Filters.FILTERS.qualifier().exactMatch("connected_wifi"))
              .filter(Filters.FILTERS.value().exactMatch("1"))
              .filter(Filters.FILTERS.qualifier().exactMatch("connected_cell"))
              .filter(Filters.FILTERS.value().exactMatch("0"))
          );

      // Read rows using the query
      ServerStream<Row> rows = dataClient.readRows(query);

      for (Row row : rows) {
        // Process each row
        // ...
      }
    } catch (Exception e) {
      // Handle exception
    }
  }
}

I understand, thank you!

I now understand why I should use a Firestore instead of a FirestoreStub, but I can't get rid of this error: 

java: constructor FirestoreTemplate in class com.google.cloud.spring.data.firestore.FirestoreTemplate cannot be applied to given types;
required: com.google.firestore.v1.FirestoreGrpc.FirestoreStub,java.lang.String,com.google.cloud.spring.data.firestore.mapping.FirestoreClassMapper,com.google.cloud.spring.data.firestore.mapping.FirestoreMappingContext
found: com.google.cloud.firestore.Firestore
reason: actual and formal argument lists differ in length

I thought that maybe it is a problem related to the added dependencies:

<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-firestore</artifactId>
<version>3.13.2</version>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-dependencies</artifactId>
<version>4.8.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-admin</artifactId>
<version>9.1.1</version>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-data-firestore</artifactId>
<version>4.5.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.0</version>
</dependency>

but I couldn't find where the problem would be, it keeps asking me in the FirestoreTemplate constructor for a FirestoreStub instead of Firestore

The error message you're seeing indicates that the constructor for FirestoreTemplate is expecting an instance of FirestoreGrpc.FirestoreStub but you're trying to pass an instance of Firestore. These are two different classes from two different client libraries for Firestore.

FirestoreGrpc.FirestoreStub is part of the lower-level auto-generated gRPC client for Firestore, which is used for asynchronous communication with Firestore. On the other hand, Firestore is part of the higher-level Google Cloud Firestore client library, which provides a more user-friendly interface for interacting with Firestore.

The FirestoreTemplate class is part of the Spring integration for Firestore (spring-cloud-gcp-starter-data-firestore), and it seems like it's expecting the gRPC stub, not the higher-level Firestore class.

Here's what you need to do to resolve the error:

  1. Ensure that you are using the correct Firestore client in your code. If you're using Spring's FirestoreTemplate, you should be using the gRPC stub (FirestoreGrpc.FirestoreStub).

  2. If you're not explicitly creating a FirestoreTemplate in your code, Spring might be trying to auto-configure one for you. In that case, make sure that you have the correct Spring Cloud GCP Firestore starter dependency in your pom.xml.

  3. Check the versions of your dependencies. There might be a version mismatch between spring-cloud-gcp-starter-data-firestore and google-cloud-firestore. Make sure that the versions are compatible.

  4. If you're manually creating a FirestoreTemplate, you'll need to construct a FirestoreGrpc.FirestoreStub and pass it to the constructor along with the other required arguments.

Here's an example of how you might create a FirestoreTemplate:

 

import com.google.cloud.firestore.FirestoreOptions;
import com.google.cloud.spring.data.firestore.FirestoreTemplate;
import com.google.cloud.spring.data.firestore.mapping.FirestoreClassMapper;
import com.google.cloud.spring.data.firestore.mapping.FirestoreMappingContext;
import com.google.firestore.v1.FirestoreGrpc;

// ...

FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance();
FirestoreGrpc.FirestoreStub firestoreStub = FirestoreGrpc.newStub(firestoreOptions.getTransportChannelProvider().getTransportChannel());

FirestoreMappingContext mappingContext = new FirestoreMappingContext();
FirestoreClassMapper classMapper = new FirestoreClassMapper();

FirestoreTemplate firestoreTemplate = new FirestoreTemplate(firestoreStub, "your-project-id", classMapper, mappingContext);

FirestoreClassMapper is an abstract class and cannot be instantiated. But I still have to implement FirestoreClassMapper? I couldn't let it use the default class for something like that or I have to override the methods with reactive operations? And there is another problem: firestoreOptions.getTransportChannelProvider().getTransportChannel() returns a TransportChannel and I need a Channel. It is not very clear to me why I have to implement this functionality of firestoreTemplate(), I thought there was a bean behind for this class, but I keep getting the error: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'codeGeneratorServiceImpl' defined in file [D:\Licenta-Practic-2FA\_2FA_application\target\classes\spring\framework\_2fa_application\totp\codeOTP\CodeGeneratorServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'codeRepository' defined in spring.framework._2fa_application.totp.codeOTP.CodeRepository defined in @EnableReactiveFirestoreRepositories declared on FirebaseConfig: Cannot resolve reference to bean 'firestoreTemplate' while setting bean property 'firestoreTemplate'
I also looked at the maven dependencies and 2 libraries were not compatible, but I think I have solved the problem and still I can't get rid of this problem and I can't even build this firestoreTemplate bean and not give me errors of types used or insufficient parameters and so on, I'm not sure I understand some things.

It seems you're encountering several issues with the configuration of FirestoreTemplate in a Spring Boot application. Let's address them step by step:

  1. FirestoreClassMapper: You're correct that FirestoreClassMapper is an abstract class and cannot be instantiated directly. However, you typically do not need to provide your own implementation. Spring Boot's auto-configuration should provide a default implementation for you when you include the spring-cloud-gcp-starter-data-firestore starter dependency. If you need to customize the behavior, you would extend it and provide your custom implementation.

  2. TransportChannel to Channel: If you need to manually create a FirestoreGrpc.FirestoreStub, you would typically get a Channel from the FirestoreOptions, not a TransportChannel. However, this is usually unnecessary because the spring-cloud-gcp-starter-data-firestore starter should auto-configure this for you.

  3. UnsatisfiedDependencyException: This exception indicates that Spring Boot's auto-configuration is not kicking in as expected. This could be due to several reasons, such as missing annotations, incorrect package structure, or incompatible versions of dependencies.

Here are some steps to troubleshoot and resolve the issue:

  • Check your configuration: Ensure that your main application class is annotated with @SpringBootApplication and is in the root package above your other packages. Spring Boot's auto-configuration scans the packages below your main application class.

  • Check your annotations: Ensure that your configuration class is annotated with @Configuration and that you have @EnableReactiveFirestoreRepositories pointing to the correct base package where your repositories are located.

  • Check FirestoreTemplate bean: If you have a custom configuration class for Firestore, make sure you're not trying to manually configure FirestoreTemplate unless you have a specific reason to do so. The starter should auto-configure it for you.

  • Check your Maven dependencies: Ensure that you have the correct and compatible versions of spring-cloud-gcp-starter-data-firestore and google-cloud-firestore. You might want to start with a known set of compatible versions from a guide or example project.

  • Clean and rebuild: Sometimes, Maven dependencies can get out of sync. Make sure to clean your project and rebuild it. You can use mvn clean install to do this.

  • Check for beans: Use the /actuator/beans endpoint to check which beans are being created by Spring Boot. If firestoreTemplate is not there, it means it's not being auto-configured as expected.

  • Check the logs: Spring Boot usually logs auto-configuration issues at startup. Check the logs for any warnings or errors related to Firestore configuration.

I solved the problem, it seems that there was no need to configure a FirestoreTemplate, I had to add dependencies in maven: <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
and put in application.properties: management.endpoints.web.exposure.include=beans and it worked. Thank you very much for your help, I wouldn't have realized it if you hadn't told me!