I start in java / springboot and I want to distribute an export function (initially a single class managed by SpingApplication), in several small classes performing an export chunk executed simultaneously.
/*
Here is my initial application class setted conventionally according to SpringBoot practice ...
Which works but it's too long
*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class Application {
public static Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Exporter.class, args);
Exporter exporter = ctx.getBean(Exporter.class);
exporter.main(args);
}
}
/* The runnable classe in Exporter.java*/
package moteur;
import config.ClauseWhereConfig;
import config.FtpConfig;
import config.PigeExportHighcoConfig;
import config.Sql2oConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
#Configuration
#EnableAutoConfiguration
#Import({ ExportSession.class})
public class Exporter {
#Autowired
private ExportSession currentExport;
public static Logger logger = LoggerFactory.getLogger(Exporter.class);
public void main(String[] args) {
run(args);
}
public void run(String[] args) {
/*do some stuff ... */
}
/*
Then I tried this :
Each exporter instance is supposed to make a piece of "select from" original (as you know with the keyword limit <from>, <to>
*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.EnableAsync;
#SpringBootApplication
#EnableAsync
public class Application {
public static Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Exporter.class, args);
Exporter exporter1 = ctx.getBean(Exporter.class);
Exporter exporter2 = ctx.getBean(Exporter.class);
exporter1.setName("exporter1");
exporter2.setName("exporter2");
exporter1.start();
exporter2.start();
}
}
/* The Exporter class now extends Thread object */
#Configuration
#EnableAutoConfiguration
#EnableAsync
#Import({ ExportSession.class, Sql2oConfig.class, ClauseWhereConfig.class, FtpConfig.class, PigeExportHighcoConfig.class})
public class Exporter extends Thread {
#Autowired
private ExportSession currentExport;
public static Logger logger = LoggerFactory.getLogger(Exporter.class);
public void main(String[] args) {
run(args);
}
public void run(String[] args) {
logger.info(getName() + "---- >: Is running" ) ;
}
This foolish attempt that of course doesn't work :
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:708)
at moteur.Application.main(Application.java:27)
In fact i'm loking for a solution for a small autonomous batch treatment
have you got this ?
Related
I spent a while trying to figure out spring boot neo4j in java. What I want is something like this
import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.GraphDatabase;
import org.neo4j.driver.v1.Record;
import org.neo4j.driver.v1.Session;
import org.neo4j.driver.v1.StatementResult;
import org.neo4j.driver.v1.Transaction;
import org.neo4j.driver.v1.Value;
public class adding {
static Driver driver;
public static void main(String args[]) throws JSONException {
StatementResult result;
driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j","password"));
Session session = driver.session();
result = session.run("CREATE (a:Person {name: bob} return a.name");
}
}
So this works an all however I'm looking to query with spring boot.
I followed this guide https://spring.io/guides/gs/accessing-data-neo4j/
and was left pretty confused. I'm not sure how I can immitate the above create process with spring boot . Is there like a query command?
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringGraphNeo4jApplication {
public static void main(String[] args) {
SpringApplication.run(SpringGraphNeo4jApplication.class, args);
}
}
The demo has this file and runs on a port.... I don't understand
Add #EnableNeo4jRepositories in you SpringGraphNeo4jApplication class
In case you want to use your own queries , use #query annotation on repository
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
#SpringBootApplication
#EnableNeo4jRepositories
public class SpringGraphNeo4jApplication {
private final static Logger log = LoggerFactory.getLogger(SpringGraphNeo4jApplication.class);
public static void main(String[] args) throws Exception {
SpringApplication.run(SpringGraphNeo4jApplication.class, args);
}
}
I have been at this for a while but can't figure it out. The repo injects fine when running the app normal, but when trying to do a spring boot unit test it never injects. Here is the code:
package com.g2p.g2prestservice.repositories;
import com.g2p.g2prestservice.model.User;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface UserRepository extends MongoRepository<User, Integer> {
}
package com.g2p.g2prestservice.repositories;
import com.g2p.g2prestservice.model.User;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
#RunWith(SpringRunner.class)
#SpringBootTest
public class UserRepositoryTest {
#Autowired
UserRepository userRepository;
#Test
public void testInsertUser() {
User user = new User("fake#email.com", "fakePassword");
userRepository.save(user);
assertEquals(userRepository.count(), 1);
}
}
I am essentially trying to follow this guide as example: https://springframework.guru/configuring-spring-boot-for-mongo/
Thank you all for solving what I am sure is a very elementary mistake.
EDIT: I THINK the problem is that the spring context isn't launching when I run the test class...
EDIT: Here is launcher class:
package com.g2p.g2prestservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
#SpringBootApplication
public class G2pRestServiceApplication {
public static void main(String[] args) {
SpringApplication.run(G2pRestServiceApplication.class, args);
}
}
try this
#SpringBootTest(classes= {Application.class})
where Application.class is where you wrote you SpringApplication.run code.
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
Here is my SourceRepository class which does not override the autogenerated general findAll() which returns Iterable
package com.infostream.repositories;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.infostream.models.Source;
public interface SourceRepositoryImpl extends PagingAndSortingRepository<Source, Long>{
Page<Source> findAll(Pageable pageRequest);
}
Here is my service class:
package com.infostream.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import com.infostream.models.Source;
import com.infostream.repositories.SourceRepositoryImpl;
#Component
public class SourcesService {
#Autowired
private SourceRepositoryImpl sourceRepository;
public PageImpl<Source> getPaginatedSources(Pageable pageRequest) {
Page<Source> searchResultPage = sourceRepository.findAll(pageRequest);
return new PageImpl<Source>(searchResultPage.getContent(), pageRequest, searchResultPage.getTotalElements());
}
public Iterable<Source> getAllSources() {
return sourceRepository.findAll();
}
}
Here is my main class which i run as a Java application.
package com.infostream.services;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.infostream.consumers.RssArticleConsumer;
import com.infostream.models.Article;
import com.infostream.models.Source;
import com.infostream.producers.RssXmlProducer;
public class HarvestService {
private static BlockingQueue<Article> article_queue = new ArrayBlockingQueue<Article>(10);
#Autowired
private static SourcesService sourcesService;
public static void main(String[] args) throws InterruptedException {
Iterable<Source> sources = sourcesService.getAllSources();
/*
for(Source s : sources) {
System.out.println(s.getUrl());
}
Thread t1 = new Thread(new RssXmlProducer(sources.iterator().next(), article_queue));
Thread t2 = new Thread(new RssArticleConsumer(article_queue));
t1.start();
t2.start();
t1.join();
t2.join();
*/
}
}
The sourcesService variable is null, i see the Autowiring is not working but i do not know why. Is it because i am running the HarvestService file as a Java Application by right clicking on the file in the package explorer and clicking run as java application?
i had the same problem also, #Autowired was not working in the main class
What i did was to get a reference to the ApplicationContext, then use it to get the sourcesService as a bean
have rewrote your class as below
package com.infostream.services;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// adedd import file
import org.springframework.context.ApplicationContext;
import com.infostream.consumers.RssArticleConsumer;
import com.infostream.models.Article;
import com.infostream.models.Source;
import com.infostream.producers.RssXmlProducer;
#SpringBootApplication // added this here
public class HarvestService
{
private static BlockingQueue<Article> article_queue = new ArrayBlockingQueue<Article>(10);
#Autowired
private static SourcesService sourcesService;
ApplicationContext context; // added this here
public static void main(String[] args) throws InterruptedException {
// added this - get reference to application context
context = SpringApplication.run(HarvestService.class, args);
// added this - get the object via the context as a bean
sourcesService = (SourcesService) context.getBean("sourcesService");
Iterable<Source> sources = sourcesService.getAllSources();
/*
for(Source s : sources) {
System.out.println(s.getUrl());
}
Thread t1 = new Thread(new RssXmlProducer(sources.iterator().next(),article_queue));
Thread t2 = new Thread(new RssArticleConsumer(article_queue));
t1.start();
t2.start();
t1.join();
t2.join();
*/
}
}
are you using spring boot?
looks like your HarvestService class needs #SpringBootApplication and add thid in main function
SpringApplication.run(HarvestService.class, args);
and make sure you have the right dependency in your maven/gradle.
hope it helps
You have to implement CommandLineRunner and put your code inside the method run, because spring need to load all the components and with the normal main it is not going to work
#Override
public void run(String... args) throws Exception {
main(args);
}
SpringApplication.run main method
Used modelmapper dependency (2.4.4) .Use #RequiredArgsConstructor and modelmapper method with #Bean annotation on main class. The bean that to be initialize should be final.
I am new to Spring AOP and annotations. I tried to write a simple program that uses Aspect. I am unable to figure out where I went wrong. Its doesn't print the what I have in my Aspect.
package com.business.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
#EnableAspectJAutoProxy
#Configuration
public class PrintMain {
public static void main(String[] args) {
// Do I always need to have this. Can't I just use #Autowired to get beans
ApplicationContext ctx = new AnnotationConfigApplicationContext(PrintMain.class);
CheckService ck = (CheckService)ctx.getBean("service");
ck.print();
}
#Bean(name="service")
public CheckService service(){
return new CheckService();
}
}
package com.business.main;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class SimpleAspect {
#Around("execution(* com.business.main.CheckService.*(..))")
public void applyAdvice(){
System.out.println("Aspect executed");
}
}
package com.business.main;
import org.springframework.stereotype.Component;
#Component
public class CheckService{
public void print(){
System.out.println("Executed service method");
}
}
Output: Executed service method
I expect to print what I have in my Aspect
I think your #Component isn't work!
Maybe, you need the #ComponentScan
#EnableAspectJAutoProxy
#ComponentScan
#Configuration
public class PrintMain {
public static void main(String[] args) {
// Do I always need to have this. Can't I just use #Autowired to get beans
ApplicationContext ctx = new AnnotationConfigApplicationContext(TNGPrintMain.class);
CheckService ck = (CheckService)ctx.getBean("service");
ck.print();
}
#Bean(name="service")
public CheckService service(){
return new CheckService();
}
}
I have been trying to add spring validators to a spring-data-rest project.
I followed along and setup the "getting started" application via this link: http://spring.io/guides/gs/accessing-data-rest/
...and now I am trying to add a custom PeopleValidator by following the documents here:
http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/validation-chapter.html
My custom PeopleValidator looks like
package hello;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class PeopleValidator implements Validator {
#Override
public boolean supports(Class<?> clazz) {
return true;
}
#Override
public void validate(Object target, Errors errors) {
errors.reject("DIE");
}
}
...and my Application.java class now looks like this
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
#Configuration
#EnableJpaRepositories
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public PeopleValidator beforeCreatePeopleValidator() {
return new PeopleValidator();
}
}
I would expect that POSTing to the http://localhost:8080/people URL would result in an error of some kind since the PeopleValidator is rejecting everything. However, no error is thrown, and the validator is never called.
I have also tried manually setting up the validator as shown in section 5.1 of the spring-data-rest documentation.
What am I missing?
So it appears that the before/after "save" events only fire on PUT and PATCH. When POSTing, the before/after "create" events fire.
I tried it the manual way again using the configureValidatingRepositoryEventListener override and it worked. I'm not sure what I'm doing differently at work than here at home. I'll have to look tomorrow.
I sure would love to hear if others have suggestions on why it wouldn't work.
For the record, here is what the new Application.java class looks like.
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
#Configuration
#EnableJpaRepositories
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration
public class Application extends RepositoryRestMvcConfiguration {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", new PeopleValidator());
}
}
Looks like the feature is currently not implemented (2.3.0), unluckily there are no constants for the event names otherwise the solution below would not be that fragile.
The Configuration adds all properly named Validator beans to ValidatingRepositoryEventListener using the right event.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.validation.Validator;
#Configuration
public class ValidatorRegistrar implements InitializingBean {
private static final List<String> EVENTS;
static {
List<String> events = new ArrayList<String>();
events.add("beforeCreate");
events.add("afterCreate");
events.add("beforeSave");
events.add("afterSave");
events.add("beforeLinkSave");
events.add("afterLinkSave");
events.add("beforeDelete");
events.add("afterDelete");
EVENTS = Collections.unmodifiableList(events);
}
#Autowired
ListableBeanFactory beanFactory;
#Autowired
ValidatingRepositoryEventListener validatingRepositoryEventListener;
#Override
public void afterPropertiesSet() throws Exception {
Map<String, Validator> validators = beanFactory.getBeansOfType(Validator.class);
for (Map.Entry<String, Validator> entry : validators.entrySet()) {
EVENTS.stream().filter(p -> entry.getKey().startsWith(p)).findFirst()
.ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue()));
}
}
}
A bit of a stab in the dark - I've not used spring-data-rest. However, after having a read of the tutorial you're following, I think the problem is that you need a PersonValidator not a PeopleValidator. Rename everything accordingly:
PersonValidator
package hello;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class PersonValidator implements Validator {
#Override
public boolean supports(Class<?> clazz) {
return true;
}
#Override
public void validate(Object target, Errors errors) {
errors.reject("DIE");
}
}
Application
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
#Configuration
#EnableJpaRepositories
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public PersonValidator beforeCreatePersonValidator() {
return new PersonValidator();
}
}
Another way of doing it is to use annotated handlers as specified here
http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/events-chapter.html#d5e443
Here is an example of how to use annotated handlers:
import gr.bytecode.restapp.model.Agent;
import org.springframework.data.rest.core.annotation.HandleBeforeCreate;
import org.springframework.data.rest.core.annotation.HandleBeforeSave;
import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
import org.springframework.stereotype.Component;
#Component
#RepositoryEventHandler(Agent.class)
public class AgentEventHandler {
public static final String NEW_NAME = "**modified**";
#HandleBeforeCreate
public void handleBeforeCreates(Agent agent) {
agent.setName(NEW_NAME);
}
#HandleBeforeSave
public void handleBeforeSave(Agent agent) {
agent.setName(NEW_NAME + "..update");
}
}
Example is from github edited for brevity.