Spring Dataflow not display properties - spring-cloud-dataflow

When I create Task in Spring Cloud Dataflow and edit properties in Spring Cloud Dataflow Dashboard I only see standard properties label despite being configured
ConfigurationProperties. And I do not know what I've set up wrongly. Below the code.
JobProps:
#Component
#ConfigurationProperties("job")
public class JobProps {
private String ux;
//getter and setter
}
JobDoing:
#Component
public class JobDoing {
public JobDoing() {
doing();
}
#Value("${job.ux:}")
private String test;
private static final Log logger = LogFactory.getLog(JobConfiguration.class);
public void doing(){
logger.info("Props: " + test);
}
}
DemoApplication:
#EnableConfigurationProperties({JobProps.class })
#EnableTask
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

You need to whitelist your application's custom configuration properties so that they get picked up by the Spring Cloud Data Flow server when extracting and displaying the application configuration properties.
To whitelist the configuration properties, you can refer this documentation.

Related

dropwizard version migration and DI

I've run to some issues trying to migrate dropwizard from 1.2 to 2.0.24 (and 2.0.25) related to DI, wondering if someone has had same issues or any ideas.
We have one application,
public class Account extends Application<AccountConfiguration> {
public static void main(String[] args) throws Exception {
new Account().run(args);
}
#Override
public void initialize(Bootstrap<Configuration> bootstrap) {
bootstrap.addBundle(new DropwizardBundle<>());
}
#Override
public void run(AccountConfiguration configuration, Environment environment) throws Exception {
...
environment.jersey().register(new SessionResource(authenticationService));
}
}
The DropWizardBundle class binds an instance to a class:
public void run(AccountConfiguration configuration, Environment environment) {
environment.jersey().register(new AbstractBinder() {
#Override
protected void configure() {
bind(configuration.getResponder()).to(Responder.class);
}
});
And the SessionResource looks like
#Path("/sessions")
#Consumes(MediaType.APPLICATION_JSON)
#Produces({MediaType.APPLICATION_JSON, "application/v1+json"})
#RequiredArgsConstructor
#Timed
public class SessionResource {
#Inject
private Responder responder;
private final AuthenticationService authenticationService;
#POST / #GET methods
}
The current code, in Dropwizard 1.2 is running and Responder is injected. Switching to 2.0.24/25 Responder is null. I am wondering if I missed something in the migration..
I'm not sure if this is working the way you intended (or the way you are think it is) in version1.X for you. I do not know what configuration.getResponder() is returning so I can't really test your case. I found for resource classes using DI, a lot of problems I see people face can be solved by registering the class and allow the H2K instantiate the resources for you.
environment.jersey().register(SessionResource.class);
You will have to update how AuthenticationService is passed into the resource by registering it to so it can also be injected. The below is an example of registering it as a AuthenticationService as a singleton.
public void run(AccountConfiguration configuration, Environment environment) {
environment.jersey().register(new AbstractBinder() {
#Override
protected void configure() {
//Not sure how AuthenticationService is instantiate but this is an example
bind(new AuthenticationService()).to(AuthenticationServic.class).in(Singleton.class);
}
});

ServiceLocator with Autofac in asp.net core 3.1

I'm developing an asp.net core 3.1 webapi application and i'm using Autofac as DI container.
For one particular case i cannot use ConstructorInjection nor propertyinjection nor methodinjection. My only way is to implement a sort of ServiceLocator pattern with the support of Autofac.
*I known that the service locator is an antipattern, but i will use that only if it will be the only chance *
Said that, I create a little static class :
public static class ServiceLocator
{
private static XXXX Resolver;
public static T Resolve<T>()
{
return Resolver.Resolve<T>();
}
public static void SetCurrentResolver(XXXX resolver)
{
Resolver = resolver;
}
}
I write XXXX on the type of Resolver property because i don't know which is the Autofac class to use. The method SetCurrentResolver will be called in the Configure method of Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILifetimeScope serviceProvider)
{
//OTHER STUFF NOT RELATED HERE
ServiceLocator.SetCurrentResolver(serviceProvider);
}
I tried to pass the instance of ILifetimeScope but when i use it later in the service locator it will be Disposed and then not work. I thinked to pass an IContainer object but i'm not able to retrieve an instance in Startup.cs (neither in the Configure method nor in the ConfigureContainer)
I Report the ConfigureContainer method for completion
public void ConfigureContainer(ContainerBuilder builder)
{
//first register the dependency for WebApi Project
builder.RegisterType<HttpContextUserService>().As<IUserService>().SingleInstance();
//and then register the dependency for all other project
var appConfiguration = new AppConfiguration();
Configuration.GetSection("Application").Bind(appConfiguration);
builder.RegisterInstance(appConfiguration).SingleInstance();
builder.RegisterModule(new DependencyInjectionBootstrapper(appConfiguration));
}
Anyone can help me with this problem?
Thanks
This is actually answered in the Autofac docs if you look at the example.
Here are the relevant bits.
public class Startup
{
public Startup(IHostingEnvironment env)
{
// Body omitted for brevity.
}
public ILifetimeScope AutofacContainer { get; private set; }
public void ConfigureServices(IServiceCollection services)
{
// Body omitted for brevity.
}
public void ConfigureContainer(ContainerBuilder builder)
{
// Body omitted for brevity.
}
public void Configure(IApplicationBuilder app)
{
// If, for some reason, you need a reference to the built container, you
// can use the convenience extension method GetAutofacRoot.
// THIS IS WHERE YOU'D SET YOUR SERVICE LOCATOR.
this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
}
}

How to inject a bean into custom argument resolver?

Hello i use spring boot 1.3.2 version. I have a custom argument resolver which's name is ActiveCustomerArgumentResolver. Everything is great, resolveArgument method works fine but i can't initialize my service component which is of my custom arg. resolver. Is there a problem with lifecycle process? Here is my code:
import org.springframework.beans.factory.annotation.Autowired;
//other import statements
public class ActiveCustomerArgumentResolver implements HandlerMethodArgumentResolver {
#Autowired
private CustomerService customerService;
#Override
public boolean supportsParameter(MethodParameter parameter) {
if (parameter.hasParameterAnnotation(ActiveCustomer.class) && parameter.getParameterType().equals(Customer.class))
return true;
else
return false;
}
#Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Principal userPrincipal = webRequest.getUserPrincipal();
if (userPrincipal != null) {
Long customerId = Long.parseLong(userPrincipal.getName());
return customerService.getCustomerById(customerId).orNull(); //customerService is still NULL here, it keeps me getting NullPointerEx.
} else {
throw new IllegalArgumentException("No user principal is associated with the current request, yet parameter is annotated with #ActiveUser");
}
}
}
Let the Spring create the resolver for you by making it a Component:
#Component
public class ActiveCustomerArgumentResolver implements HandlerMethodArgumentResolver {...}
Then inject the resolver into your WebConfig instead of simply using the new, like following:
#EnableWebMvc
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired private ActiveCustomerArgumentResolver activeCustomerArgumentResolver;
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(activeCustomerArgumentResolver);
}
}
This is how i've solved the problem, not a generic one but helps me a lot:
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application extends WebMvcConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(activeCustomerArgumentResolver());
}
#Bean
public ActiveCustomerArgumentResolver activeCustomerArgumentResolver() {
return new ActiveCustomerArgumentResolver();
}
}

multiple ejb injections which implement the same interface

i am very new to this ejb stuff. is there any possibility that in a single file i can have multiple injections based on some criteria.
for eg
public interface common(){
public void sayhello();
}
beanA
implements common()
beanB
implements common()
both are stateless beans
now i have a client which needs to trigger hello method based on some criteria. for eg. say based on console input if string contains A then beanA should be injected otherwise beanB.
Is there any possibility? and again my next question is , can i say this dynamic injection is not managed by container? if so how can i let container take the control? i need a sample code or atleast any tutorial ref.
thanks in advance!!
No, this is not really possible. You might be able to get close with a custom CDI scope that uses a thread local or session attribute, but I wouldn't recommend it. Instead, just inject a reference to both EJBs, and select the one to use as needed:
#EJB(beanName="BeanA")
Common beanA;
#EJB(beanName="BeanB")
Common beanB;
private Common getCommon(String input) {
return isBeanAInput(input) ? beanA : beanB;
}
you could do something like this:
public interfaces ICommon {
public void sayhello();
}
#Stateless
#LocalHome
public class BeanA implements ICommon {
public void sayhello() {
// say hallo
}
}
#Stateless
#LocalHome
public class BeanB implements ICommon {
public void sayhello() {
// say hallo
}
}
and here the CDI "client" which uses the EJB services
#Model
public void MyJSFControllerBean {
#Inject
private BeanA beanA;
#Inject
private BeanB beanB;
public String sayhello(final String input) {
if("a".equals(input)) {
beanA.sayhello();
} else {
beanB.sayhello();
}
return "success";
}
}
Or the other solution would be that you create a CDI producer to create this. but then you are mixing two different concepts. but i think it depends ou your concrete usecase.
dynamic injection does not exist! with #Produce and #Qualifier you can control the creation of the required CDI beans to inject. but this is only for CDI not for EJB.
here the CDI producer example:
public void ICommonProducer {
#EJB
private BeanA beanA;
#EJB
private BeanB beanB;
#Produces
public ICommon produce() {
final String input = "?????";
// but here you have the problem that must get the input from elsewhere....
if("a".equals(input)) {
beanA.sayhello();
} else {
beanB.sayhello();
}
}
}
#Model
public void MyJSFControllerBean {
#Inject
private ICommon common;
public String sayhello(final String input) {
common.sayhello();
return "success";
}
}
i have not teseted this code...

Spring Data Neo4j "Hello, World" standalone app

I'm trying to write a "Hello, World" with Spring Data Neo4j in a standalone app. It runs and actually creates the Neo4j database, but my #Autowired repo is not being initialized. I suspect the problem is in my main class, but I don't know what to try. Unsurprisingly, almost all the Spring tutorials I've found are about web apps.
What am I doing wrong?
config bean:
#Configuration
#EnableNeo4jRepositories(basePackages = "test2")
public class ConfigBean extends Neo4jConfiguration {
private static final String DB_PATH = "/home/kevin/tmp/hello-spring-data-neo4j/";
public ConfigBean() {
setBasePackage("test2");
}
#Bean
public GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
}
}
node entity:
#NodeEntity
public class Foo {
#GraphId
private Long id;
}
repository:
public interface FooRepository extends GraphRepository<Foo> { }
main class:
#Component
public class Test2 {
#Autowired
FooRepository repo;
public void doStuff() {
System.out.println("repo: " + repo); // null!
}
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext("test2");
new Test2().doStuff();
}
}
It logs about 350 lines of output. These are the last few lines. I searched for this error message, but the impression I got is that it's unrelated to my problem.
20:44:30.630 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemProperties]
20:44:30.631 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemEnvironment]
20:44:30.635 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source. Returning [null]
repo: null
Via the magical "ask a question, find the answer" effect, my main class now looks like this, and the repo is being assigned:
#Component
public class Test2 {
#Autowired
FooRepository repo;
public void doStuff() {
System.out.println("repo: " + repo);
}
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext("test2");
Test2 test2 = context.getBean(Test2.class);
test2.doStuff();
}
}

Resources