NullPoointerException when running the application

68 views
Skip to first unread message

Dondell Batac

unread,
Aug 5, 2021, 7:34:19 PM8/5/21
to dropwizard-user
I have issue when running the application.

I don't have clue which causes this issue.

java.lang.NullPointerException
    at java.base/java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)
    at java.base/java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1006)
    at java.base/java.util.Properties.put(Properties.java:1334)
    at java.base/java.util.Properties.setProperty(Properties.java:229)
    at io.dropwizard.db.DataSourceFactory.build(DataSourceFactory.java:872)
    at io.dropwizard.hibernate.SessionFactoryFactory.build(SessionFactoryFactory.java:40)
    at io.dropwizard.hibernate.HibernateBundle.run(HibernateBundle.java:74)
    at io.dropwizard.setup.Bootstrap.run(Bootstrap.java:183)
    at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:43)
    at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:87)
    at io.dropwizard.cli.Cli.run(Cli.java:79)
    at io.dropwizard.Application.run(Application.java:94)
    at com.fulcrumgt.tardis.TardisApplication.main(TardisApplication.java:87)

Ryan Kennedy

unread,
Aug 5, 2021, 8:48:20 PM8/5/21
to dropwiz...@googlegroups.com
If I had to guess, some piece of configuration passed to your hibernate bundle has a null value in it:

Ryan

--
You received this message because you are subscribed to the Google Groups "dropwizard-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dropwizard-us...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dropwizard-user/f21b8bac-a2fb-47cb-b99a-e9cdf8892f2an%40googlegroups.com.

Dondell Batac

unread,
Aug 8, 2021, 6:43:47 AM8/8/21
to dropwizard-user
Hi Ryan,

I am new to Dropwizard. Can you point out what are those configuration that is being passed to my hibernate bundle?

This is my code for my hibernatebundle:
private final HibernateBundle<TardisConfiguration> hibernate = new ScanningHibernateBundle<TardisConfiguration>(new String[] {"com.my.package.hibernateEntities"}, new SessionFactoryFactory())
{
public DataSourceFactory getDataSourceFactory(TardisConfiguration configuration)
{
return configuration.getDatabase();
}
};


Thanks

Jochen Schalanda

unread,
Aug 8, 2021, 9:05:55 AM8/8/21
to dropwizard-user
Hi,

please post the configuration file you're starting the application with.

Cheers,
Jochen

Dondell Batac

unread,
Aug 8, 2021, 10:36:55 AM8/8/21
to dropwizard-user
Here's my configuration file

package com.my.package;

import com.bendb.dropwizard.redis.JedisFactory;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.my.package.hibernateEntities.OIDCMapperField;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.dropwizard.Configuration;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.flyway.FlywayFactory;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import microsoft.exchange.webservices.data.core.ExchangeService;
import microsoft.exchange.webservices.data.core.enumeration.misc.ConnectingIdType;
import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
import microsoft.exchange.webservices.data.credential.WebCredentials;
import microsoft.exchange.webservices.data.misc.ImpersonatedUserId;
import org.hibernate.validator.constraints.URL;
import org.quartz.simpl.SimpleThreadPool;

import javax.validation.Valid;
import javax.validation.constraints.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

@Getter
@Setter
public class TardisConfiguration extends Configuration
{
@Valid
private DataSourceFactory database = new DataSourceFactory();

@NotNull
private File teExportDir;

@NotNull
private File teReconDir;

@Valid
private AuthenticationConfig auth = new AuthenticationConfig();

@Valid
private ClientSettings clientSettings = new ClientSettings();

@Valid
private PistonConfig pushNotifications = new PistonConfig();

@Valid
private IntegrationSettings integrations = new IntegrationSettings();

@Valid
private ErrorLogSettings errorLogSettings = new ErrorLogSettings();

@Valid
private ExchangeConfig exchange = new ExchangeConfig();

@Valid
private CredentialManagerSettings credentials = new CredentialManagerSettings();

public static class CredentialManagerSettings
{
private static final String CREDENTIAL_MANAGER_EXCHANGE_USERNAME = "exchange-service-account-username";
private static final String CREDENTIAL_MANAGER_EXCHANGE_PASSWORD = "exchange-service-account-password";

@Getter
@Setter
private String fileName = "store.json";

@Valid
@Getter
@Setter
private File directory;

@Getter
@Setter
private String encryptionKey;

private CredentialManager credentialManager;

@JsonIgnore
public CredentialManager getManager()
{
if(credentialManager == null)
{
credentialManager = new CredentialManager(directory, encryptionKey, fileName);
}

return credentialManager;
}
}

@Setter
public static class ExchangeConfig
{
@URL
private String uri;

@NotNull
@NotEmpty
private String username;

@NotNull
@NotEmpty
private String password;

@JsonIgnore
private CredentialManager credentialManager;

public boolean impersonation = true;

public boolean fetchSentEmail = true;

public ExchangeService getService() throws URISyntaxException
{
Optional<String> username = Optional.empty();
Optional<String> password = Optional.empty();

if(credentialManager != null)
{
username = credentialManager.get(CredentialManagerSettings.CREDENTIAL_MANAGER_EXCHANGE_USERNAME);
password = credentialManager.get(CredentialManagerSettings.CREDENTIAL_MANAGER_EXCHANGE_PASSWORD);
}
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
service.setCredentials(new WebCredentials(
username.orElseGet(() -> this.username),
password.orElseGet(() -> this.password)
));
service.setUseDefaultCredentials(false);
service.setUrl(new URI(uri));

return service;
}

public ExchangeService getServiceFor(String userToImpersonate) throws URISyntaxException
{
ExchangeService service = getService();
if(impersonation)
{
service.setImpersonatedUserId(new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userToImpersonate));
}
return service;
}

public void closeService(ExchangeService service)
{
if(service != null)
{
service.close();
}
}
}

@Getter
@Setter
public static class AuthenticationConfig
{
@Valid
private SessionConfig session = new SessionConfig();

@Valid
private KerberosConfig kerberos = new KerberosConfig();

@Valid
private Map<String, Realm> realms = Maps.newHashMap();

@Valid
private OpenIdConfig provider = new OpenIdConfig();

@Valid
private OIDCMapperField oidcMapperField;

@Valid
private boolean oidcEnabled;
}

@Data
public static class OpenIdConfig
{
private String authUri;
private String tokenUri;
private String name;
private String appId;
private String authRedirectUri;
private String clientSecret;
private String jweKey;
private String basicUserInfoUri;
private String openIDKeyDiscoveryUrl;
private String openIDIssuer;
private String allowedSkewSeconds;
private String configUrl;
private String logoutUrl;
private String tokenValidateUri;
private List<String> validRedirectUri;
}

@Getter
@Setter
public static class SessionConfig
{
@NotBlank
private String signingKey;
@Min(1)
@Max(12)
private int tokenTtl = 2;
@Min(1)
@Max(168)
private int sessionTtl = 48;

@Min(1)
private int allowedSkew = 10;
}

@Getter
@Setter
public static class KerberosConfig
{
@NotNull
private File keyTab;

private File ticketCache;
private File config;

@NotBlank
@Pattern(regexp = "([^/@]+)/([^/@]+)@([^/@]+)")
private String principal;

private String password;

private boolean enabled = false;

private boolean fallbackToSimpleAuth = false;
}

@Getter
@Setter
public static class Realm
{
private List<String> aliases = Lists.newArrayList();

private List<HostDetails> hostDetails = Lists.newArrayList();
}

@Getter
@Setter
public static class HostDetails
{
@NotBlank
@JsonProperty("ldapHost")
private String host;

@Min(1)
@Max(65535)
@JsonProperty("ldapPort")
private int port = 389;

boolean ssl;
}

@Getter
@Setter
public static class ClientSettings
{
/**
* Smallest unit of time in minutes that can be billed.
*/
@Min(0)
@Max(60)
private int timeIncrement;

/**
* Number of months back in time that the client should cache
*/
@Min(1)
@Max(24)
private int historyCache;

private int minimumCharsInNarrative;
}

@Getter
@Setter
public static class IntegrationSettings
{
/**
* Key required for the EMS pushing
*/
@NotEmpty
private String emsKey;
}

@Getter
@Setter
public static class ErrorLogSettings
{
/**
* number of records cached at a time
*/
@Min(1)
@Max(1000)
private int maximumSize;

/**
* cached record expires after write in configured minutes
*/
@Min(1)
@Max(2880)
private int expiresAfterWrite;

/**
* cached record expires after write in configured minutes
*/
@Min(1)
@Max(1000)
private int concurrencyLevel;
}

private FeatureFlagsConfig features = new FeatureFlagsConfig();

@Valid
private FlywayFactory flyway = new FlywayFactory();

@Valid
@NotNull
@JsonProperty
private JedisFactory redis = new JedisFactory();

@Data
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public static class FeatureFlagsConfig
{
private boolean EpochConfigExchangeIntegrationEnabled;
private Boolean EpochConfigActionCodesRequired;
private Boolean EpochConfigCodeSetTemplatesEnabled;
private Integer EpochConfigNarrativesMinimumChars;
private Integer EpochConfigNarrativesMaximumChars;
private LoginMode EpochConfigLoginMode;
private FirstDay EpochConfigCalendarFirstDayOfWeek;
private Boolean EpochConfigFlatFeeCodesEnabled;
private Boolean EpochConfigTimeSegmentsSubmittedVisible;
private Boolean EpochConfigTimeEntriesMattersRequired;
private boolean EpochConfigTimeCastEnabled;
private Boolean EpochConfigTimeCastPullFromLocalOutlook;
private Boolean EpochConfigTimeCastConnectAutomaticallyByDefault;
private int EpochConfigSyncPeriodInMinutes;
private Boolean EpochConfigReferenceRequired;
private Boolean EpochConfigTimersEnabled;
private Boolean EpochConfigOldActionCodesEnabled;
private boolean EpochConfigTKGoalsEnabled;
private boolean EpochConfigKerberosEnabled;
private Boolean EpochConfigTrackedMatterClientsEnabled;
private int EpochConfigTimeCastSegmentsFetchDays;
private int EpochConfigTimeCastSegmentsRetentionDays;
private int EpochConfigTimeEntriesPageDays;
private Boolean EpochConfigMattersPageEnabled;
private Boolean EpochConfigTimeCastURLWhiteListEnabled;

public enum LoginMode
{
EAGER_SSO_FALLBACK,
EAGER_SSO_NOFALLBACK,
OPTIONAL_SSO,
CREDENTIALS_ONLY
}

public enum FirstDay
{
SUN,
MON,
TUE,
WED,
THURS,
FRI,
SAT
}
}

@NotNull
private File eula;

@JsonProperty("eula")
public void setEula(String file) throws FileNotFoundException
{
this.eula = new File(file);
if(!this.eula.isFile())
{
throw new FileNotFoundException("EULA file not found");
}
}

@NotBlank
private String callDataURL;

@NotBlank
private String callDataUserName;

@NotBlank
private String callDataPassword;

@NotNull
private File callDataDir;

@Valid
SchedulerConfig quartz = new SchedulerConfig();

@Data
public static class SchedulerConfig
{
@Min(1)
private int threadPoolCount = 10;

@NotBlank
private final String threadPoolClass = SimpleThreadPool.class.getCanonicalName();

public Properties getSchedulerProperties()
{
Properties schedulerProperties = new Properties();
schedulerProperties.put("org.quartz.threadPool.class", this.threadPoolClass);
schedulerProperties.put("org.quartz.threadPool.threadCount", Integer.toString(this.threadPoolCount));
return schedulerProperties;
}
}

@Valid
Jobs jobs = new Jobs();

@Data
public static class Jobs
{
@Valid
private JobsConfig processCallDetailRecordJob = new JobsConfig();

@Valid
private JobsConfig loadCallDetailRecordJob = new JobsConfig();

@Valid
private JobsConfig fetchExchangeUserPhoneNosJob = new JobsConfig();

@Valid
private JobsConfig fetchExchangeUserContactsJob = new JobsConfig();

@Valid
private JobsConfig fetchExchangeUserDataJob = new JobsConfig();
}

@Data
public static class JobsConfig
{
@Min(0)
private long repeatInterval = 60000;

@Valid
@NotNull
TimeUnit timeUnit = TimeUnit.MILLISECONDS;

boolean enabled = true;

@JsonIgnore
public long getRepeatIntervalValue()
{
return timeUnit.toMillis(repeatInterval);
}

public String cron;

private Integer minThreads = 1;
private Integer maxThreads = 1;
}

@NotBlank
private String ciscoCallDataURL;

@NotBlank
private String ciscoCallDataUserName;

@NotBlank
private String ciscoCallDataPassword;

private boolean ciscoCDRFileDeleteAfterDownload;

@Valid
private Map<String, String> ciscoSftpConfig = Maps.newHashMap();

@Valid
private AuditConfig audits = new AuditConfig();

@Data
public static class AuditConfig
{
private AuditSetting timeEntry = new AuditSetting();
private AuditSetting template = new AuditSetting();
private AuditSetting timer = new AuditSetting();
private AuditSetting timerChunk = new AuditSetting();
}

@Data
public static class AuditSetting
{
boolean enabled = true;
}

private String matterSort = "M.Client_Name, M.Matter_Name";

@Data
public static class EmailConfig
{
@Valid
private JobsConfig emailDispatchJob = new JobsConfig();

@NotNull
Map<String, String> smtpDetails = Maps.newHashMap();

@NotBlank
private String appSenderEmail;

@NotBlank
private String appSenderPass;
}

@Data
public static class NotificationDispatchers
{
@Valid
EmailConfig email;
}

@Valid
NotifSettings notifications = new NotifSettings();

@Data
public static class NotifSettings
{
@Valid
private NotificationDispatchers dispatchers = new NotificationDispatchers();

private boolean enabled = false;

@NotBlank
private String frontendURL;
}
}

Ryan Kennedy

unread,
Aug 8, 2021, 4:05:57 PM8/8/21
to dropwiz...@googlegroups.com
I think the problem is that you’re constructing an empty SessionFactoryFactory rather than including it as part of your configuration.

It looks like you’re manually creating these classes. Usually folks will drive creation via the Dropwizard configuration mechanism. e.g 

I suspect doing it the way you’re doing it is bypassing some default values that would otherwise be set by Jackson or it’s skipping some validation that would point out that you’ve left off a required field. 

Ryan

Dondell Batac

unread,
Aug 8, 2021, 6:50:25 PM8/8/21
to dropwizard-user
Hi Ryan,

Actually I have tried this code below and still I got same error.

private final HibernateBundle<ExampleConfiguration> hibernate = new HibernateBundle<ExampleConfiguration>(Person.class) {
    @Override
    public DataSourceFactory getDataSourceFactory(ExampleConfiguration configuration) {
        return configuration.getDataSourceFactory();
    }
};

Dondell

Dondell Batac

unread,
Aug 8, 2021, 7:02:52 PM8/8/21
to dropwizard-user
Hi Ryan,

I got the issue fixed now. The issue is because there is a missing value on my config.yml. I forgot to supply my databaseName field a value.

database:
driverClass: com.microsoft.sqlserver.jdbc.SQLServerDriver
user: xx
password: xxxxxxx!
url: jdbc:sqlserver://xxx.xxx.xx.xxx:xxxx
maxWaitForConnection: 1s
validationQuery: "/* MyService Health Check */ SELECT 1"
validationQueryTimeout: 3s
minSize: 4
maxSize: 16

checkConnectionWhileIdle: true

evictionInterval: 10s
properties:
databaseName:
characterEncoding: UTF-8
charSet: UTF-8
hibernate.dialect: org.hibernate.dialect.SQLServer2012Dialect
hibernate.enable_lazy_load_no_trans: true

Thanks,

Dondell

Ryan Kennedy

unread,
Aug 8, 2021, 7:09:53 PM8/8/21
to dropwiz...@googlegroups.com
Ah, yeah…that’d do it. Interesting failure mode. I would have expected configuration validation to fail before things get that far, but maybe the database name isn’t declared as a required field.  

Ryan

Dondell Batac

unread,
Aug 8, 2021, 7:40:32 PM8/8/21
to dropwizard-user
Yeah, hopefully in the future it will have a configuration validation :).

Thank you for helping,

Dondell
Reply all
Reply to author
Forward
0 new messages