I have a legacy application which uses Spring-Rest and Google-GSON (declared in pom.xml) for serializing/deserializing Objects. In one of these objects there's a java.util.Date property, I want to set the date format but I cannot find how to do it.
I can't even switch to Jackson because a colleague of mine uses it explicitly in a part of his code.
How can I set the date format in this scenario?
This application doesn't use Spring Boot. Everything I found for this problem is about Spring-boot + Jackson.
EDIT: I add some details. I have this Class:
#Entity
#Table(name="WEB_ELENCO_SCHEMI")
#IdClass(PK.class)
public class WebElencoSchemi implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="COD_ARCHIVIO_ARCAM")
private BigDecimal codArchivioArcam;
#Temporal(TemporalType.DATE)
#Column(name="DATA_AGGIORNAM")
private Date dataAggiornam;
...
}
And this repository:
public interface WebElencoSchemiRepository extends CrudRepository<WebElencoSchemi, BigDecimal> {
public List<WebElencoSchemi> findByCodArchivioArcam(BigDecimal codArchivioArcam);
I want to set the format of dataAggiornam JSON output. I'm using GSON as serializator/deserializator for Spring Rest, as defined in pom.xml.
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
I tried adding a spring.gson.date-format property in my properties file with no success.
I'm NOT using Spring boot and I cannot switch to Jackson (in which the problem is solved with a simple annotation on the class property).
You can set a date format while creating the Gson object with the GsonBuilder.
Something like;
Gson gson = new GsonBuilder().setDateFormat("dd/MM/yyyy HH:mm").serializeNulls().create();
It has a bunch of other factory methods which are super useful also, for your perusal. Love this library.
Related
In a regular entity for SDR, it takes care of all properties of an entity for you saving it to the database. But how do you handle files?
#Entity
public class User {
String name;
Set<File> myfiles; //how can I make this work?
}
#RepositoryRestResource
public interface UserRepository extends JpaRepository<User, Long> {}
How can I make it so that a User owns a list of files, can upload and download them?
This is not really possible with Spring Data/REST as it focusses on structured data; i.e. tables and associations, for the most part.
#Lob is problematic as it forces you to store your content in the database which isn't necessarily where you want to store it. The file-system or S3 might be better for example.
byte[] is also problematic if you have very large files as you will likely cause OutOfMemoryExceptions.
Instead, there is a community project called Spring Content that addresses exactly the problem you are trying to solve.
Spring Content provides the same programming paradigms as Spring Data/REST for unstructured data; i.e. images, documents, movies, etc. So, using this project you can associate one, or in your case, many "content" objects with your Spring Data entities and manage them over HTTP just like you do with your Spring Data Entities too.
Its pretty simple to add to your project, as follows:
pom.xml (boot starters also available)
<!-- Java API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-fs</artifactId>
<version>1.0.0.M4</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest</artifactId>
<version>1.0.0.M4</version>
</dependency>
Configuration
#Configuration
#EnableFilesystemStores
#Import("org.springframework.content.rest.config.RestConfiguration.class")
public class ContentConfig {
#Bean
FileSystemResourceLoader fileSystemResourceLoader() throws IOException {
return new FileSystemResourceLoader(new File("/path/to/uploaded/files").getAbsolutePath());
}
}
To associate content, modify your User entity as follows:
#Entity
public class User {
String name;
List<Image> images;
}
Add an Image entity:
#Entity
public class Image {
#ContentId
private String contentId;
#ContentLength
private long contentLength = 0L;
#MimeType
private String mimeType = "text/plain";
}
And to this add a "store" (the equivalent of a Repository but for content):
ImageStore.java
#StoreRestResource
public interface ImageStore extends FilesystemContentStore<Image, String> {}
This is all you need to create REST endpoints # /users/{userId}/images. When your application starts, Spring Content will look at your dependencies seeing Spring Content Filesystem, look at your ImageStore interface and inject a filesystem-based implementation of that interface. It will also see the Spring Content REST dependency and inject an #Controller implementation that forwards HTTP requests to your ImageStore. Just like Spring Data does for your UserRepository. This saves you having to implement any of this yourself which I think is what you are after.
So...
To manage content with the injected REST API:
curl -X POST /users/{userId}/images -F file=#/path/to/image.jpg
will store the image on the filesystem at `` and associate it with the user entity whose id is userId.
curl /users/{userId}/images/{contentId} -H "Accept: image/jpeg"
will fetch it again and so on...supports all CRUD methods and video streaming as well BTW!
There are a couple of getting started guides here. The reference guide for Spring Content Filesystem is here. And there is a tutorial video here. The coding bit starts about 1/2 way through.
A couple of additional points:
- if you use the Spring Boot Starters then you don't need the #Configuration for the most part.
- Just like Spring Data is an abstraction, so is Spring Content so you aren't limited to storing your images on the filesystem. You could store them as BLOBs in the database, or in cloud storage like S3.
HTH
I suggest you can use #Lob instead to save file data (fileData variable below)
#Entity
public class File {
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
private String fileName;
private String fileType;
#Lob
private byte[] fileData;
}
Because of history reason, we must adapt old sys. This is the xml request:
<?xml version="1.0" encoding="UTF-8"?>
<User>
<Age>18</Age>
<Gender>Male</Gender>
<PassWord>string</PassWord>
<UserName>
<FirstName>Maxwell</FirstName>
<LastName>xxx</LastName>
<MiddleName>string</MiddleName>
</UserName>
</User>
Now, we need to implemente the consumer-service with springboot. But it didn't support payload case insensitive when mapping to bean.
#Data
public class User{
private Username UserName;
private String PassWord;
private int Age;
private String Gender;
#Data
class UserName{
private String LastName;
private String MiddleName;
private String FirstName;
}
}
Result:
I know I could use #XmlElement, but it will have some issue when integrate with swagger #annotation.
I would like to map the XML payload to Java Object directly using #RequestBody Spring annotation. My question here is How do I make the java Object to map to the fields ignoring the case.
I found the way to handle this issue. We could import jackson-dataformat-xml into pom.xml
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.6</version>
</dependency>
If don’t use jackson-dataformat-xml, SpringBoot automatically uses JAXB of JDK to convert XML. It will case sensitive.
Call .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true) to the ObjectMapper to be case-insensitive.
I am looking out for some help related with spring boot data using Cassandra database.
I have following dependencies in my pom.xml.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>2.1.10.3</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-mapping</artifactId>
<version>2.1.10.3</version>
</dependency>
The table structure looks like:
#Table(value = "TEST_ORDERS")
public class OrderDTO {
#PrimaryKey
#Column(value = "email")
private String emailId;
#Column(value = "order_id")
private int orderId;
#Column(value = "creation_date")
private Timestamp creationDate;
#Column(value = "discount_total")
private double discountTotal;
#Column(name = "shipments")
//This is a UDT type
private Set<ShippingDetails> shipments;
//getters and setters here
}
The ShippingDetails object is a UDT with following declartion and i defined as a frozen collection in the cassandra CQL sripts
#UDT(name = "shipping", keyspace = "mc_checkout")
public class ShippingDetails {
#Field(name = "name")
private FullName name;
#Field(name = "quantity_shipped")
private int quantityShipped;
#Field(name = "shipping_address")
private CheckoutAddress shippingAddress;
//so on
}
There is a repository created for the basic CRUD operations:
#Repository
public interface OrderRepository extends CrudRepository<OrderDTO, String> {
}
When i try to invoke findOne API of this repository in my Service class
i get below error:
Cassandra entities must have the #Table, #Persistent or #PrimaryKeyClass Annotation
Spring Data for Apache Cassandra and Datastax' Mapping are two independent tools that try to accomplish the same. Please use either one but don't mix these.
CrudRepository is a Spring Data type while #Field and #UDT are coming from Datastax Mapping.
UDT support for Spring Data for Apache Cassandra is available as of version 1.5, see reference docs. Spring Data for Apache Cassandra 1.5 requires Datastax Java Driver 3.0 or newer.
I have a spring-boot application (1.4RC1, I know it's RC, but Spring Data Redis 1.7.2 is not) where I'm using spring-boot-starter-redis.
The application uses a Spring Data Repository (CrudRepository) which should save an object (using #RedisHash annotation) with String and Boolean properties and one custom class property, which also has only Strings and Longs as properties.
When I save an object (via the repository), everything went fine and I can see all the properties in the database as I would expect.
When I want to read the data from the database (via the repository) I only get the properties from the parent object. The custom class property is null.
I would expect to get the property loaded from the database as well. As the documentation states you can write a custom converter, but since I don't need to do that, when I want to write the data, I shouldn't need to write a reading converter as well.
I wonder if I need to annotate the custom class property, but I couldn't find anything in the documentation. Can you point me in the right direction?
The classes are as follows:
Class sample:
#Data
#EqualsAndHashCode(exclude = {"isActive", "sampleCreated", "sampleConfiguration"})
#RedisHash
public class Sample {
#Id
private String sampleIdentifier;
private Boolean isActive;
private Date sampleCreated;
private SampleConfiguration sampleConfiguration;
public Sample(String sampleIdentifier, SampleConfiguration sampleConfiguration){
this.sampleIdentifier = sampleIdentifier;
this.sampleConfiguration = sampleConfiguration;
}
}
Class SampleConfiguration:
#Data
public class SampleConfiguration {
private String surveyURL;
private Long blockingTime;
private String invitationTitle;
private String invitationText;
private String participateButtonText;
private String doNotParticipateButtonText;
private String optOutButtonText;
private Long frequencyCappingThreshold;
private Long optOutBlockingTime;
}
I added #NoArgsConstructor to my Sample class as Christoph Strobl suggested. Then the repository reads the SampleConfiguration correctly. Thanks, Christoph!
Now that I found how to use converters in an HTML SELECT in Spring Roo, I am trying to do the same in a list.
I managed to register a Converter in my ApplicationConversionServiceFactoryBean, but now I need to use it as well when displaying a list of my envities. I have the following entity :
#RooJavaBean
#RooToString
#RooEntity
public class Environment {
#NotNull
#Size(min = 2, max = 30)
private String name;
#ManyToOne
private Application application;
}
When displaying it as a list in the generated MVC, it looks like the application is displayed as a toString() and not using the registered converter.
What am I missing ?
You need to push-in refactor the Roo generated converter method to the application conversion factory bean.
Sometimes, by default toString() method is used for the conversion.
Alternatively, you can try pushing in and overriding the toString() method within the entity itself. You will have to remove the #RooToString annotation while doing this.
Cheers!!!