I can't resolve ILogger instance in my console application...
I'm using Unity IoC and Serilog.
The registration is done like this:
container = new UnityContainer();
container.RegisterFactory<ILogger>(factory =>
{
ILogger log = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
return log;
}, new ContainerControlledLifetimeManager());
And then when I try this:
var logger = container.Resolve<ILogger>();
I get an exception:
Unity.ResolutionFailedException HResult=0x80131500 Message=Failed
to select a constructor for Serilog.Core.Logger
_____________________________________________________ Exception occurred while:
ā¢resolving type: 'ILogger' mapped to 'Logger'
Source=Unity.Container StackTrace: at
Unity.UnityContainer.ExecuteValidatingPlan(BuilderContext& context)
at Unity.UnityContainer.Unity.IUnityContainer.Resolve(Type type,
String name, ResolverOverride[] overrides) at
Unity.UnityContainerExtensions.Resolve[T](IUnityContainer container,
ResolverOverride[] overrides)
Inner Exception 1: InvalidOperationException: Failed to select a
constructor for Serilog.Core.Logger
Inner Exception 2: InvalidRegistrationException: Exception of type
'Unity.Exceptions.InvalidRegistrationException' was thrown.
I even tried registering it like this:
container = new UnityContainer();
ILogger log = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
container.RegisterInstance<ILogger>(log);
but with the same resulting exception thrown.
Please help
Found the problem...
The problem was this line of code down the road, overriding my configuration:
container.RegisterTypes(AllClasses.FromAssembliesInBasePath(), WithMappings.FromMatchingInterface, WithName.Default);
Related
I have a docker-compose setup to start my SpringBoot application and a MySQL database. If the database starts first, then my application can connect successfully. But if my application starts first, no database exists yet, so the application throws the following exception and exits:
app_1 | 2018-05-27 14:15:03.415 INFO 1 --- [ main]
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
app_1 | 2018-05-27 14:15:06.770 ERROR 1 --- [ main]
com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization
app_1 | com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Communications link failure
I could edit my docker-compose file to make sure the database is always up before the application starts up, but I want the application to be able to handle this case on its own, and not immediately exit when it cannot reach the database address.
There are ways to configure the datasource in the application.properties file to make the application reconnect to the database, as answered here and here. But that doesn't work for a startup connection to the datasource.
How can I make my SpringBoot application retry the connection at startup to the database at a given interval until it successfully connects to the database?
Set HikariCP's initializationFailTimeout property to 0 (zero), or a negative number. As documented here:
āinitializationFailTimeout
This property controls whether the pool will "fail fast" if the pool cannot be seeded with an initial connection successfully. Any positive number is taken to be the number of milliseconds to attempt to acquire an initial connection; the application thread will be blocked during this period. If a connection cannot be acquired before this timeout occurs, an exception will be thrown. This timeout is applied after the connectionTimeout period. If the value is zero (0), HikariCP will attempt to obtain and validate a connection. If a connection is obtained, but fails validation, an exception will be thrown and the pool not started. However, if a connection cannot be obtained, the pool will start, but later efforts to obtain a connection may fail. A value less than zero will bypass any initial connection attempt, and the pool will start immediately while trying to obtain connections in the background. Consequently, later efforts to obtain a connection may fail. Default: 1
There is an alternative way to do this, which doesn't rely on a specific Connection Pool library or a specific database. Note that you will need to use spring-retry to achieve the desired behaviour with this approach
First you need to add spring-retry to your dependencies :
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>${spring-retry.version}</version>
</dependency>
Then you can create a decorator over DataSource that will extends AbstractDataSource like bellow :
#Slf4j
#RequiredArgsConstructor
public class RetryableDataSource extends AbstractDataSource {
private final DataSource dataSource;
#Override
#Retryable(maxAttempts = 5, backoff = #Backoff(multiplier = 1.3, maxDelay = 10000))
public Connection getConnection() throws SQLException {
log.info("getting connection ...");
return dataSource.getConnection();
}
#Override
#Retryable(maxAttempts = 5, backoff = #Backoff(multiplier = 2.3, maxDelay = 10000))
public Connection getConnection(String username, String password) throws SQLException {
log.info("getting connection by username and password ...");
return dataSource.getConnection(username, password);
}
}
Then you will need to inject this custom DataSource decorator into Spring context by creating a custom BeanPostProcessor :
#Slf4j
#Order(value = Ordered.HIGHEST_PRECEDENCE)
#Component
public class RetryableDatabasePostProcessor implements BeanPostProcessor {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof DataSource) {
log.info("-----> configuring a retryable datasource for beanName = {}", beanName);
return new RetryableDataSource((DataSource) bean);
}
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
Last but not least you will need to enable Spring retry by adding #EnableRetry annotation to spring main class, example :
#EnableRetry
#SpringBootApplication
public class RetryableDbConnectionApplication {
public static void main(String[] args) {
SpringApplication.run(RetryableDbConnectionApplication.class, args);
}
}
For some reason, I get exception during instantiation of the home controller. I am very puzzled by it. I am thinking that may be it is caused by the different life time scope of the different dependencies - InstancePerDependency and SingleInstance.
using: Autofac.4.0.0
In my Register(). I have:
builder.Register(x => new DepositEligibilityService()).As<IDepositEligibilityService>().InstancePerDependency();
builder.Register(x => new SemanticExceptionManager()).As<IExceptionManager>().SingleInstance();
builder.Register(x => new SemanticLoggingManager()).As<ILoggingManager>().SingleInstance();
and
public class HomeController : BaseController
{
private readonly IAuthenticationManager _authenticationManager;
LoginInfo _loginInfo;
public HomeController(IDepositEligibilityService depositEligibilityService, IExceptionManager exceptionManager, ILoggingManager loggingManager):base(depositEligibilityService, exceptionManager, loggingManager)
{
// ...
}
}
I sometimes get an exception like the following:
Exception information:
Exception type: DependencyResolutionException
Exception message: An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = HomeController (ReflectionActivator), Services = [DepositEligibility.Web.Controllers.HomeController], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope ---> An exception was thrown while invoking the constructor 'Void .ctor(DepositEligibility.Web.Services.IDepositEligibilityService, Gdot.Services.SemanticLogging.Interfaces.IExceptionManager, Gdot.Services.SemanticLogging.Interfaces.ILoggingManager)' on type 'HomeController'. ---> Object reference not set to an instance of an object. (See inner exception for details.) (See inner exception for details.)
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
at Autofac.Core.Resolving.InstanceLookup.Execute()
at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters)
at System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType)
An exception was thrown while invoking the constructor 'Void .ctor(DepositEligibility.Web.Services.IDepositEligibilityService, Gdot.Services.SemanticLogging.Interfaces.IExceptionManager, Gdot.Services.SemanticLogging.Interfaces.ILoggingManager)' on type 'HomeController'. ---> Object reference not set to an instance of an object. (See inner exception for details.)
at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
Object reference not set to an instance of an object.
at DepositEligibility.Web.Controllers.BaseController..ctor(IDepositEligibilityService depositEligibilityService, IExceptionManager exceptionManager, ILoggingManager loggingManage)
at DepositEligibility.Web.Controllers.HomeController..ctor(IDepositEligibilityService depositEligibilityService, IExceptionManager exceptionManager, ILoggingManager loggingManager)
at lambda_method(Closure , Object[] )
at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
My struts2 webapp makes use of a SQL database. Within the DB access code, I've written a basic try/catch handler that catches SQL or general exceptions, writes the detail to a log file, and then continues. The hierarchy of classes is as follows:
Action method -> get or set method on Model -> DB access.
//Action method in action class
public string doActionMethod() throws Exception
{
String results = SampleModel.getResults();
}
//Model method in model class
public string getResults() throws Exception
{
String results = DBLayer.runQuery("SELECT Results FROM SampleTable WHERE Value='1');
}
//Method that queries database in DB access class
public string runQuery() throws Exception
{
ResultSet rs = null;
Connection dbConnection = null;
PreparedStatement preparedStatement = null;
dbConnection = MSSQLConnection.getConnection();
preparedStatement = dbConnection.prepareStatement(sqlQuery);
//run SQL statements
return String(rs.get(0));
}
I'd like caught exceptions to bubble up to the Action level, so that I can forward them to an appropriate error page. Is there a better way to do this than adding a "throws Exception" to the method signature?
Since you have no hope of recovery, throw an application-specific RuntimeException.
Use standard Struts 2 declarative exception handling to get your app to the appropriate error page.
Can I use the ContactPicker contract when the app is snapped?
var picker = new Windows.ApplicationModel.Contacts.ContactPicker();
picker.CommitButtonText = "Select";
picker.SelectionMode = Windows.ApplicationModel.Contacts.ContactSelectionMode.Fields;
picker.DesiredFields.Add(Windows.ApplicationModel.Contacts.KnownContactField.Email);
var contactInformation = await picker.PickSingleContactAsync();
The above code works when in fullscreen but throws the following exception on the call to PickSingleContactAsync() when snapped to the side of the screen:
System.Runtime.InteropServices.COMException was unhandled by user code
HResult=-2147467259
Message=Error HRESULT E_FAIL has been returned from a call to a COM component.
Source=mscorlib
ErrorCode=-2147467259
StackTrace:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at TouchToneDtmf.MainPage.d__e.MoveNext()
in
d:\Users\Foo\MainPage.xaml.cs:line
556 InnerException:
It's not working when the app is snapped - you should check the visual state of the app before calling the ContactPicker.
In the official C# sample there is also method EnsureUnsnapped() you might find helpful when implementing this contract.
Every time you call a file[/contact] picker you must first make sure that your
app can show the file[/contact] picker by verifying that your app in not snapped
or, if your app is snapped, that it can be unsnapped in order to show
the file picker. Source - How to save files through file pickers
using Windows.UI.ViewManagement;
//...
internal bool EnsureUnsnapped()
{
bool unsnapped = ((ApplicationView.Value != ApplicationViewState.Snapped) || ApplicationView.TryUnsnap());
return unsnapped;
}
I'm building an application in C# that has a static class which initiate a COM class and handles some event handlers of another class that hooks keyboard.
When I call a method of the COM class from a button event handler in my WPF window, the method works without any problems but when I call it in one of the event callbacks within my static class it throws following exception:
Unable to cast COM object of type 'BLAHBLAH' to interface type
'BLAHBLAH'. This operation failed because the QueryInterface call on
the COM component for the interface with IID
'{9DD6680B-3EDC-40DB-A771-E6FE4832E34A}' failed due to the following
error: An outgoing call cannot be made since the application is
dispatching an input-synchronous call. (Exception from HRESULT:
0x8001010D (RPC_E_CANTCALLOUT_ININPUTSYNCCALL)).
Can you please tell me, what this exception means and how can I solve it?
Wrap your code in a new thread:
Thread thread = new Thread(() =>
{
ManagementObjectSearcher theSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject currentObject in theSearcher.Get())
{
Debug.WriteLine("Device present: " + currentObject);
ManagementObject theSerialNumberObjectQuery = new ManagementObject("Win32_PhysicalMedia.Tag='" + currentObject["DeviceID"] + "'");
serial = theSerialNumberObjectQuery["SerialNumber"].ToString();
}
});
thread.Start();
thread.Join(); //wait for the thread to finish
Refer this KB http://support.microsoft.com/kb/198996
Looks like it is because of threads(May not be user defined threads)