Skip to content

Commit c071d3d

Browse files
committed
(maint) Update documentation on how to use configuration
1 parent 1417028 commit c071d3d

File tree

3 files changed

+181
-25
lines changed

3 files changed

+181
-25
lines changed

README.md

100644100755
Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ class Person {
3030

3131
// inspect an object
3232
List<Person> people = query.getResultList();
33-
ObjectStringifier stringifier = new ObjectStringifier(people);
34-
stringifier.setMode(Mode.PROMISCUOUS);
35-
// stringifier.setBeanFactory(...);
33+
Stringify stringify = Stringify.of(people);
34+
stringify.mode(Mode.PROMISCUOUS);
35+
// stringify.beanFactory(...);
3636
assert "<Person id=15, parent=<Person id=16, parent=null, "
3737
+ "childs=[(↻)], account=⁂Lazy>, childs=[], "
38-
+ "account=⁂Lazy>".equals(stringifier.toString());
38+
+ "account=⁂Lazy>".equals(stringify.toString());
3939
```
4040

4141
### In Quiet mode
@@ -51,11 +51,11 @@ class Person {
5151

5252
// inspect an object
5353
List<Person> people = query.getResultList();
54-
ObjectStringifier stringifier = new ObjectStringifier(people);
55-
stringifier.setMode(Mode.QUIET);
54+
Stringify stringify = Stringify.of(people);
55+
stringify.mode(Mode.QUIET);
5656
assert "<Person id=15, parent=<Person id=16, parent=null, "
5757
+ "childs=[(↻)], account=⁂Lazy>, childs=[], "
58-
+ "account=⁂Lazy>".equals(stringifier.toString());
58+
+ "account=⁂Lazy>".equals(stringify.toString());
5959
```
6060

6161
## Features
@@ -83,9 +83,100 @@ Stringify Object for Java is designed to inspect complex objects that can have c
8383
* Lombok can't **detect cycles** is object graph, which implies `StackOverflowException` being thrown in that case
8484
* Lombok can't detect a **lazy loaded entities**, which leads to force loading it from JPA by invoking SQL statements. It's typical **n+1 problem**, but with nasty consequences - your `toString()` method is invoking SQL without your knowledge!!
8585

86+
## Configuration
87+
88+
Configuration is done in two ways: declarative - using Java's service loader mechanism,
89+
and programmatic.
90+
91+
### Configuration using Service Loader
92+
93+
A `Configurator` interface is intended to be implemented in user code, and assigned
94+
to [Service Loader](https://www.baeldung.com/java-spi) mechanism.
95+
96+
To do that, create on your classpath, a file:
97+
98+
`/META-INF/services/pl.wavesoftware.utils.stringify.spi.Configurator`
99+
100+
In that file, place a fully qualified class name of your class that implements
101+
`Configurator` interface. It should be called first time you use an Stringify to inspect
102+
an object:
103+
104+
```
105+
# classpath:/META-INF/services/pl.wavesoftware.utils.stringify.spi.Configurator
106+
org.acmecorp.StringifyConfigurator
107+
```
108+
109+
Then implement that class in your code:
110+
111+
```java
112+
package org.acmecorp;
113+
114+
import pl.wavesoftware.utils.stringify.api.Configuration;
115+
import pl.wavesoftware.utils.stringify.spi.Configurator;
116+
117+
public final class StringifyConfigurator implements Configurator {
118+
119+
@Override
120+
public void configure(Configuration configuration) {
121+
configuration.beanFactory(new SpringBeanFactory());
122+
}
123+
}
124+
```
125+
126+
with example Spring based BeanFactory:
127+
128+
```java
129+
package org.acmecorp;
130+
131+
import org.springframework.context.event.ContextRefreshedEvent;
132+
import org.springframework.context.ApplicationContext;
133+
import org.springframework.context.annotation.Configuration;
134+
135+
import pl.wavesoftware.utils.stringify.spi.BeanFactory;
136+
import pl.wavesoftware.utils.stringify.spi.BootingAware;
137+
138+
@Configuration
139+
class SpringBeanFactory implements BeanFactory, BootingAware {
140+
private static ApplicationContext context;
141+
142+
@EventListener(ContextRefreshedEvent.class)
143+
void onRefresh(ContextRefreshedEvent event) {
144+
SpringBeanFactory.context = event.getApplicationContext();
145+
}
146+
147+
@Override
148+
public <T> T create(Class<T> contractClass) {
149+
return SpringBeanFactory.context.getBean(contractClass);
150+
}
151+
152+
@Override
153+
public boolean isReady() {
154+
return SpringBeanFactory.context != null;
155+
}
156+
}
157+
```
158+
159+
### Programmatic configuration
160+
161+
You can also fine tune you configuration on instance level - using methods available at
162+
`Stringify` interface:
163+
164+
```java
165+
// given
166+
BeanFactory beanFactory = createBeanFactory();
167+
Person person = createPerson();
168+
169+
// then
170+
Stringify stringifier = Stringify.of(person);
171+
stringifier
172+
.beanFactory(beanFactory)
173+
.mode(Mode.QUIET)
174+
.stringify();
175+
```
176+
86177
## Dependencies
87178

88-
* Java >= 7
179+
* Java >= 8
89180
* [EID Exceptions](https://github.com/wavesoftware/java-eid-exceptions) library
90181

91182
### Contributing

src/main/java/pl/wavesoftware/utils/stringify/api/Configuration.java

100644100755
Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,25 @@
2222
/**
2323
* A interface that represents a configuration options for this library
2424
* <p>
25-
* To use that one should implement {@link Configurator} with Java's
26-
* {@link java.util.ServiceLoader ServiceLoader} mechanism.
27-
* <p>
28-
* To do that, create on your classpath, a file:
29-
* <pre>META-INF/services/pl.wavesoftware.utils.stringify.spi.Configurator</pre>
25+
* To configure this library you either use:
26+
* <ul>
27+
* <li>declarative way - using Java's {@link java.util.ServiceLoader ServiceLoader}
28+
* mechanism,</li>
29+
* <li>or programmatic way.</li>
30+
* </ul>
3031
*
3132
* <p>
32-
* In that file, place a fully qualified class name of your class that implements
33-
* {@link Configurator} interface. It should be called first time you
34-
* use an {@link pl.wavesoftware.utils.stringify.Stringify Stringify} to inspect
35-
* an object.
33+
* On how to use declarative way consult Javadoc of {@link Configurator}.
34+
* <p>
35+
* To use programmatic way, just invoke configuration methods on instance of
36+
* {@link pl.wavesoftware.utils.stringify.Stringify Stringify} object.
37+
* <p>
38+
* {@link BeanFactory} interface can be used to create instances of classes, declared
39+
* in annotations used to define inspection rules.
3640
*
3741
* @see Configurator
42+
* @see BeanFactory
43+
* @see pl.wavesoftware.utils.stringify.Stringify Stringify
3844
* @author <a href="mailto:krzysztof.suszynski@wavesoftware.pl">Krzysztof Suszynski</a>
3945
* @since 2.0.0
4046
*/

src/main/java/pl/wavesoftware/utils/stringify/spi/Configurator.java

100644100755
Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,78 @@
1818

1919
import pl.wavesoftware.utils.stringify.api.Configuration;
2020

21+
import java.util.ServiceLoader;
22+
2123
/**
22-
* An interface to implement as a Java's {@link java.util.ServiceLoader ServiceLoader}
23-
* mechanism.
24+
* A {@code Configurator} interface is intended to be implemented in user code, and
25+
* assigned to <a href="https://www.baeldung.com/java-spi">Service Loader</a> mechanism.
2426
* <p>
2527
* To do that, create on your classpath, a file:
26-
* <pre>META-INF/services/pl.wavesoftware.utils.stringify.spi.Configurator</pre>
2728
*
28-
* <p>
29+
* <pre>
30+
* /META-INF/services/pl.wavesoftware.utils.stringify.spi.Configurator
31+
* </pre>
32+
*
2933
* In that file, place a fully qualified class name of your class that implements
30-
* {@link Configurator} interface. It should be called first time you
31-
* use an {@link pl.wavesoftware.utils.stringify.Stringify Stringify} to inspect
32-
* an object.
33-
*
34+
* {@code Configurator} interface. It should be called first time you use an Stringify
35+
* to inspect an object:
36+
*
37+
* <pre>
38+
* # classpath:/META-INF/services/pl.wavesoftware.utils.stringify.spi.Configurator
39+
* org.acmecorp.StringifyConfigurator
40+
* </pre>
41+
*
42+
* Then implement that class in your code:
43+
*
44+
* <pre>
45+
* package org.acmecorp;
46+
*
47+
* import pl.wavesoftware.utils.stringify.api.Configuration;
48+
* import pl.wavesoftware.utils.stringify.spi.Configurator;
49+
*
50+
* public final class StringifyConfigurator implements Configurator {
51+
*
52+
* &#064;Override
53+
* public void configure(Configuration configuration) {
54+
* configuration.beanFactory(new SpringBeanFactory());
55+
* }
56+
* }
57+
* </pre>
58+
*
59+
* with example Spring based BeanFactory:
60+
*
61+
* <pre>
62+
* package org.acmecorp;
63+
*
64+
* import org.springframework.context.event.ContextRefreshedEvent;
65+
* import org.springframework.context.ApplicationContext;
66+
* import org.springframework.context.annotation.Configuration;
67+
*
68+
* import pl.wavesoftware.utils.stringify.spi.BeanFactory;
69+
* import pl.wavesoftware.utils.stringify.spi.BootingAware;
70+
*
71+
* &#064;Configuration
72+
* class SpringBeanFactory implements BeanFactory, BootingAware {
73+
* private static ApplicationContext context;
74+
*
75+
* &#064;EventListener(ContextRefreshedEvent.class)
76+
* void onRefresh(ContextRefreshedEvent event) {
77+
* SpringBeanFactory.context = event.getApplicationContext();
78+
* }
79+
*
80+
* &#064;Override
81+
* public <T> T create(Class<T> contractClass) {
82+
* return SpringBeanFactory.context.getBean(contractClass);
83+
* }
84+
*
85+
* &#064;Override
86+
* public boolean isReady() {
87+
* return SpringBeanFactory.context != null;
88+
* }
89+
* }
90+
* </pre>
91+
*
92+
* @see ServiceLoader
3493
* @see Configuration
3594
* @author <a href="mailto:krzysztof.suszynski@wavesoftware.pl">Krzysztof Suszynski</a>
3695
* @since 2.0.0

0 commit comments

Comments
 (0)