java – Is it possible to route based on path in Spring Cloud Gateway?

my problem is the following:
I need to set up gateway to route depending on the incoming path, for example:
http://whatever.com/get/abcd:efgh:jklm:nopq-1234-5678-90ab
should direct to http://service.com/service5 because the number following the second to last dash is a 5.
Accordingly,
http://whatever.com/get/abcd:efgh:jklm:nopq-1234-8678-90ab
should direct to http://service.com/service8 because the number following the second to last dash is an 8.
The preceding abcd:efgh: etc is not static so it can be anything, but it does have a format with exact number of semicolons and dashes, so a regex could do the trick, I guess.
However, I could not find anything in Path route predicate. (I could do fine with Query as it accepts REGEX, but in this special case I need to route depending on the path).

Is this possible at all? Thank you in advance!

Spring Boot REST – Use of ThreadPoolTaskExecutor for single jobs

I joined a new team in my company and I see them using a “ThreadPoolTaskExecutor” extensively. It is basically a Backend REST application for a Front-End, that calls other SOAP APIs and returns the result to the client – simply a passthrough. 99% of the times, each REST endpoint is only calling a single SOAP API and returns the response in json format to the client. However, though it’s just a single SOAP call, they use the “ThreadPoolTaskExecutor” and call the .get() blocking method.

ThreadPoolTaskExecutor @Bean on @Configuration class:

@Bean(name=“soapAsyncExecutor")
@Qualifier("soapAsyncExecutor")
   public ThreadPoolTaskExecutor getSoapAsyncExecutor() {
    final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    final ThreadFactory customThreadfactory = new ThreadFactoryBuilder()
        .setNameFormat(“SoapExecutor-%d")
        .setUncaughtExceptionHandler(uncaughtExceptionHandler())
        .setDaemon(true)
        .build();
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executor.setCorePoolSize(80);
    executor.setMaxPoolSize(200);
    executor.setQueueCapacity(80);
    executor.setKeepAliveSeconds(60);
    executor.setAllowCoreThreadTimeOut(true);
    executor.setThreadFactory(customThreadfactory);
    executor.afterPropertiesSet();
    return executor;
   }

Code on @Service:

@Async("soapAsyncExecutor")
@Override
public Future<OrderInfo> getOrderInfoAsync(final String orderId) {
    return new AsyncResult<OrderInfo>(this.getOrderInfo(orderId);
}

private OrderInfo getOrderInfo(final String orderId) {
    // return result from SOAP call which typically take 1 second
}

and then from the @RestController Async method above is called like this:

@GetMapping(value = "/order/{orderId}")
public OrderInfo getOrderInfo(@PathVariable("orderId") final String orderId) {
   OrderInfo orderInfo = orderService.getOrderInfoAsync(orderId).get();
   return orderInfo;
}

As I understand, each request to a REST endpoint in Spring, spins up a new thread anyway (let’s call this the main thread for my lack of a better word). And calling the “.get()” method there is blocking the main thread. My question is, during this blocking period,

  1. What is the official state of the main thread – “Blocked” or “Waiting”? If Blocked, is there even a slightest benefit of using a “ThreadPoolTaskExecutor” like this for a single job as it makes the main thread block anyway?
  2. Can this code be tweaked in any way to bring benefit or does it make no sense to use async programming for a single job like this inside a RestController endpoint?

java – Why do I actually need an interface in Spring Boot?

When programming in Spring/Spring Boot, it’s a common practice to have every service/component implement an interface, for example:

public interface IAdder {
    int add(int a, int b);
}

@Service
public class Adder implements IAdder {
    public int add(int a, int b) { return a + b; }
}

Why do I actually need to write that interface if I don’t plan on having multiple implementations for “Adder” functionality?

One common answer to that question is “you’ll need it for mocking in your unit tests”. To that, I can answer – not really. I can mock the adder using every possible mocking framework you can think of (Mockito, for example):

@Autowired
IMultiplier multiplier;  // Class under test

@Mock
IAdder adder;

@Test
public void multiplicationTest() {
    // Arrange
    when(adder).add(3, 3).thenReturn(6);
    
    // Act
    int result = multiplier.multiply(3, 5);
    
    // Assert
    verify(adder, times(4)).add(3, 3);
    assertThat(result).isEqualTo(15);
}

Having said that, what advantage can the IAdder interface provide for me?

windows – Active Directory / Domain spring cleaning best practices

I am taking over an AD role and one of the tasks I want to accomplish is to “clean up” active directory… remove stale accounts, empty groups, ensure groups have the right users in them.

The domain has a few thousand users.

What is the best resource for “active directory / domain management”?

spring boot – Como disparar uma fila para um listener persistir uma pesquisa no banco?

Implementei uma especificação técnica com o contexto apenas no domínio de usuários onde o objetivo principal do serviço é ser massivo e otimizado para realizar buscas, mas na ultima etapa da especificação aparece a premissa: “Toda vez que realizar uma busca pelo usuário, dispare em uma fila com a string de busca na pesquisa, e um listener salvará essa pesquisa no banco.”
Isso me pareceu uma mensageria no caso um contexto separado usando filas e estas guardando as pesquisas numa tabela separada com a lista, mas também pode ser um simples observer no mesmo contexto com os dados persistidos carregando a chave(string busca)
Qual seria a interpretação desse trecho que vcs entenderiam?
OBS: Já estou usando o elasticsearch + redis para a primeira parte da otimização.

Normalization of database tables. Spring DATA JPA Hibernate

I created the table as stated in the hibernate Bidirectional @ManyToMany documentation. I did exactly the same as shown.

When I add a person, I get the following table:

enter image description here

If you look closely, you will notice that there is a violation of one of the main principles of normalization, that is, information redundancy. Repeats several times New York and Los Angeles

How to add a person correctly so as not to violate the normalization of the database tables, so that there is no data redundancy?

enter image description here

Person.java

    @Entity(name = "Person")
    public class Person {

        @Id
        @GeneratedValue
        private Long id;

        private String name;

        @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
        private List<Address> addresses = new ArrayList<>();

        public Person() {
        }

        public Person(String name) {
            this.name = name;
        }

        // Getters and setters are omitted for brevity

        public void addAddress(Address address) {
            addresses.add( address );
            address.getOwners().add( this );
        }

        public void removeAddress(Address address) {
            addresses.remove( address );
            address.getOwners().remove( this );
        }
    }

Address.java

    @Entity(name = "Address")
    public class Address {

        @Id
        @GeneratedValue
        private Long id;

        private String street;

        @ManyToMany(mappedBy = "addresses")
        private List<Person> owners = new ArrayList<>();

        public Address() {
        }

        public Address(String street) {
            this.street = street;
        }

        // Getters and setters are omitted for brevity
    }

LifecycleController.java

    @Controller
    public class LifecycleController {

        @Autowired
        ServiceJpa serviceJpa;


        @GetMapping(value = "/savePerson")
        public String savePersonAddress () {


            Person person1 = new Person("Jack");

            Address address1 = new Address( "New York" );
            Address address2 = new Address( "Los Angeles" );

            person1.addAddress( address1 );
            person1.addAddress( address2 );

            serviceJpa.savPerson( person1 );


            return "/savePerson";
        }

    }

java – Problema com persistencia com spring

O erro:
java.lang.IllegalArgumentException: Not an entity: class br.com.api.entities.Characters

Minha Class

package br.com.api.entities;

import java.time.LocalDateTime;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Characters {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private LocalDateTime modified;
private String resourceURI;

public Characters() {

}

// Getters and Setters

A grande incógnita aqui é que quando eu pego o Metamodel
para verificar se minha entidade lá esta, ela realmente aparece Characters.

Meu Controller

package br.com.api.controls;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import br.com.api.entities.Characters;
import br.com.hcf.HCFConnection;

@RestController
@RequestMapping("api/v1/public")
public class CharacterControl {

    @GetMapping("/characters")
    public ResponseEntity<Object> getAll() {
        try {
            return ResponseEntity.ok(new HCFConnection<>(Characters.class).all());
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Characters not found");
        }
    }

}

Um adendo, eu não estou usando o spring-boot-starter-data-jpa.

Spring Boot c/ JPA e Banco H2 [fechada]

Estou importando as dependências, no arquivo pom.xml, mas após a importação aparece um erro que não faço idéia, tbm não achei nada parecido por aqui…. Se alguém puder dar uma dica, agradeço!

Segue mensagem de erro….

"Execution default-resources of goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources failed: newPosition < 0: (-1 < 0) (org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources:default-resources:process-resources)
org.apache.maven.plugin.PluginExecutionException: Execution default-resources of goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources failed: newPosition < 0: (-1 < 0)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:148)
at org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:332)
at org.eclipse.m2e.core.internal.embedder.MavenImpl.lambda$8(MavenImpl.java:1380)
at org.eclipse.m2e.core.internal.embedder.MavenExecutionContext.executeBare(MavenExecutionContext.java:179)…"

uri – Spring UriComponentsBuilder – Stack Overflow

I have a String with both an encoded part and a variable.

https://example.com/foo%2Fbar/{variable}

I’m trying to create a URI object like this:

String s = "https://example.com/foo%2Fbar/{0}"
URI uri = UriComponentsBuilder.fromHttpUrl(s)
                .buildAndExpand("baz")
                .toUri();

The result is https://example.com/foo%252Fbar/baz but I would like to get https://example.com/foo%2Fbar/baz.

How can I make sure my variable is expanded but avoid the encoded part to be encoded again?

spring batch multiple inputfiles in environment variables

I need serious help please
i’m stuck for 3 days now in same problem
i have to code a spring batch program that read multiple csv files and copy their content into an output file.
My batch configuration is syntactically correct and i run the app without errors but i don’t see items displayed in console!! feel like the files where not even red!
I have two writers:
One to write in console and the other to write in dest file
But none of them woked!!
I don’t think that files are even red !
here is my batchConfig class:

@Component

@Configuration

@EnableBatchProcessing

public class batchConfig {

 

                   @Autowired

                    private JobBuilderFactory jobBuilderFactory;

                    

                    @Autowired

                    private StepBuilderFactory stepBuilderFactory;

               

                //    @Value(value="Fichiers-eclates/fichier-eclate-*.csv")

                //    private Resource() inputResources;

                  //  @Value("#{jobParameters('FichierEclate')}") Resource() inputFile;

                   @Value("file:/Fichiers-eclates/*.csv") Resource() inputFile;

 

                //   @Value("#{jobParameters('FichierRegrouppe')}") Resource  outputFile;

                   

                    

                    @Bean

                    public ConsoleItemWriter<FichierEclate> writerConsole()

                    {

                        return new ConsoleItemWriter<FichierEclate>();

                    }

                 

                   

                    public FlatFileItemWriter<FichierEclate> writer() 

                    {

                      

                        FlatFileItemWriter<FichierEclate> writer = new FlatFileItemWriter<>();

                        

                      

                       writer.setResource(new ClassPathResource("Fichiers-regrouppes/outputData.csv"));

                         

                     

                        writer.setAppendAllowed(true);

                  

                       

                        writer.setLineAggregator(new DelimitedLineAggregator<FichierEclate>() {

                            {

                                setDelimiter(",");

                                setFieldExtractor(new BeanWrapperFieldExtractor<FichierEclate>() {

                                    {

                                        setNames(new String() { "AffaireID","CodeClasse","CodeAppli","NBcompte","NBlot" });

                                    }

                                });

                            }

                        });

                        return writer;

                    }

               

                    @Bean

                    public Job readCSVFilesJob() {

                        return jobBuilderFactory

                                .get("readCSVFilesJob")

                                .incrementer(new RunIdIncrementer())

                                .start(step1())

                                .build();

                    }

               

                    @Bean

                    public Step step1()  {

                        return stepBuilderFactory.get("step1").<FichierEclate, FichierEclate>chunk(100)

                                .reader(multiResourceItemReader())

                                .writer(writerConsole())

                                .build();

                    }

                    @Primary

                    @Bean

                    public MultiResourceItemReader<FichierEclate> multiResourceItemReader()

                    {

                        MultiResourceItemReader<FichierEclate> resourceItemReader = new MultiResourceItemReader<FichierEclate>();

                        resourceItemReader.setResources(inputFile);

                        resourceItemReader.setDelegate(reader());

                        return resourceItemReader;

                    }

                   

                   @SuppressWarnings({ "rawtypes", "unchecked" })

                    @Bean

                    public FlatFileItemReader<FichierEclate> reader()

                    {

                      

                        FlatFileItemReader<FichierEclate> reader = new FlatFileItemReader<FichierEclate>();

                       

                      
                        reader.setLinesToSkip(1);  

                         

                       

                        reader.setLineMapper(new DefaultLineMapper() {

                            {

                              

                                setLineTokenizer(new DelimitedLineTokenizer() {

                                    {

                                        setNames(new String() { "AffaireID","CodeClasse","CodeAppli","NBcompte","NBlot" });

                                    }

                                });

                               

                                setFieldSetMapper(new BeanWrapperFieldSetMapper<FichierEclate>() {

                                    {

                                       setTargetType(FichierEclate.class);

                                    }

                                });

                            }

                        });

                        return reader;

                    }

 @Bean
 public JobParametersValidator defaultJobParametersValidator() {
 DefaultJobParametersValidator bean = new DefaultJobParametersValidator();

                                               bean.setRequiredKeys(new String() { "FichierEclate" });

                                               bean.setOptionalKeys(new String() { "run.id" });

                                               return bean;

                               }

 

                               @Bean

                               public JobParametersValidator myJobParametersValidator() {

                                               return new MyJobParametersValidator();

                               }

}

here another class for consoleWriter :

import java.util.List;

 

import org.springframework.batch.item.ItemWriter;

 

public class ConsoleItemWriter<T> implements ItemWriter<T> {

    @Override

    public void write(List<? extends T> items) throws Exception {

        for (T item : items) {

            System.out.println(item);

        }

    }

}

Now my questions are:

1/ the folder that contains multiple files to be red is outside so i
want to pass the folder path as environment variable in “Run
configurations” in Eclipse. I’ll need this in production later. Then i
call that environment variable in the flatefileItemReader or the
MultiresourceReader, not sure, i need you to tell me which one and how
please?

2/ the outputfile that will contain the content of all input files
should be created automatically in specific folder. this folder path
should be also passed as environment variable and called later in
FlatFileitemWriter.

3/ Why i don’t see items displayed in console althought i don’t have
errors? if because the files where not red, tell me how to acheive
question “1”.

How can i solve this please ?!!