1. https://letsencrypt.org/
큰 메이져 업체들에서 스폰을 하고있어 지속성이 있을것으로 예상된다.
2. https://startssl.com
2017년 1월 24일 화요일
2017년 1월 15일 일요일
2017년 1월 3일 화요일
jpa @OneToMany(mappedBy="?", fetch=FetchType.LAZY) 일때 @responsebody 오류날 경우
http://stackoverflow.com/questions/3325387/infinite-recursion-with-jackson-json-and-hibernate-jpa-issue
Since Jackson 1.6 you can use two annotations to solve the infinite recursion problem without ignoring the getters/setters during serialization:
@JsonManagedReference and @JsonBackReference.
Explanation
For Jackson to work well, one of the two sides of the relationship should not be serialized, in order to avoid the infite loop that causes your stackoverflow error.
So, Jackson takes the forward part of the reference (your
Set<BodyStat> bodyStats in Trainee class), and converts it in a json-like storage format; this is the so-called marshalling process. Then, Jackson looks for the back part of the reference (i.e. Trainee trainee in BodyStat class) and leaves it as it is, not serializing it. This part of the relationship will be re-constructed during the deserialization (unmarshalling) of the forward reference.
You can change your code like this (I skip the useless parts):
Business Object 1:
@Entity
@Table(name = "ta_trainee", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class Trainee extends BusinessObject {
@OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@Column(nullable = true)
@JsonManagedReference
private Set<BodyStat> bodyStats;
Business Object 2:
@Entity
@Table(name = "ta_bodystat", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class BodyStat extends BusinessObject {
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name="trainee_fk")
@JsonBackReference
private Trainee trainee;
Now it all should work properly.
If you want more informations, I wrote an article about Json and Jackson Stackoverflow issues on Keenformatics, my blog.
EDIT:
Another useful annotation you could check is @JsonIdentityInfo: using it, everytime Jackson serializes your object, it will add an ID (or another attribute of your choose) to it, so that it won't entirely "scan" it again everytime. This can be useful when you've got a chain loop between more interrelated objects (for example: Order -> OrderLine -> User -> Order and over again).
In this case you've got to be careful, since you could need to read your object's attributes more than once (for example in a products list with more products that share the same seller), and this annotation prevents you to do so. I suggest to always take a look at firebug logs to check the Json response and see what's going on in your code.
Sources:
- Keenformatics - How To Solve JSON infinite recursion Stackoverflow (my blog)
- Jackson References
- Personal experience
2017년 1월 2일 월요일
JPA Support Keywords inside method name
출처 : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
| Keyword | Sample | JPQL snippet |
|---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | findByFirstname,findByFirstnameIs,findByFirstnameEquals | … where x.firstname = ?1 |
Between | findByStartDateBetween | … where x.startDate between ?1 and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
LessThanEqual | findByAgeLessThanEqual | … where x.age <= ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate < ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith | findByFirstnameStartingWith | … where x.firstname like ?1(parameter bound with appended %) |
EndingWith | findByFirstnameEndingWith | … where x.firstname like ?1(parameter bound with prepended %) |
Containing | findByFirstnameContaining | … where x.firstname like ?1(parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn(Collection<Age> ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection<Age> age) | … where x.age not in ?1 |
True | findByActiveTrue() | … where x.active = true |
False | findByActiveFalse() | … where x.active = false |
IgnoreCase | findByFirstnameIgnoreCase | … where UPPER(x.firstame) = UPPER(?1) |
2016년 12월 21일 수요일
2016년 12월 20일 화요일
swagger 2 spring boot
출처 : http://heidloff.net/article/usage-of-swagger-2-0-in-spring-boot-applications-to-document-apis/
Usage of Swagger 2.0 in Spring Boot Applications to document APIs
Posted on by Niklas Heidloff
As IBM VP Angel Diaz stated in an interview on SearchCloudComputing “Swagger is the way most developers describe [REST] APIs”. With version 2.0 many important features like extensibility have been added, there is a big community and many developers are using it by now. Additionally there is work going on to create an open governance model around the Swagger specification under the Linux Foundation as part of the Open API Initiative.
What I like most about Swagger is the ability to document APIs directly in the (Java) source code via annotations so that documentation and actual API implementations are not out of synch.
IBM uses Swagger for the API documentation of several products and services internally. Furthermore the API management service in IBM Bluemix can import Swagger 2.0 definitions to manage your APIs easily.
The Java Spring framework has a lot of traction in the enterprise community these days. In order to use Swagger in Spring Boot applications I tried Springfox which is not part of Swagger core but it integrates nicely in Spring and supports the core Swagger annotations.
Below I extended the Spring sample Building a RESTful Web Service with Swagger annotations.
First you need to define the dependencies to the Springfox and Swagger libraries, in my case in Maven.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId> <artifactId>gs-rest-service</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.0.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.2.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.2.2</version> <scope>compile</scope> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-releases</id> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-releases</id> </pluginRepository> </pluginRepositories></project> |
Then I enabled Swagger in the boot application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| package hello;import static springfox.documentation.builders.PathSelectors.regex;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import com.google.common.base.Predicate;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.service.ApiInfo;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;@SpringBootApplication@EnableSwagger2@ComponentScan("hello")public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public Docket newsApi() { return new Docket(DocumentationType.SWAGGER_2) .groupName("greetings") .apiInfo(apiInfo()) .select() .paths(regex("/greeting.*")) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Spring REST Sample with Swagger") .description("Spring REST Sample with Swagger") .contact("Niklas Heidloff") .license("Apache License Version 2.0") .version("2.0") .build(); }} |
In the controller I used Swagger annotations to document the API.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| package hello;import java.util.concurrent.atomic.AtomicLong;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiResponse;import io.swagger.annotations.ApiResponses;import io.swagger.annotations.ResponseHeader;@RestControllerpublic class GreetingController { private static final String template = "Hello, %s!"; private final AtomicLong counter = new AtomicLong(); @ApiOperation(value = "getGreeting", nickname = "getGreeting") @RequestMapping(method = RequestMethod.GET, path="/greeting", produces = "application/json") @ApiImplicitParams({ @ApiImplicitParam(name = "name", value = "User's name", required = false, dataType = "string", paramType = "query", defaultValue="Niklas") }) @ApiResponses(value = { @ApiResponse(code = 200, message = "Success", response = Greeting.class), @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 403, message = "Forbidden"), @ApiResponse(code = 404, message = "Not Found"), @ApiResponse(code = 500, message = "Failure")}) public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) { return new Greeting(counter.incrementAndGet(), String.format(template, name)); }} |
In the sample resource I documented parameters.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| package hello;import com.fasterxml.jackson.annotation.JsonProperty;import io.swagger.annotations.ApiModelProperty;public class Greeting { private final long id; private final String content; public Greeting(long id, String content) { this.id = id; this.content = content; } public long getId() { return id; } @JsonProperty(required = true) @ApiModelProperty(notes = "The name of the user", required = true) public String getContent() { return content; }} |
Here is the outcome in the API explorer.
피드 구독하기:
글 (Atom)

