1

In my code below, mongoURI initially pulls the correct URI string from application.properties, and connects to the database successfully. However, once I make a call to getUserByAuth0ID, I'm getting a "java.net.UnknownHostException: null: Name or service not known" error and debug statements show that mongoURI is now set to null.

What's going on? Nowhere in my code do I touch the value of mongoURI. My previous version of the code has mongoURI hardcoded as a variable and it runs with no issues.

@Service
public class DBConnectService {
    private static MongoCollection<User> users;
    private static Logger logger = LogManager.getLogger(DBConnectService.class);

    @Value("${package.mongoURI}")
    private String mongoURI;
    
    /**     Opens a connection to mongodb for the length of the program operation        */
    @PostConstruct
    public void init() {
        logger.info("Connecting to MongoDB");
        try {
            System.out.println (mongoURI);  // URI prints out correctly here
            CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
            CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);
            MongoClientSettings clientSettings = MongoClientSettings.builder()
                    .applyConnectionString(new ConnectionString(mongoURI))
                    .codecRegistry(codecRegistry)
                    .build();
            
            MongoClient mongoClient = MongoClients.create(clientSettings);
            MongoDatabase database = mongoClient.getDatabase("db");
            users = database.getCollection("users", User.class);
        } catch(Exception e) {
            logger.error("MongoDB connection failure:\n" + e);
        }
    }

    public User getUserByAuth0ID (String authID) {
        System.out.println (mongoURI);  // URI prints out here as null
        User user = getUser(authID, "auth0ID");
        if (user == null) {
            user = createUserAccount(authID);
        }
        return user;
    }

    public static User getUser (String info, String field) {
        User user = users.find(eq(field, info)).first();
        return user; 
    }

    public static User createUserAccount (String authID) {
        JsonObject newUserInfo = Auth0Service.getUserInfo(authID);
        
        if (newUserInfo.get("email_verified").getAsBoolean()) {
            
            User newUser = new User()
                    .setEmail(newUserInfo.get("email").getAsString())
                    .setName(newUserInfo.get("name").getAsString())
                    .setAuth0ID(authID);
            
            users.insertOne(newUser);
            
            return newUser;
        } else {
            logger.info ("Email NOT verified");
            
            return null;
        }
    }

Application.properties line:

#       --- MongoDB ---
package.mongoURI = mongodb+srv://admin:secretURL/?retryWrites=true&w=majority

rando
  • 13
  • 4
  • Can you show your `application.properties` where `mongoURI` is defined. – Ashish Patil Jul 14 '22 at 12:20
  • Editing it into the question – rando Jul 14 '22 at 12:33
  • `nornir.mongoURI ` is this name you used in application properties? – Ashish Patil Jul 14 '22 at 12:36
  • Err. More of me forgetting to edit the name before posting. I can confirm that it's pulling the correct variable from application.properties the first time – rando Jul 14 '22 at 12:39
  • Is there a reason you don't use "Spring Data MongoDB" and instead configure the Mongo DB client yourself? – jhueg Jul 14 '22 at 12:53
  • Also `getUserByAuth0ID` shows no code with interaction with mongo client. Please add the code for `getUser` and `createUserAccount` also – jhueg Jul 14 '22 at 12:54
  • Um not really. I'm new to mongoDB and this was what their guide said to do – rando Jul 14 '22 at 12:57
  • Does this answer your question? [java - Spring @Value annotation returns null](https://stackoverflow.com/questions/36534059/java-spring-value-annotation-returns-null) – Ashish Patil Jul 14 '22 at 13:02
  • @AshishPatil it does not, that's due to '@value' not working with static variable which I'm not using. – rando Jul 14 '22 at 13:07
  • @jhueg I've added the code to the question – rando Jul 14 '22 at 13:07
  • ok sure, will check , i have deleted my original answer as it doesn't validate your question – Ashish Patil Jul 14 '22 at 13:10
  • @rando then I would really recommend to use "Spring Data MongoDB" an let spring do all the configuration for you and use the handy "repository" it offers (they are aweseome). It is much less error prone. See a tutorial for it here: https://www.baeldung.com/spring-data-mongodb-tutorial – jhueg Jul 14 '22 at 13:15
  • @rando, i have added my additional answer which I think is the case – Ashish Patil Jul 14 '22 at 13:18

1 Answers1

0

Your @Value annotation has incorrect details of mongoURI.Either use @Value("${nornir.mongoURI}") or change to package.mongoURI inside application.properties.

Edit: It is more likely you are calling getUserByAuth0ID manually something like --

DBConnectService service = new DBConnectService();
service.getUserByAuth0ID();

Because if mongoURI is coming as null, it means, this method getUserByAuth0ID is not getting called via spring way, i.e. by autowiring DBConnectService & then accessing this method; but rather it is getting called manually i.e. by manually creating object of DBConnectService.

If this is case, then it is obvious that your normal java object don't know about @Value annotation & hence it is not setting any value.

@PostConstruct will always works as it will get executed at startup when bean is getting created & hence @Value is working properly there.

To fix this issue, make sure you have spring bean of DBConnectService & you are accessing getUserByAuth0ID via that bean.

Edit 2 : --

Basic pseudo about how to use this in your calling class :

@Autowired
DBConnectService service;


public void yourdbMethod(){
 service.getUserByAuth0ID();
}
Ashish Patil
  • 4,428
  • 1
  • 15
  • 36
  • Hi, that's my bad, I forgot to anonymise my application.properties before posting it. To reiterate, I am definitely pulling the info correctly from application.properties the first time, I've checked the value of mongoURI when the database connection is first opened. – rando Jul 14 '22 at 12:44
  • @rando : you haven't shown how you are defining your mongo uri during bootstrapping of your spring application. Can you confirm that is correct details? Because if its `null` in service, then it is not correct details. – Ashish Patil Jul 14 '22 at 12:46
  • Yes, it's hardcoded. Again, the database is connecting correcly at startup. – rando Jul 14 '22 at 12:48
  • Well, if you have hardcoded it for startup, can you use same hardcoding string here in service? or even just print string in console, based on url, there must be some differences how you are using your url – Ashish Patil Jul 14 '22 at 12:49
  • Basically, a println statement in my DB connection code shows the URI correctly. However, a println statement in my method below shows a value of null for the URI – rando Jul 14 '22 at 12:50
  • that's why I am telling, use direct hardcoded uri in service as well. This error is because of mismatch of `application.properties` .. You can try using same `@Value` annotation in startup to check if `null` is coming there as well. if it is, then you have to use whatever I suggested in my answer. – Ashish Patil Jul 14 '22 at 12:53
  • I am not using direct hardcoded URI because it would contain mongodb login info, which is a security risk. I HAVE checked that @value is working in startup, I've mentioned that several times. The value is getting set correctly at startup, before being nulled somehow – rando Jul 14 '22 at 12:59
  • Your edited answer sounds like it's right. I did not realise a new instance of DBConnect would not get the value injected into it. I'm new to Spring - how would I implement the solution that you suggested? – rando Jul 14 '22 at 13:26
  • Can you upvote & accept answer in meanwhile as it resolve your original query. – Ashish Patil Jul 14 '22 at 13:27
  • I don't have enough rep to upvote, but I've accepted the answer. – rando Jul 14 '22 at 13:28
  • just shared some sample code how you should use this in your calling class & method. You have to annotate your DBService with `Autowired` annotation & then you can use this method. thanks for accepting answer. you can also upvote may be after sometime if this is your first question. – Ashish Patil Jul 14 '22 at 13:33
  • @rando, if you have any further question, let me know, will have a look. – Ashish Patil Jul 14 '22 at 13:34