Project

General

Profile

1
package eu.dnetlib.services;
2

    
3
import java.io.File;
4
import java.lang.annotation.Annotation;
5
import java.util.ArrayList;
6
import java.util.HashMap;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.UUID;
10

    
11
import javax.annotation.PostConstruct;
12

    
13
import org.apache.commons.logging.Log;
14
import org.apache.commons.logging.LogFactory;
15
import org.dom4j.Element;
16
import org.springframework.beans.factory.annotation.Autowired;
17
import org.springframework.context.Lifecycle;
18
import org.springframework.web.bind.annotation.PathVariable;
19
import org.springframework.web.bind.annotation.RequestBody;
20
import org.springframework.web.bind.annotation.RequestMapping;
21
import org.springframework.web.bind.annotation.RequestMethod;
22
import org.springframework.web.bind.annotation.RequestParam;
23
import org.springframework.web.bind.annotation.RestController;
24
import org.springframework.web.client.RestTemplate;
25

    
26
import eu.dnetlib.conf.DnetGenericApplicationProperties;
27
import eu.dnetlib.enabling.annotations.DnetService;
28
import eu.dnetlib.enabling.annotations.DnetServiceType;
29
import eu.dnetlib.exceptions.DnetGenericException;
30
import eu.dnetlib.exceptions.DnetGenericRuntimeException;
31
import eu.dnetlib.services.async.AsyncClientUtils;
32
import eu.dnetlib.services.async.AsyncResponse;
33
import eu.dnetlib.services.async.HasAsyncMethods;
34
import eu.dnetlib.services.async.ResponseAck;
35
import eu.dnetlib.services.async.ResponseAck.ResponseAckStatus;
36

    
37
public abstract class BaseService implements Lifecycle {
38

    
39
	private static final Log log = LogFactory.getLog(BaseService.class);
40

    
41
	private boolean started = false;
42

    
43
	private String profileId;
44

    
45
	private String baseUrl;
46

    
47
	private Map<String, String> serviceProperties = new HashMap<>();
48

    
49
	private Map<String, String> extraProtocols = new HashMap<>();
50

    
51
	private DnetServiceType serviceType;
52

    
53
	@Autowired
54
	private DnetGenericApplicationProperties containerConfiguration;
55

    
56
	@Autowired
57
	private AsyncClientUtils asyncClientUtils;
58

    
59
	@PostConstruct
60
	public void init() throws DnetGenericException {
61

    
62
		verifyRequiredAnnotations(DnetService.class);
63
		verifyRequiredAnnotations(RestController.class);
64
		verifyRequiredAnnotations(RequestMapping.class);
65

    
66
		serviceType = getClass().getAnnotation(DnetService.class).value();
67
		baseUrl = containerConfiguration.getUrl() + getClass().getAnnotation(RequestMapping.class).value()[0];
68

    
69
		final File dir = new File(containerConfiguration.getBaseDir());
70
		if (!dir.exists()) {
71
			dir.mkdirs();
72
		}
73
	}
74

    
75
	private void verifyRequiredAnnotations(final Class<? extends Annotation> a) throws DnetGenericException {
76
		if (!getClass().isAnnotationPresent(a)) {
77
			final String message = "A required annotation is missing (@" + a.getSimpleName() + ") in class " + getClass();
78
			log.error(message);
79
			throw new DnetGenericException(message);
80
		}
81
	}
82

    
83
	@Override
84
	public void start() {
85
		log.info("Starting service " + serviceType);
86
		if (started) {
87
			log.warn("Service " + this + "already started, check bean initializations!");
88
		}
89
		started = true;
90
	}
91

    
92
	@Override
93
	public boolean isRunning() {
94
		log.debug("called isRunning " + this);
95
		return false;
96
	}
97

    
98
	@Override
99
	public void stop() {
100
		log.info("Stopping service " + this);
101
	}
102

    
103
	@RequestMapping(value = "", method = RequestMethod.GET)
104
	public ServiceRunningInstance getStatus() {
105
		return ServiceRunningInstance.newInstance(profileId, baseUrl, baseDir());
106
	}
107

    
108
	@RequestMapping(value = "async/response/{id}", method = RequestMethod.POST)
109
	public final ResponseAck asyncResponse(@PathVariable final String id, @RequestBody final AsyncResponse response) {
110
		return asyncClientUtils.processResponse(id, response) ? ResponseAck.OK : ResponseAck.IGNORED;
111
	}
112

    
113
	@RequestMapping(value = "async/method/{method}", method = RequestMethod.POST)
114
	public final String asyncMethod(@PathVariable final String method, @RequestParam final String caller, @RequestBody final String jsonParams)
115
			throws DnetGenericException {
116

    
117
		log.info("Starting async method: " + method);
118

    
119
		if (this instanceof HasAsyncMethods) {
120

    
121
			final String id = "invocation-" + UUID.randomUUID();
122
			final String url = caller + "/async/response/" + id;
123
			final RestTemplate restTemplate = new RestTemplate();
124

    
125
			new Thread(() -> {
126
				try {
127
					((HasAsyncMethods) this).processMethod(method, jsonParams, res -> restTemplate.postForObject(url, res, ResponseAckStatus.class));
128
				} catch (final Exception e) {
129
					log.error("Invocation of async method failed", e);
130
					throw new DnetGenericRuntimeException("Invocation of async method failed", e);
131
				}
132
			}).start();
133

    
134
			return id;
135

    
136
		} else {
137
			log.error("Service " + getServiceType() + " does not implement HasAsyncMethods interface");
138
			throw new DnetGenericException("Service " + getServiceType() + " does not implement HasAsyncMethods interface");
139
		}
140

    
141
	}
142

    
143
	protected String baseDir() {
144
		return containerConfiguration.getBaseDir();
145
	}
146

    
147
	public String getProfileId() {
148
		return profileId;
149
	}
150

    
151
	public void setProfileId(final String profileId) {
152
		this.profileId = profileId;
153
	}
154

    
155
	public Map<String, String> getServiceProperties() {
156
		return serviceProperties;
157
	}
158

    
159
	public List<Element> geXmlProfileSections() {
160
		return new ArrayList<>();
161
	}
162

    
163
	public void setServiceProperties(final Map<String, String> serviceProperties) {
164
		this.serviceProperties = serviceProperties;
165
	}
166

    
167
	public Map<String, String> getExtraProtocols() {
168
		return extraProtocols;
169
	}
170

    
171
	public void setExtraProtocols(final Map<String, String> extraProtocols) {
172
		this.extraProtocols = extraProtocols;
173
	}
174

    
175
	public DnetServiceType getServiceType() {
176
		return serviceType;
177
	}
178

    
179
	public void setServiceType(final DnetServiceType serviceType) {
180
		this.serviceType = serviceType;
181
	}
182

    
183
	public String getBaseUrl() {
184
		return baseUrl;
185
	}
186

    
187
	public void setBaseUrl(final String baseUrl) {
188
		this.baseUrl = baseUrl;
189
	}
190

    
191
}
(3-3/6)