Use DefaultValue annotation parameter (accepts strings) alongside the QueryParam annotation

@GET
@Path("/bookmarks")
@Produces(MediaType.APPLICATION_JSON)
@Operation(
    summary = "Return bookmarks from repository",
    description = "Return bookmarks from repository")
@ApiResponses({
    @ApiResponse(responseCode = "200", description = "OK"),
    @ApiResponse(responseCode = "403", description = "Forbidden")
})
@RolesAllowed(ADMIN_ROLE)
public void getAllBookmarks(
    @Parameter(description = "max number of returned bookmarks")
    @DefaultValue(Integer.MAX_VALUE + "")
    @QueryParam("maxResult") Integer maxResult) {
  bookmarksService.getBookmarks(maxResult);
}

Shared with from Codever.land. 👉 Use the Copy to mine functionality to copy this snippet to your own personal collection and easy manage your code snippets.

Given the following Superhero class:

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import lombok.Getter;
import lombok.Setter;

@XmlRootElement(name = "super-hero")
@XmlAccessorType(XmlAccessType.FIELD)
@Getter
@Setter
class SuperHero {
  @XmlElement(name = "name")
  String name;

  @XmlElement(name = "super-power")
  String superPower;
}

You can convert an XML String to a SuperHero instance with the following code:

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.StringReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

@RunWith(JUnitPlatform.class)
class TestXmlStringToObjectUnmarshalling {

  static final String superHeroXml =
      "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
          + "<super-hero>"
          + "  <name>Superman</name>"
          + "  <super-power>Flight</super-power>"
          + "</super-hero>";

  @Test
  void testXmlUnmarshalling() throws JAXBException {
    JAXBContext jaxbContext = JAXBContext.newInstance(SuperHero.class);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

    StringReader reader = new StringReader(superHeroXml);
    SuperHero superHero = (SuperHero) unmarshaller.unmarshal(reader);

    assertEquals("Flight", superHero.getSuperPower());
  }
}

Note:

  • create a JAXBContext which includes the SuperHero class - JAXBContext.newInstance(SuperHero.class)
  • create a JAXB Unmarshaller and apply the unmarshal method to a StringReader wrapping the text (it could be also a FileReader or any other Reader for that matter)

Shared with from Codever.land. 👉 Use the Copy to mine functionality to copy this snippet to your own personal collection and easy manage your code snippets.

Use the executeUpdate method of the Query interface. It will return the number of deleted entries:

public int deleteOldMessages(int daysBack) {
  var query = em.createQuery("delete from Message m where createdAt < :givenTimestamp");
  query.setParameter(Message.GIVEN_TIMESTAMP, LocalDateTime.now().minusDays(daysBack));

  return query.executeUpdate();
}

Shared with from Codever.land. 👉 Use the Copy to mine functionality to copy this snippet to your own personal collection and easy manage your code snippets.

With Java version 8 it’s very easy to get the current timestamp with LocalDateTime.now(). One problem that might arise is it’s not easily testable/mockable. Imagine some testing data and conditions depend on the date you set through this call, or you want to do “time travel”. The solution is quite simple - define a service class that produces the current timestamp, which you can then easily mock, in this case we’ll name it ProductionCalendar:

@ApplicationScoped
public class ProductionCalendar {
  public LocalDateTime currentTimestamp() {
    return LocalDateTime.now();
  }

  public LocalDate currentDate() {
    return LocalDate.now();
  }

  public String currentTimestamp(Partner partner) {
    return DateTimeFormatter.ofPattern("yyyy-MM-dd-HH.mm.ss.SSSSSS")
        .format(LocalDateTime.now());
  }
}

Then when were you need to call LocalDateTime.now() inject this service and use its methods instead:

@Stateless
public class PartnerRepository {

  @Inject ProductionCalendar productionCalendar;

  @Inject EntityManager entityManager;

  public void savePartner(String partnerNumber) {
    Partner partner = new Partner();
    partner.setPartnerNumber(partnerNumber);
    partner.setCreatedAt(productionCalendar.currentTimestamp());

    entityManager.persist(partner);
  }

  public List<Partner> getPartnerCreatedAfterDate(LocalDateTime timestamp) {
    String queryJpql = "select p from P p where createdAt > :timestamp order by createdAt desc";
    TypedQuery<Partner> query = entityManager.createQuery(queryJpql, Partner.class);
    query.setParameter("timestamp", timestamp);

    return query.getResultList();
  }
}

Then, in the test class you can easily mock ProductionCalendar and calls to its methods and set timestamps as we need them:

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)
public class UserServiceUnitTest {

  @Inject PartnerRepository partnerRepository;

  @Mock ProductionCalendar productionCalendar;

  @Test
  void testGetLatestPartners() {
     when(productionCalendar.currentTimestamp()).thenReturn(LocalDatetime.now().minusDays(1));
     partnerRepository.save("12345");
     var recentPartners = partnerRepository.getPartnerCreatedAfterDate(LocalDatetime.now().minusDays(2));
     assertThat(recentPartners, hasSize(1));
  }

}

Shared with from Codever.land. 👉 Use the Copy to mine functionality to copy this snippet to your own personal collection and easy manage your code snippets.

In the snippet you can see a message driven bean set up to consume asynchronously messages from a JMS queue:

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.inject.Inject;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import javax.xml.bind.JAXBException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@MessageDriven(
    name = "AccountMessageBean",
    activationConfig = {
      @ActivationConfigProperty(
          propertyName = "destinationType",
          propertyValue = "javax.jms.Queue"),
      @ActivationConfigProperty(
          propertyName = "destination",
          propertyValue = "java:jboss/exported/queue/account.queue"),
      @ActivationConfigProperty(
          propertyName = "acknowledgeMode",
          propertyValue = "Auto-acknowledge")
    })
public class AccountMessageBean implements MessageListener {

  private static final Logger logger = LoggerFactory.getLogger(AccountMessageBean.class);

  @Inject  MessageDrivenContext messageDrivenContext;

  @Inject MessageService messageService;

  @Override
  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void onMessage(Message message) {
    if (!(message instanceof TextMessage)) {
      logger.warn("This is not a text message. Break");
      return;
    }

    TextMessage messageText = (TextMessage) message;
    try {
      if (messageText.getText().contains("organisation")) {
        this.messageService.createOrganisation(messageText.getText());
      } else if (messageText.getText().contains("person"))
        this.messageService.createPerson(messageText.getText());
      else {
        logger.warn("Something went wrong, must be one of those types");
      }

    } catch (JMSException | JAXBException e) {
      logger.error("An error occured while processing the message, mark to rollback");
      messageDrivenContext.setRollbackOnly();
    }
  }
}

Note the following:

  • @MessageDriven annotation where the type of the consumed resource is defined (destinationType - here javax.jms.Queue, but it could also be javax.jms.Topic), the location of the queue (propertyName = "destination") and that the message from the queue is acknowledged once the processing is successful (this is the default setup)
  • the consuming message driven bean implements the javax.jms.MessageListener and the method onMessage(Message message)
  • if a container-managed transaction is not present a new one is created - @TransactionAttribute(TransactionAttributeType.REQUIRED)
  • the consumed message is expected to be text (javax.jms.TextMessage)
  • you access the string value of the message by calling the getText() method - messageText.getText()
  • MessageDrivenContext is used to gain additional access to transaction management - here the transaction is marked for rollback, if an error occurs messageDrivenContext.setRollbackOnly(); (this is only possible in container-based transactions)

Reference - https://docs.oracle.com/javaee/6/tutorial/doc/bncgl.html#bncgq


Shared with from Codever.land. 👉 Use the Copy to mine functionality to copy this snippet to your own personal collection and easy manage your code snippets.