I'm having some issues with Spring LocaleContextHolder.
I have the following code:
public void sendPasswordRecoverySmsAsync(String phone) {
CompletableFuture.runAsync(() -> {
sendPasswordRecoverySmsSync(phone);
});
}
public void sendPasswordRecoverySmsSync(String phone) {
User user = userDao.findByPhone(phone, User.class).orElseThrow(() -> new UserNotFoundException(phone));
log.info("User found, recovering password");
user.setUpdateTime(LocalDateTime.now());
userDao.save(user);
int otp = codesGenerator.generateOtp(user.getUpdateTime());
// Sends the SMS.
Locale locale = LocaleContextHolder.getLocale();
System.out.println("locale " + locale);
String appName = messageSource.getMessage("app.name", null, locale);
String smsContent = messageSource.getMessage("sms.password.recovery", new Object[] { otp }, locale);
Message message = new TextMessage(appName, phone, smsContent);
try {
smsClient.submitMessage(message);
} catch (NexmoClientException | IOException e) {
log.error("Error while sending recovery password message to phone number [{}]", phone, e);
throw new UserActivationException("Error while recovering password for user with phone: " + phone, e);
}
}
and this test:
#Before
public void setup() {
LocaleContextHolder.resetLocaleContext();
Mockito.when(tokenGenerator.generateOtp(Mockito.any())).thenReturn(14);
}
#Test(timeout = 3000)
public void testSendPasswordRecoverySmsAsyncError() throws Exception {
// Mocks.
LocaleContextHolder.setLocale(Locale.ENGLISH, true);
String mockPhone = "333";
User mockUser = mockModelBuilder.user(true, true);
Mockito.when(userDao.findByPhone(mockPhone, User.class)).then(r -> {
// TODO
return Optional.of(mockUser);
});
CountDownLatch latch = new CountDownLatch(1);
ArgumentCaptor<TextMessage> messageCaptor = ArgumentCaptor.forClass(TextMessage.class);
Mockito.when(smsClient.submitMessage(messageCaptor.capture())).then(r -> {
latch.countDown();
throw new NexmoClientException();
});
// Test.
service.sendPasswordRecoverySmsAsync(mockPhone);
latch.await();
// Assertions.
Assert.assertTrue(true);
TextMessage actualMessage = messageCaptor.getValue();
Assert.assertEquals("myApp", actualMessage.getFrom());
Assert.assertEquals(mockPhone, actualMessage.getTo());
Assert.assertEquals("Your password recovery code for myApp app is 14", actualMessage.getMessageBody());
}
I would expect the ouput of my test being "en" and this works properly if I launch only this one. However, when I run all my tests, the ouput is "it". This is probably either because in other tests I set an ITALIAN locale or because it's getting the system default.
But why is it getting the wrong one even when I'm resetting it explicitly?
For solely the purpose of testing such localization cases, you might just need to add the following on your test method. This will essentially mark the context Dirty and recreate it, depending on whether you mention as the context being Dirty either before or After the test execution.
#DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
#Test(timeout = 3000)
public void testSendPasswordRecoverySmsAsyncError() throws Exception {...
Please refer the documentation here
Hope this helps, as it resolved a similar problem for me.
Related
TL:DR; When running tests with different #ResourceArgs, the configuration of different tests get thrown around and override others, breaking tests meant to run with specific configurations.
So, I have a service that has tests that run in different configuration setups. The main difference at the moment is the service can either manage its own authentication or get it from an external source (Keycloak).
I firstly control this using test profiles, which seem to work fine. Unfortunately, in order to support both cases, the ResourceLifecycleManager I have setup supports setting up a Keycloak instance and returns config values that break the config for self authentication (This is due primarily to the fact that I have not found out how to get the lifecycle manager to determine on its own what profile or config is currently running. If I could do this, I think I would be much better off than using #ResourceArg, so would love to know if I missed something here).
To remedy this shortcoming, I have attempted to use #ResourceArgs to convey to the lifecycle manager when to setup for external auth. However, I have noticed some really odd execution timings and the config that ends up at my test/service isn't what I intend based on the test class's annotations, where it is obvious the lifecycle manager has setup for external auth.
Additionally, it should be noted that I have my tests ordered such that the profiles and configs shouldn't be running out of order; all the tests that don't care are run first, then the 'normal' tests with self auth, then the tests with the external auth profile. I can see this working appropriately when I run in intellij, and the fact I can tell the time is being taken to start up the new service instance between the test profiles.
Looking at the logs when I throw a breakpoint in places, some odd things are obvious:
When breakpoint on an erring test (before the external-configured tests run)
The start() method of my TestResourceLifecycleManager has been called twice
The first run ran with Keycloak starting, would override/break config
though the time I would expect to need to be taken to start up keycloak not happening, a little confused here
The second run is correct, not starting keycloak
The profile config is what is expected, except for what the keycloak setup would override
When breakpoint on an external-configured test (after all self-configured tests run):
The start() method has now been called 4 times; appears that things were started in the same order as before again for the new run of the app
There could be some weirdness in how Intellij/Gradle shows logs, but I am interpreting this as:
Quarkus initting the two instances of LifecycleManager when starting the app for some reason, and one's config overrides the other, causing my woes.
The lifecycle manager is working as expected; it appropriately starts/ doesn't start keycloak when configured either way
At this point I can't tell if I'm doing something wrong, or if there's a bug.
Test class example for self-auth test (same annotations for all tests in this (test) profile):
#Slf4j
#QuarkusTest
#QuarkusTestResource(TestResourceLifecycleManager.class)
#TestHTTPEndpoint(Auth.class)
class AuthTest extends RunningServerTest {
Test class example for external auth test (same annotations for all tests in this (externalAuth) profile):
#Slf4j
#QuarkusTest
#TestProfile(ExternalAuthTestProfile.class)
#QuarkusTestResource(value = TestResourceLifecycleManager.class, initArgs = #ResourceArg(name=TestResourceLifecycleManager.EXTERNAL_AUTH_ARG, value="true"))
#TestHTTPEndpoint(Auth.class)
class AuthExternalTest extends RunningServerTest {
ExternalAuthTestProfile extends this, providing the appropriate profile name:
public class NonDefaultTestProfile implements QuarkusTestProfile {
private final String testProfile;
private final Map<String, String> overrides = new HashMap<>();
protected NonDefaultTestProfile(String testProfile) {
this.testProfile = testProfile;
}
protected NonDefaultTestProfile(String testProfile, Map<String, String> configOverrides) {
this(testProfile);
this.overrides.putAll(configOverrides);
}
#Override
public Map<String, String> getConfigOverrides() {
return new HashMap<>(this.overrides);
}
#Override
public String getConfigProfile() {
return testProfile;
}
#Override
public List<TestResourceEntry> testResources() {
return QuarkusTestProfile.super.testResources();
}
}
Lifecycle manager:
#Slf4j
public class TestResourceLifecycleManager implements QuarkusTestResourceLifecycleManager {
public static final String EXTERNAL_AUTH_ARG = "externalAuth";
private static volatile MongodExecutable MONGO_EXE = null;
private static volatile KeycloakContainer KEYCLOAK_CONTAINER = null;
private boolean externalAuth = false;
public synchronized Map<String, String> startKeycloakTestServer() {
if(!this.externalAuth){
log.info("No need for keycloak.");
return Map.of();
}
if (KEYCLOAK_CONTAINER != null) {
log.info("Keycloak already started.");
} else {
KEYCLOAK_CONTAINER = new KeycloakContainer()
// .withEnv("hello","world")
.withRealmImportFile("keycloak-realm.json");
KEYCLOAK_CONTAINER.start();
log.info(
"Test keycloak started at endpoint: {}\tAdmin creds: {}:{}",
KEYCLOAK_CONTAINER.getAuthServerUrl(),
KEYCLOAK_CONTAINER.getAdminUsername(),
KEYCLOAK_CONTAINER.getAdminPassword()
);
}
String clientId;
String clientSecret;
String publicKey = "";
try (
Keycloak keycloak = KeycloakBuilder.builder()
.serverUrl(KEYCLOAK_CONTAINER.getAuthServerUrl())
.realm("master")
.grantType(OAuth2Constants.PASSWORD)
.clientId("admin-cli")
.username(KEYCLOAK_CONTAINER.getAdminUsername())
.password(KEYCLOAK_CONTAINER.getAdminPassword())
.build();
) {
RealmResource appsRealmResource = keycloak.realms().realm("apps");
ClientRepresentation qmClientResource = appsRealmResource.clients().findByClientId("quartermaster").get(0);
clientSecret = qmClientResource.getSecret();
log.info("Got client id \"{}\" with secret: {}", "quartermaster", clientSecret);
//get private key
for (KeysMetadataRepresentation.KeyMetadataRepresentation curKey : appsRealmResource.keys().getKeyMetadata().getKeys()) {
if (!SIG.equals(curKey.getUse())) {
continue;
}
if (!"RSA".equals(curKey.getType())) {
continue;
}
String publicKeyTemp = curKey.getPublicKey();
if (publicKeyTemp == null || publicKeyTemp.isBlank()) {
continue;
}
publicKey = publicKeyTemp;
log.info("Found a relevant key for public key use: {} / {}", curKey.getKid(), publicKey);
}
}
// write public key
// = new File(TestResourceLifecycleManager.class.getResource("/").toURI().toString() + "/security/testKeycloakPublicKey.pem");
File publicKeyFile;
try {
publicKeyFile = File.createTempFile("oqmTestKeycloakPublicKey",".pem");
// publicKeyFile = new File(TestResourceLifecycleManager.class.getResource("/").toURI().toString().replace("/classes/java/", "/resources/") + "/security/testKeycloakPublicKey.pem");
log.info("path of public key: {}", publicKeyFile);
// if(publicKeyFile.createNewFile()){
// log.info("created new public key file");
//
// } else {
// log.info("Public file already exists");
// }
try (
FileOutputStream os = new FileOutputStream(
publicKeyFile
);
) {
IOUtils.write(publicKey, os, UTF_8);
} catch (IOException e) {
log.error("Failed to write out public key of keycloak: ", e);
throw new IllegalStateException("Failed to write out public key of keycloak.", e);
}
} catch (IOException e) {
log.error("Failed to create public key file: ", e);
throw new IllegalStateException("Failed to create public key file", e);
}
String keycloakUrl = KEYCLOAK_CONTAINER.getAuthServerUrl().replace("/auth", "");
return Map.of(
"test.keycloak.url", keycloakUrl,
"test.keycloak.authUrl", KEYCLOAK_CONTAINER.getAuthServerUrl(),
"test.keycloak.adminName", KEYCLOAK_CONTAINER.getAdminUsername(),
"test.keycloak.adminPass", KEYCLOAK_CONTAINER.getAdminPassword(),
//TODO:: add config for server to talk to
"service.externalAuth.url", keycloakUrl,
"mp.jwt.verify.publickey.location", publicKeyFile.getAbsolutePath()
);
}
public static synchronized void startMongoTestServer() throws IOException {
if (MONGO_EXE != null) {
log.info("Flapdoodle Mongo already started.");
return;
}
Version.Main version = Version.Main.V4_0;
int port = 27018;
log.info("Starting Flapdoodle Test Mongo {} on port {}", version, port);
IMongodConfig config = new MongodConfigBuilder()
.version(version)
.net(new Net(port, Network.localhostIsIPv6()))
.build();
try {
MONGO_EXE = MongodStarter.getDefaultInstance().prepare(config);
MongodProcess process = MONGO_EXE.start();
if (!process.isProcessRunning()) {
throw new IOException();
}
} catch (Throwable e) {
log.error("FAILED to start test mongo server: ", e);
MONGO_EXE = null;
throw e;
}
}
public static synchronized void stopMongoTestServer() {
if (MONGO_EXE == null) {
log.warn("Mongo was not started.");
return;
}
MONGO_EXE.stop();
MONGO_EXE = null;
}
public synchronized static void cleanMongo() throws IOException {
if (MONGO_EXE == null) {
log.warn("Mongo was not started.");
return;
}
log.info("Cleaning Mongo of all entries.");
}
#Override
public void init(Map<String, String> initArgs) {
this.externalAuth = Boolean.parseBoolean(initArgs.getOrDefault(EXTERNAL_AUTH_ARG, Boolean.toString(this.externalAuth)));
}
#Override
public Map<String, String> start() {
log.info("STARTING test lifecycle resources.");
Map<String, String> configOverride = new HashMap<>();
try {
startMongoTestServer();
} catch (IOException e) {
log.error("Unable to start Flapdoodle Mongo server");
}
configOverride.putAll(startKeycloakTestServer());
return configOverride;
}
#Override
public void stop() {
log.info("STOPPING test lifecycle resources.");
stopMongoTestServer();
}
}
The app can be found here: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/open-qm-base-station
The tests are currently failing in the ways I am describing, so feel free to look around.
Note that to run this, you will need to run ./gradlew build publishToMavenLocal in https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/libs/open-qm-core to install a dependency locally.
Github issue also tracking this: https://github.com/quarkusio/quarkus/issues/22025
Any use of #QuarkusTestResource() without restrictToAnnotatedClass set to true, means that the QuarkusTestResourceLifecycleManager will be applied to all tests no matter where the annotation is placed.
Hope restrictToAnnotatedClass will solve the problem.
I am working on a web_application sing Java,servlets,JSP and using apache Tomcat as application server
What I have done
i have created a UI where user is selecting mail Ids (they can select more than one)
And when user is clicking on send button i am triggering my java class and sending the mail
Now What i have to do
Now i have to do this dynamically,every night at 12:00 O'clock i have to send mail to some particular users
User to whom i have to send mail i am getting that mail id from login query so that is not an issue
I just want to know how can I send mail when it is midnight 12:00 O'clock
Codding I have done till now
servlet class
public class EmailSendingServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private String host;
private String port;
private String user;
private String pass;
public void init() {
ServletContext context = getServletContext();
host = context.getInitParameter("host");
port = context.getInitParameter("port");
user = context.getInitParameter("user");
pass = context.getInitParameter("pass");
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String recipient = request.getParameter("To"); // this i will get from login query
String subject = request.getParameter("subject");//this i can define manually
String content = request.getParameter("content");//same for this also
String resultMessage = "";
try {
EmailUtility.sendEmail(host, port, user, pass, recipient, subject,
content);
resultMessage = "The e-mail was sent successfully";
} catch (Exception ex) {
ex.printStackTrace();
resultMessage = "There were an error: " + ex.getMessage();
}
}
}
Java Utility classs
public class EmailUtility {
public static void sendEmail(String host, String port, final String userName, final String password,
String toAddress, String subject, String message) throws AddressException, MessagingException {
Properties properties = new Properties();
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.port", port);
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.starttls.enable", "true");
Session session = Session.getDefaultInstance(properties, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, password);
}
});
session.setDebug(false);
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(userName));
if (toAddress!= null) {
List<String> emails = new ArrayList<>();
if (toAddress.contains(",")) {
emails.addAll(Arrays.asList(toAddress.split(",")));
} else {
emails.add(toAddress);
}
Address[] to = new Address[emails.size()];
int counter = 0;
for(String email : emails) {
to[counter] = new InternetAddress(email.trim());
counter++;
}
msg.setRecipients(Message.RecipientType.TO, to);
}
msg.setSubject(subject);
msg.setSentDate(new Date());
msg.setText(message);
Transport.send(msg);
}
}
You can use a ScheduledExecutorService for handling this in "plain" Java:
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
int count = 0;
Runnable task = () -> {
count++;
System.out.println(count);
};
ScheduledFuture<?> scheduledFuture = ses.scheduleAtFixedRate(task, 12, TimeUnit.HOURS);
There is also a method for using an initial delay, but you can read more here:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
For your use case:
Introduce a new class EmailSendJobUtil:
public class EmailSendUtil {
public void createAndSubmitSheduledJob() {
ScheduledExecutorService ses = Executors.sheduledThreadPool(1);
ScheduledFuture<> sheduledFuture = ses.sheduleAtFixedRate(EmailUtility.sendMail(), 12, TimeUnit.HOURS);
}
}
However, you will get troubles with your code structure. Try to introduce a method in your EmailUtility that encapsulates the automatated sending of mails.
Introduce a repository for saving to which users you have to send mails automatically and read this data in the new method that only handles the automatic sending. You could do something like this:
public class MailJobRepository {
private List<MailJob> jobs;
void add();
void remove();
List<> getJobs();
}
And in your EmailUtility introduce a new method:
public void sendAutomatedEmails() {
jobRepository.getJobs().foreach(job -> {
sendMail(job.getToAddress(), job.getSubject(), job.getMessage());
});
}
Then you can shedule this new method and you have splitted your code into logical seperate parts.
Just a little hint:
String host, String port, final String userName, final String password
This is data for your "side" of the email sending and should not be passed as a method parameter. You can save this data into your EmailUtility class.
In java the scheduler is used to schedule a thread or task that executes at a certain period of time or periodically at a fixed interval. There are multiple ways to schedule a task in Java :
java.util.TimerTask
java.util.concurrent.ScheduledExecutorService
Quartz Scheduler
org.springframework.scheduling.TaskScheduler
For pure java implementation without any framework usage, using ScheduledExecutorService running a task at certain periods:
public void givenUsingExecutorService_whenSchedulingRepeatedTask_thenCorrect()
throws InterruptedException {
TimerTask repeatedTask = new TimerTask() {
public void run() {
EmailUtility.sendEmail(host, port, user, pass, recipient,object,content);
System.out.println("The e-mail was sent successfully");
}
};
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));
ZonedDateTime nextRun = now.withHour(5).withMinute(0).withSecond(0);
if(now.compareTo(nextRun) > 0)
nextRun = nextRun.plusDays(1);
Duration duration = Duration.between(now, nextRun);
long initalDelay = duration.getSeconds();
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(repeatedTask,
initalDelay,
TimeUnit.DAYS.toSeconds(1),
TimeUnit.SECONDS);
executor.shutdown();
}
You should take a look to isocline's Clockwork it's a java process engine. It is capable of coding various functions more efficiently than Quartz, and has specific execution function.
I try to write a test of pubsub:
#Test
public void sendTopic() throws Exception {
CustomSubscriber customSubscriber = new CustomSubscriber();
customSubscriber.startAndWait();
CustomPublisher customPublisher = new CustomPublisher();
customPublisher.publish("123");
}
and:
public CustomSubscriber() {
this.subscriptionName = SubscriptionName.create(SdkServiceConfig.s.GCP_PROJECT_ID, SdkServiceConfig.s.TOPIC_ID );
this.receiveMsgAction = (message, consumer) -> {
// handle incoming message, then ack/nack the received message
System.out.println("Id : " + message.getMessageId());
System.out.println("Data : " + message.getData().toStringUtf8());
consumer.ack();
};
this.afterStopAction = new ApiFutureEmpty();
}
// [TARGET startAsync()]
public void startAndWait() throws Exception {
Subscriber subscriber = createSubscriberWithCustomCredentials();
subscriber.startAsync();
// Wait for a stop signal.
afterStopAction.get();
subscriber.stopAsync().awaitTerminated();
}
and:
public ApiFuture<String> publish(String message) throws Exception {
ByteString data = ByteString.copyFromUtf8(message);
PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(data).build();
ApiFuture<String> messageIdFuture = publisher.publish(pubsubMessage);
ApiFutures.addCallback(messageIdFuture, new ApiFutureCallback<String>() {
public void onSuccess(String messageId) {
System.out.println("published with message id: " + messageId);
}
public void onFailure(Throwable t) {
System.out.println("failed to publish: " + t);
}
});
return messageIdFuture;
}
/**
* Example of creating a {#code Publisher}.
*/
// [TARGET newBuilder(TopicName)]
// [VARIABLE "my_project"]
// [VARIABLE "my_topic"]
public void createPublisher(String projectId, String topicId) throws Exception {
TopicName topic = TopicName.create(projectId, topicId);
try {
publisher = createPublisherWithCustomCredentials(topic);
} finally {
// When finished with the publisher, make sure to shutdown to free up resources.
publisher.shutdown();
}
}
When i run the code i get this error:
Caused by: io.grpc.StatusRuntimeException: NOT_FOUND: Resource not found (resource=add-partner-request).
What am i missing?
Whatever entity is named "add-partner-request" was not successfully created or does not belong to the project. If "add-partner-request" is the topic, then you actually need to create the topic; the line TopicName.create(projectId, topicId) is not sufficient for creating the topic itself. Typically, one would create the topic in the Cloud Pub/Sub portion of the Cloud console or via a gcloud command, e.g.,
gcloud pubsub topics create add-partner-request
Ensure that the project you are logged into in the console is the one used in the code. You should also set the project explicitly when creating the topic via the --project flag or verify that the default project is the correct one:
gcloud config list --format='text(core.project)'
For tests, it is typical to create and delete in code. For example, to create a topic:
Topic topic = null;
ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
TopicAdminClient topicAdminClient = TopicAdminClient.create();
try {
topic = topicAdminClient.createTopic(topicName);
} catch (APIException e) {
System.out.println("Issue creating topic!");
}
If "add-partner-request" is the subscription name, then the same things apply. The gcloud command would change a bit:
gcloud pubsub subscriptions create add-partner-request --topic=<topic name>
The command to create the subscription in Java would be as follows:
Subscription subscription = null;
ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
ProjectSubscriptionName subscriptionName = ProjectSubscriptionName.of(projectId, subscriptionId);
SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create();
try {
subscription = subscriptionAdminClient.createSubscription(
subscriptionName, topicName, PushConfig.newBuilder().build(), 600);
} catch (APIException e) {
System.out.println("Issue creating topic!");
}
I'm assuming TOPIC_ID is the name of your topic; you actually need to reference a subscription. You can easily create a subscription from the GCP console, then reference that name in the SubscriptionName.create(project,yoursubscriptionname)
I think that you forget to create a topic inside your project with the following name "add-partner-request".
You can create it using the following code:
try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
// projectId <= unique project identifier, eg. "my-project-id"
TopicName topicName = TopicName.create(projectId, "add-partner-request");
Topic topic = topicAdminClient.createTopic(topicName);
return topic;
}
I try to exclude a stop from routing through the code.
I create gtfs realtime Alert
public class ServiceAlertStop {
GtfsRealtime.FeedMessage feedMessage;
public GtfsRealtime.FeedMessage config(){
GtfsRealtime.FeedMessage.Builder feedMessageBuilder =
GtfsRealtime.FeedMessage.newBuilder();
GtfsRealtime.FeedHeader.Builder header =
GtfsRealtime.FeedHeader.newBuilder();
header.setTimestamp(System.currentTimeMillis());
header.setIncrementality(GtfsRealtime.FeedHeader.
Incrementality.FULL_DATASET);
header.setGtfsRealtimeVersion("1.0");
feedMessageBuilder.setHeader(header);
GtfsRealtime.FeedEntity.Builder entity =
GtfsRealtime.FeedEntity.newBuilder();
entity.setId("0");
GtfsRealtime.Alert.Builder alert = GtfsRealtime.Alert.newBuilder();
alert.setCause(GtfsRealtime.Alert.Cause.UNKNOWN_CAUSE);
alert.setEffect(GtfsRealtime.Alert.Effect.STOP_MOVED);
GtfsRealtime.TimeRange.Builder activePeriod =
alert.addActivePeriodBuilder();
activePeriod.setStart(System.currentTimeMillis());
activePeriod.setEnd(System.currentTimeMillis() + 172800000);
GtfsRealtime.TranslatedString.Builder translatedString =
GtfsRealtime.TranslatedString.newBuilder();
GtfsRealtime.TranslatedString.Translation.Builder translation =
GtfsRealtime.TranslatedString.Translation.newBuilder();
translation.setLanguage("en");
translation.setText("Stop is closed!");
translatedString.addTranslation(translation);
alert.setDescriptionText(translatedString);
alert.setHeaderText(translatedString);
GtfsRealtime.EntitySelector.Builder entitySelector =
alert.addInformedEntityBuilder();
entitySelector.setStopId("22126");
entity.setAlert(alert);
feedMessageBuilder.addEntity(entity);
feedMessage = feedMessageBuilder.build();
return feedMessage;
}
public void run(Graph graph){
AlertsUpdateHandler updateHandler = new AlertsUpdateHandler();
updateHandler.setEarlyStart(1);
updateHandler.setFeedId("1");
updateHandler.setAlertPatchService(new AlertPatchServiceImpl(graph));
updateHandler.setFuzzyTripMatcher(new
GtfsRealtimeFuzzyTripMatcher(graph.index));
updateHandler.update(feedMessage);
}
}
ASCII representation of an my Alert
header {
gtfs_realtime_version: "1.0"
incrementality: FULL_DATASET
timestamp: 1493520112381
}
entity {
id: "0"
alert {
active_period {
start: 1493520112415
end: 1493692912415
}
informed_entity {
stop_id: "22126"
}
cause: UNKNOWN_CAUSE
effect: STOP_MOVED
header_text {
translation {
text: "Stop is closed!"
language: "en"
}
}
description_text {
translation {
text: "Stop is closed!"
language: "en"
}
}
}
}
Then I load it in otp after the graph is built, in class OTPMain.java
ServiceAlertStop serviceAlertStop = new ServiceAlertStop();
serviceAlertStop.config();
serviceAlertStop.run(graphService.getRouter().graph);
After that i don't receive error, but when i begin planner trip this stop (22126) also exist in new route(( I need that otp don't use this stop. Is it possible to exclude stops from routing through the code?
If you use the OpenTripPlanner API to do your trip planning, there is a 'bannedStops' and 'bannedStopsHard' parameter you can set in the plan API call that will force the router to ignore a stop.
I am new to FIX. I have a FIX message:
8=FIX.4.4|9=122|35=D|34=215|49=CLIENT12|52=20100225-19:41:57.316|56=B|1=Marcel|11=13346|21=1|40=2|44=5|54=1|59=0|60=20100225-19:39:52.020|10=072|
and I am using quickfixJ.
Here is my class code:
public String getYear(Message aMessage, SessionID aSessionID){
try {
crack(aMessage, aSessionID);
} catch (Exception e) {
e.printStackTrace();
}
String year = String.valueOf(mUTCCal.get(Calendar.YEAR));
String begin = String.valueOf(BeginString);
return year + " " + begin;
}
and when I call this method I 2012 null
I tried all sorts of methods for different fields and I get null. I am confused about why I do not get null for the date and how do I make it interpret correctly the other fields?
quickfix.fix44.NewOrderSingle message;
message = new quickfix.fix44.NewOrderSingle();
SessionID session = new SessionID("beginString", "senderCompID", "targetCompID");
MyApp app = new MyApp("", "", "");
String result = app.myMessage(message, session);
System.out.println(result);
I do not understand where to input the string I have (up top) into message
public void onMessage(Message message, SessionID sessionID) throws FieldNotFound {
Header header = message.getHeader();
String FIX = header.getString(8);
System.out.println(FIX);
}
public void onMessage(quickfix.fix44.NewOrderSingle message, SessionID sessionID) throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
Header header = message.getHeader();
String FIX = header.getString(8);
String a = message.getString(1);
System.out.println(a);
System.out.println(FIX);}
In order to correctly get and parse FIX messages via QuickFIX, you must:
Create your Application: http://www.quickfixengine.org/quickfix/doc/html/application.html
Implement FromApp(Message message, SessionID sessionID) method
Implement the cracked method for ALL your message types you will receive from your counterparty
The FromApp method can be very simple:
public void fromApp(Message message, SessionID sessionID)
{
crack(message, sessionID);
}
Now, in your example you have a message FIX 4.4 of type 35=D [NewOrderSingle]
Therefore, you MUST implement a method as follows:
public override void onMessage(QuickFix44.NewOrderSingle message, SessionID session)
{
base.onMessage(message, session);
}
Now into your method you can easily work with all the fields you need:
public override void onMessage(QuickFix44.NewOrderSingle message, SessionID session)
{
base.onMessage(message, session);
ClOrdID ordid = new ClOrdID();
message.get(ordid);
}
Please also take a look here: http://www.quickfixengine.org/quickfix/doc/html/receiving_messages.html